- created by gloomyfish
图像处理之半调色融合
图像处理中错误扩散,抖动算法在在数字半调技术中有着重要的应用,是报纸,黑白
打印机等输出设备常常采用的技术。常见的图像半调技术有矩阵错误扩散,弗洛伊德-
斯坦德伯格错误扩散,空间填充曲线采样错误扩散等。本文借助半调算法,实现两张
图像的融合,将背景纹理融合到目标图像中,创造惊艳的图像处理效果。
算法基本思想:
读取纹理图像像素点P(x,y)与目标图像对应像素D(x,y),输入参数调节S取值范围[0~1]
根据参数S计算颜色差值cs = S * 255,假设像素值分别为P(x, y) =mv, D(x, y) = dv
则融合后的像素值pd(x, y)=255*(1-3x^2 - 2x^3)其中x = (mv - (dv - cs)/2cs)
运行效果:
背景图像分别为:
程序源代码:
package com.gloomyfish.filter.study;
import java.awt.image.BufferedImage;
/**
* A filter which uses a another image as a ask to produce a halftoning effect.
*/
public class HalftoneFilter extends AbstractBufferedImageOp {
private float softness = 0.1f;
private boolean invert;
private BufferedImage mask;
public HalftoneFilter() {
System.out.println("Stylize/Halftone...");
}
/**
* Set the softness of the effect in the range 0..1.
* @param softness the softness
* @min-value 0
* @max-value 1
*/
public void setSoftness( float softness ) {
this.softness = softness;
}
/**
* Get the softness of the effect.
* @return the softness
* @see #setSoftness
*/
public float getSoftness() {
return softness;
}
/**
* Set the halftone background image.
* @param BufferedImage maskImage
* @see #getMask
*/
public void setMask( BufferedImage maskImage ) {
this.mask = maskImage;
}
public void setInvert( boolean invert ) {
this.invert = invert;
}
public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
int width = src.getWidth();
int height = src.getHeight();
if ( dst == null )
dst = createCompatibleDestImage( src, null );
if ( mask == null )
return dst;
int maskWidth = mask.getWidth();
int maskHeight = mask.getHeight();
// scale to [0~255]
float s = 255*softness;
int[] inPixels = new int[width];
int[] maskPixels = new int[maskWidth];
for ( int y = 0; y < height; y++ ) {
getRGB( src, 0, y, width, 1, inPixels ); // get row pixels
getRGB( mask, 0, y % maskHeight, maskWidth, 1, maskPixels ); // get row pixels
for ( int x = 0; x < width; x++ ) {
int maskRGB = maskPixels[x % maskWidth];
int inRGB = inPixels[x];
if ( invert )
maskRGB ^= 0xffffff;
// start to halftone here!!
int ir = (inRGB >> 16) & 0xff;
int ig = (inRGB >> 8) & 0xff;
int ib = inRGB & 0xff;
int mr = (maskRGB >> 16) & 0xff;
int mg = (maskRGB >> 8) & 0xff;
int mb = maskRGB & 0xff;
int r = (int)(255 * (1-cubeInterpolation( ir-s, ir+s, mr )));
int g = (int)(255 * (1-cubeInterpolation( ig-s, ig+s, mg )));
int b = (int)(255 * (1-cubeInterpolation( ib-s, ib+s, mb )));
inPixels[x] = (inRGB & 0xff000000) | (r << 16) | (g << 8) | b;
}
setRGB( dst, 0, y, width, 1, inPixels );
}
return dst;
}
public static float cubeInterpolation(float a, float b, float x) {
if (x < a)
return 0;
if (x >= b)
return 1;
x = (x - a) / (b - a);
return x*x * (3 - 2*x);
}
}