图像处理之玻璃水印特效(祝大家圣诞节快乐)

简介: 图像处理之玻璃水印特效(祝大家圣诞节快乐)

基本流程:


一幅文字图像,一幅目标图像,文字将会被作为水印添加到目标图像中。最终生成


一幅带水印的目标图像。


基本思想:


首先对文字图像进行预处理,扫描它的每个像素提取文字图像的水平与垂直边缘。


完成对整个文字图像扫描以后,就得到了文字图像的水平与垂直边缘数据。关于


边缘提取可以参考这里:http://blog.csdn.net/jia20003/article/details/7562092


然你也可以选择其它算子然后扫描目标图像的每个像素,利用第一步计算出来的


边缘信息值作为权重值,计算每个像素上下左右的四个像素,然后完成插值计算


计算出输出像素,最终得到最后的玻璃水印效果


程序效果:


文字图像:

1356365745_8980.png



目标图像:


1356365792_1126.png


最终水印图像: 1356365908_5382.jpg

package com.gloomyfish.filter.study;
 
import java.awt.image.BufferedImage;
 
public class DisplaceFilter extends AbstractBufferedImageOp {
    /**
     * Treat pixels off the edge as zero.
     */
  public final static int ZERO = 0;
 
    /**
     * Clamp pixels to the image edges.
     */
  public final static int CLAMP = 1;
 
    /**
     * Wrap pixels off the edge onto the oppsoite edge.
     */
  public final static int WRAP = 2;
 
    /**
     * Clamp pixels RGB to the image edges, but zero the alpha. This prevents gray borders on your image.
     */
  public final static int RGB_CLAMP = 3;
  
  protected int edgeAction = RGB_CLAMP;
  private float amount = 1;
  private BufferedImage textImage = null;
  private int[] xmap, ymap;
  private int dw, dh;
  
  public DisplaceFilter() {
    this(RGB_CLAMP);
  }
  
  public DisplaceFilter(int edgeAction) {
    this.edgeAction = edgeAction;
  }
  
  public float getAmount() {
    return amount;
  }
 
  public void setAmount(float amount) {
    this.amount = amount;
  }
 
  public BufferedImage getTextImage() {
    return textImage;
  }
 
  public void setTextImage(BufferedImage textInputImage) {
    this.textImage = textInputImage;
  }
  
  @Override
  public BufferedImage filter(BufferedImage src, BufferedImage dest) {
    BufferedImage dm = textImage != null ? textImage : src;
        int width = src.getWidth();
        int height = src.getHeight();
        if ( dest == null )
            dest = createCompatibleDestImage( src, null );
    dw = dm.getWidth();
    dh = dm.getHeight();
    int[] inPixels = new int[width*height];
        int[] outPixels = new int[width*height];
        getRGB( src, 0, 0, width, height, inPixels );
        
    int[] textImagePixels = new int[dw*dh];
    getRGB( dm, 0, 0, dw, dh, textImagePixels );
    xmap = new int[dw*dh];
    ymap = new int[dw*dh];
    
    int i = 0;
    for ( int y = 0; y < dh; y++ ) {
      for ( int x = 0; x < dw; x++ ) {
        int rgb = textImagePixels[i];
        int r = (rgb >> 16) & 0xff;
        int g = (rgb >> 8) & 0xff;
        int b = rgb & 0xff;
        // An arbitrary scaling factor which gives a good range 
        // for "amount", 16 is another optional value
        textImagePixels[i] = (r+g+b) / 8; 
        i++;
      }
    }
 
    // it is very important pre-process, extract the edge
    i = 0;
    for ( int y = 0; y < dh; y++ ) {
      int j1 = ((y+dh-1) % dh) * dw;// row - 1
      int j2 = y*dw; // row
      int j3 = ((y+1) % dh) * dw; // row + 1
      for ( int x = 0; x < dw; x++ ) {
        int k1 = (x+dw-1) % dw; // column - 1
        int k2 = x; // column
        int k3 = (x+1) % dw; // column + 1
        xmap[i] = textImagePixels[k1+j1] + textImagePixels[k1+j2] + textImagePixels[k1+j3] - textImagePixels[k3+j1] - textImagePixels[k3+j2] - textImagePixels[k3+j3];
        ymap[i] = textImagePixels[k1+j3] + textImagePixels[k2+j3] + textImagePixels[k3+j3] - textImagePixels[k1+j1] - textImagePixels[k2+j1] - textImagePixels[k3+j1];
        i++;
      }
    }
    textImagePixels = null;
    
    // start to process input pixel here!!!!
    float[] out = new float[2];
    int srcWidth = width;
    int srcHeight = height;
    int srcWidth1 = width-1;
    int srcHeight1 = height-1;
    int outdex = 0;
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        outdex = y * width + x;
        transformInverse(x, y, out);
        int srcX = (int)Math.floor( out[0] );
        int srcY = (int)Math.floor( out[1] );
        float xWeight = out[0]-srcX;
        float yWeight = out[1]-srcY;
        int nw, ne, sw, se;
 
        if ( srcX >= 0 && srcX < srcWidth1 && srcY >= 0 && srcY < srcHeight1) {
          // Easy case, all corners are in the image
          i = srcWidth*srcY + srcX;
          nw = inPixels[i];
          ne = inPixels[i+1];
          sw = inPixels[i+srcWidth];
          se = inPixels[i+srcWidth+1];
        } else {
          // Some of the corners are off the image
          nw = getPixel( inPixels, srcX, srcY, srcWidth, srcHeight );
          ne = getPixel( inPixels, srcX+1, srcY, srcWidth, srcHeight );
          sw = getPixel( inPixels, srcX, srcY+1, srcWidth, srcHeight );
          se = getPixel( inPixels, srcX+1, srcY+1, srcWidth, srcHeight );
        }
        //双线性插值
        outPixels[outdex] = ImageMath.bilinearInterpolate(xWeight, yWeight, nw, ne, sw, se);
      }
    }
    
    // 返回最终结果
    setRGB( dest, 0, 0, width, height, outPixels );
    xmap = ymap = null;
    return dest;
  }
  
  /**
   * 
   * @param x
   * @param y
   * @param out
   */
  protected void transformInverse(int x, int y, float[] out) {
    int i = (y % dh)*dw + x % dw;
    out[0] = x + amount * xmap[i];
    out[1] = y + amount * ymap[i];
  }
  
  final private int getPixel( int[] pixels, int x, int y, int width, int height ) {
    if (x < 0 || x >= width || y < 0 || y >= height) {
      switch (edgeAction) {
      case ZERO:
      default:
        return 0;
      case WRAP:
        return pixels[(ImageMath.mod(y, height) * width) + ImageMath.mod(x, width)];
      case CLAMP:
        return pixels[(ImageMath.clamp(y, 0, height-1) * width) + ImageMath.clamp(x, 0, width-1)];
      case RGB_CLAMP:
        return pixels[(ImageMath.clamp(y, 0, height-1) * width) + ImageMath.clamp(x, 0, width-1)] & 0x00ffffff;
      }
    }
    return pixels[ y*width+x ];
  }
}

转载请务必注明!

祝大家圣诞快乐!!!

相关文章
|
移动开发 前端开发 JavaScript
童年回忆——开心消消乐(内含源码inscode一键运行)
童年回忆——开心消消乐(内含源码inscode一键运行)
|
前端开发 JavaScript
中秋之美——html+css+js制作中秋网页
中秋之美——html+css+js制作中秋网页
897 0
中秋之美——html+css+js制作中秋网页
|
前端开发 程序员
程序员也可以很浪漫,精选10个圣诞节特效及源码
最近离圣诞节不远了、整理了一些关于圣诞相关的前端特效网页设计和小游戏的代码送大家、直接上效果吧。 代码过长的 可直接预览获取 [快速预览](https://www.hereitis.cn/articleDetails/969)
程序员也可以很浪漫,精选10个圣诞节特效及源码
|
9月前
|
Python
用Pygame Zero 画矩形 (空心、实心、多个矩形、多层同心矩形、彩虹条矩形、条纹相间、随机颜色矩形、特殊效果、渐变效果)
用Pygame Zero 画矩形 (空心、实心、多个矩形、多层同心矩形、彩虹条矩形、条纹相间、随机颜色矩形、特殊效果、渐变效果)
253 40
|
11月前
CSS3制作的聚光灯下倒影文字选装动画特效源码
CSS3聚光灯下倒影文字特效是一段基于CSS3实现的聚光灯下带倒影的文字旋转动画效果代码,具有真实的视觉感,同时文字还会在旋转过程中显示出灯光的反射效果,很有意思,欢迎对此段代码感兴趣的朋友前来下载使用。
117 6
|
9月前
|
设计模式 关系型数据库
「全网最细 + 实战源码案例」设计模式——简单工厂模式
简单工厂模式是一种创建型设计模式,通过工厂类根据传入参数创建不同类型的对象,也称“静态工厂方法”模式。其结构包括工厂类、产品接口和具体产品类。优点是封装性强、代码复用性好;缺点是扩展性差,增加新产品时需修改工厂类代码,违反开闭原则。适用于对象种类较少且调用者无需关心创建细节的场景。
178 19
|
前端开发 JavaScript
会旋转的圣诞树
这篇文章介绍了如何使用HTML、CSS和JavaScript实现一个动态旋转的圣诞树效果,包括详细的实现步骤和编码实现,以及最终效果的展示。
会旋转的圣诞树
惊呆了、老铁。CSDN竟然有GitHub的加速功能????
这篇文章介绍了几种加速访问GitHub的方法,包括使用镜像网站、代理网站下载、利用CDN加速以及转入Gitee平台进行加速。作者建议,对于较大的项目推荐使用代理网站或Gitee下载,而对于较小的项目,使用CDN加速即可满足需求。
惊呆了、老铁。CSDN竟然有GitHub的加速功能????
浪漫3D圣诞树特效【附源码】Merry Christmas to My Girl !
浪漫3D圣诞树特效【附源码】Merry Christmas to My Girl !
181 1