您的位置:首页 > 其它

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

2012-12-25 00:16 375 查看
基本流程:
一幅文字图像,一幅目标图像,文字将会被作为水印添加到目标图像中。最终生成
一幅带水印的目标图像。
基本思想:
首先对文字图像进行预处理,扫描它的每个像素提取文字图像的水平与垂直边缘。
完成对整个文字图像扫描以后,就得到了文字图像的水平与垂直边缘数据。关于
边缘提取可以参考这里:/article/1391098.html
然你也可以选择其它算子然后扫描目标图像的每个像素,利用第一步计算出来的
边缘信息值作为权重值,计算每个像素上下左右的四个像素,然后完成插值计算
计算出输出像素,最终得到最后的玻璃水印效果
程序效果:
文字图像:




目标图像:




最终水印图像:




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 ]; 	} }
转载请务必注明!
祝大家圣诞快乐!!!

本文出自 “流浪的鱼” 博客,请务必保留此出处http://gloomyfish.blog.51cto.com/8837804/1400396
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: