两幅图像的融合与叠加
假设两幅图像的大小完全一致,对应的像素数组分别为A与B,对应的任意单个像素值分别是a与b,混合后的像素值为c
几种典型图像叠加操作:
1、乘法叠加
c=(ab)/255 public int modeOne(int v1,int v2){
return (v1v2)/255;
}
2、加法叠加
c=(a+b)/2 public int modeTwo(int v1,int v2){
return (v1+v2)/2;
}
3、减法叠加
c=|a-b| public int modeThree(int v1,int v2){
return Math.abs(v1-v2);
}
4、取反叠加
c=255-((255-a)(255-b)/255)——首先对各自的像素取反,然后使用乘法叠加后对得到的结果再次取反。
public int modeFour(int v1,int v2){
double p = (int)((255-v1)(255-v2));
return (int)(255-p/255);
}
5、加法取反叠加
c=255-(a+b) {(a+b)<255} | c=0 {(a+b)>=255}
public int modeFive(int v1,int v2){
int p = (int) (v1+v2);
if(p>255){
return 0;
}else{
return 255-p;
}
}
6、除法取反叠加
c=(a/(255-b))255 public int modeSix(int v1,int v2){
if(v2==255)
return 0;
double p = (v1/(255-v2))255;
return clamp((int)p);
}
主要代码如下:
package chapter5;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
/**
-
Created by LENOVO on 18-1-30.
*/
public class BlendFilter extends AbstractBufferedImageOp {
public static final int MULTIPLY_PIXEL = 1;
public static final int PLUS_PIXEL = 2;
public static final int MINUS_PIXEL = 3;
public static final int INVERSE_PIXEL = 4;
public static final int INVERSE_PLUS_PIXEL = 5;
public static final int DIVERSION_PIXEL = 6;private int mode;
File file = new File(“C:/Users/LENOVO/Desktop/rainbow.jpg”);//读取的融合图片
private BufferedImage secondImage ;
public BlendFilter(){
mode = MULTIPLY_PIXEL;//乘法叠加
try {
secondImage = ImageIO.read(file);} catch (IOException e) { e.printStackTrace(); }
}
public void setMode(int mode) {
this.mode = mode;
}
public void setSecondImage(BufferedImage secondImage) {
this.secondImage = secondImage;
}public BufferedImage filter(BufferedImage src,BufferedImage dest){
checkImages(src);
int width = src.getWidth();
int height = src.getHeight();
if(dest == null){
dest = creatCompatibleDestImage(src,null);
}
int[] input1 = new int[widthheight];//原图
int[] input2 = new int[secondImage.getWidth()secondImage.getHeight()];//第二张图
int[] outPixels = new int[widthheight];
getRGB(src,0,0,width,height,input1);
getRGB(secondImage,0,0,secondImage.getWidth(),secondImage.getHeight(),input2);
int index = 0;
int ta1 = 0,tr1 = 0,tg1 = 0,tb1 = 0;
for(int row=0;row<height;row++){
for(int col=0;col<width;col++){
index = rowwidth +col;
ta1 = (input1[index] >> 24) & 0xff;
tr1 = (input1[index] >> 16) & 0xff;
tg1 = (input1[index] >> 8) & 0xff;
tb1 = (input1[index]) & 0xff;
int rgb[] = getBlendData(tr1,tg1,tb1,input2,row,col);
outPixels[index] = (ta1 << 24) | (clamp(rgb[0]) << 16) |(clamp(rgb[1]) << 8) |clamp(rgb[2]);
}
}
setRGB(dest,0,0,width,height,outPixels);
return dest;
}//获取融合后的像素数据
private int[] getBlendData(int tr1,int tg1,int tb1,int[] input,int row,int col){
int width = secondImage.getWidth();
int height = secondImage.getHeight();
int index = row*width+col;
if(col>=width || row >=height){//
return new int[]{tr1,tg1,tb1};
}
int tr = (input[index] >> 16) & 0xff;
int tg = (input[index] >>8) & 0xff;
int tb = (input[index]) & 0xff;
int[] rgb = new int[3];if(mode == MULTIPLY_PIXEL){ rgb[0] = modeOne(tr1,tr); rgb[1] = modeOne(tg1,tg); rgb[2] = modeOne(tb1,tb); }else if(mode == PLUS_PIXEL){ rgb[0] = modeTwo(tr1,tr); rgb[1] = modeTwo(tg1,tg); rgb[2] = modeTwo(tb1,tb); }else if(mode == MINUS_PIXEL){ rgb[0] = modeThree(tr1,tr); rgb[1] = modeThree(tg1,tg); rgb[2] = modeThree(tb1,tb); }else if(mode == INVERSE_PIXEL){ rgb[0] = modeFour(tr1,tr); rgb[1] = modeFour(tg1, tg); rgb[2] = modeFour(tb1, tb); }else if(mode == INVERSE_PLUS_PIXEL){ rgb[0] = modeFive(tr1, tr); rgb[1] = modeFive(tg1, tg); rgb[2] = modeFive(tb1, tb); }else if(mode == DIVERSION_PIXEL){ rgb[0] = modeSix(tr1, tr); rgb[1] = modeSix(tg1, tg); rgb[2] = modeSix(tb1, tb); } return rgb;
}
//乘法叠加
public int modeOne(int v1,int v2){
return (v1v2)/255;
}
//加法叠加
public int modeTwo(int v1,int v2){
return (v1+v2)/2;
}
//减法叠加
public int modeThree(int v1,int v2){
return Math.abs(v1-v2);
}
//取反叠加
public int modeFour(int v1,int v2){
double p = (int)((255-v1)(255-v2));
return (int)(255-p/255);
}
//加法取反叠加
public int modeFive(int v1,int v2){
int p = (int) (v1+v2);
if(p>255){
return 0;
}else{
return 255-p;
}
}
//除法取反叠加
public int modeSix(int v1,int v2){
if(v2 == 255)
return 0;
double p = (v1/(255-v2))*255;
return clamp((int)p);
}
//判断两张图像大小是否相同
public void checkImages(BufferedImage src){
int width = src.getWidth();
int height = src.getHeight();
if(secondImage == null || secondImage.getWidth()>width || secondImage.getHeight()>height){
throw new IllegalArgumentException(“输入图片必须要大于融合的图片”);
}
}
}
主要代码如下: