如何将图像中的颜色更改为透明
How to change a color to transparent in an Image
我需要将图像中的白色更改为透明。我试过这个..
它拉光栅逐行抓取像素并用 abgr 填充第二个图像。其中 a =0 如果 rgb 值等于白色或 255 如果 rgb 值 dont.and 将它们写入第二个图像。
package color;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class ColorToAlpha {
public static void main(String[] args){
try {
BufferedImage i=ImageIO.read(ColorToAlpha.class.getResource("brown.jpg"));
JLabel jl=new JLabel();
jl.setIcon(new ImageIcon(rasterToAlpha(i,Color.white)));
JOptionPane.showConfirmDialog(null, jl);
} catch (IOException e) {}
}
public static BufferedImage rasterToAlpha(BufferedImage r,Color c){
BufferedImage bi=new BufferedImage(r.getWidth(),r.getHeight(),BufferedImage.TYPE_4BYTE_ABGR);
WritableRaster wr2=bi.getRaster();
WritableRaster wr=r.getRaster();
for(int i=0;i<r.getHeight();i++){
int[] xx=new int[4*r.getWidth()];//array for the abgr
int[] x=new int[3*r.getWidth()];//array for the bgr
wr.getPixels(0, i, r.getWidth(),1,x);//get them line by line
for(int j=0,k = 0;j<x.length;j+=3,k+=4){
if(c.equals(new Color( x[j+2], x[j+1],x[j]))){//flip bgr to rgb and check
xx[k]=0;xx[k+1]=0;xx[k+2]=0;xx[k+3]=0;//if its the same make it transparent
}
else{xx[k]=255;xx[k+1]=x[j];xx[k+2]=x[j+1];xx[k+3]=x[j+2];}//make it opaque
}
wr2.setPixels(0, i, r.getWidth(),1,xx);//write the line
}
return bi;}
}
但结果非常 funny.What 我做错了吗请帮忙。
这就是它的结局……
编辑
它肯定更好,但它是红色而不是黑色。
虽然 BufferedImage
类型是源图像的 BGR 和目标图像的 ABGR,但您从 getPixels
获得的整数实际上是在常见的 RGB 顺序中。并且 ABGR 图像期望数组按 RGBA 顺序排列。
这没有很好的记录,但是颜色是根据图像的颜色模型(RGB)而不是根据原始缓冲区顺序映射到整数的。
所有这一切的结果是,当您将 k
元素设置为 255 时,它实际上是 red 值,因此您得到 "reddened"图片。通过将源数组的 j+2
值放入目标数组的 k+3
值中,您实际上从原始图像的 blue 值中获得了 alpha 值.
这也意味着您不应该颠倒值的顺序来创建一个 Color
对象来与您的颜色进行比较。
所以这是一个为您更正的循环(请注意,我重命名了变量以使其更有意义。您真的不应该使用 r
、x
、xx
,c
等等,看不懂。格式也很重要!):
public static BufferedImage rasterToAlpha(BufferedImage sourceImage, Color origColor) {
BufferedImage targetImage = new BufferedImage(sourceImage.getWidth(),
sourceImage.getHeight(),
BufferedImage.TYPE_4BYTE_ABGR);
WritableRaster targetRaster = targetImage.getRaster();
WritableRaster sourceRaster = sourceImage.getRaster();
for (int row = 0; row < sourceImage.getHeight(); row++) {
int[] rgba = new int[4 * sourceImage.getWidth()];
int[] rgb = new int[3 * sourceImage.getWidth()];
// Get the next row of pixels
sourceRaster.getPixels(0, row, sourceImage.getWidth(), 1, rgb);
for (int i = 0, j = 0; i < rgb.length; i += 3, j += 4) {
if (origColor.equals(new Color(rgb[i], rgb[i + 1], rgb[i + 2]))) {
// If it's the same make it transparent
rgba[j] = 0;
rgba[j + 1] = 0;
rgba[j + 2] = 0;
rgba[j + 3] = 0;
} else {
rgba[j] = rgb[i];
rgba[j + 1] = rgb[i + 1];
rgba[j + 2] = rgb[i + 2];
// Make it opaque
rgba[j + 3] = 255;
}
}
// Write the line
targetRaster.setPixels(0, row, sourceImage.getWidth(), 1, rgba);
}
return targetImage;
}
package color;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class ColorToAlpha {
public static void main(String[] args){
try {
BufferedImage i=ImageIO.read(ColorToAlpha.class.getResource("brown.jpg"));
JLabel jl=new JLabel();
jl.setIcon(new ImageIcon(rasterToAlpha(i,Color.white)));
JOptionPane.showConfirmDialog(null, jl);
} catch (IOException e) {}
}
public static BufferedImage rasterToAlpha(BufferedImage r,Color c){
BufferedImage bi=new BufferedImage(r.getWidth(),r.getHeight(),BufferedImage.TYPE_4BYTE_ABGR);
WritableRaster wr2=bi.getRaster();
WritableRaster wr=r.getRaster();
for(int i=0;i<r.getHeight();i++){
int[] xx=new int[4*r.getWidth()];//array for the abgr
int[] x=new int[3*r.getWidth()];//array for the bgr
wr.getPixels(0, i, r.getWidth(),1,x);//get them line by line
for(int j=0,k = 0;j<x.length;j+=3,k+=4){
if(c.equals(new Color( x[j+2], x[j+1],x[j]))){//flip bgr to rgb and check
xx[k]=0;xx[k+1]=0;xx[k+2]=0;xx[k+3]=0;//if its the same make it transparent
}
else{xx[k]=255;xx[k+1]=x[j];xx[k+2]=x[j+1];xx[k+3]=x[j+2];}//make it opaque
}
wr2.setPixels(0, i, r.getWidth(),1,xx);//write the line
}
return bi;}
}
但结果非常 funny.What 我做错了吗请帮忙。 这就是它的结局…… 编辑 它肯定更好,但它是红色而不是黑色。
虽然 BufferedImage
类型是源图像的 BGR 和目标图像的 ABGR,但您从 getPixels
获得的整数实际上是在常见的 RGB 顺序中。并且 ABGR 图像期望数组按 RGBA 顺序排列。
这没有很好的记录,但是颜色是根据图像的颜色模型(RGB)而不是根据原始缓冲区顺序映射到整数的。
所有这一切的结果是,当您将 k
元素设置为 255 时,它实际上是 red 值,因此您得到 "reddened"图片。通过将源数组的 j+2
值放入目标数组的 k+3
值中,您实际上从原始图像的 blue 值中获得了 alpha 值.
这也意味着您不应该颠倒值的顺序来创建一个 Color
对象来与您的颜色进行比较。
所以这是一个为您更正的循环(请注意,我重命名了变量以使其更有意义。您真的不应该使用 r
、x
、xx
,c
等等,看不懂。格式也很重要!):
public static BufferedImage rasterToAlpha(BufferedImage sourceImage, Color origColor) {
BufferedImage targetImage = new BufferedImage(sourceImage.getWidth(),
sourceImage.getHeight(),
BufferedImage.TYPE_4BYTE_ABGR);
WritableRaster targetRaster = targetImage.getRaster();
WritableRaster sourceRaster = sourceImage.getRaster();
for (int row = 0; row < sourceImage.getHeight(); row++) {
int[] rgba = new int[4 * sourceImage.getWidth()];
int[] rgb = new int[3 * sourceImage.getWidth()];
// Get the next row of pixels
sourceRaster.getPixels(0, row, sourceImage.getWidth(), 1, rgb);
for (int i = 0, j = 0; i < rgb.length; i += 3, j += 4) {
if (origColor.equals(new Color(rgb[i], rgb[i + 1], rgb[i + 2]))) {
// If it's the same make it transparent
rgba[j] = 0;
rgba[j + 1] = 0;
rgba[j + 2] = 0;
rgba[j + 3] = 0;
} else {
rgba[j] = rgb[i];
rgba[j + 1] = rgb[i + 1];
rgba[j + 2] = rgb[i + 2];
// Make it opaque
rgba[j + 3] = 255;
}
}
// Write the line
targetRaster.setPixels(0, row, sourceImage.getWidth(), 1, rgba);
}
return targetImage;
}