[英]Java ImageIO.write is Colorizing a Greyscale Image
I'm having a problem that's been driving me crazy for days. 我遇到了困扰我数日的问题。 Hopefully, someone here can help me understand what's happening. 希望这里有人可以帮助我了解正在发生的事情。 I'm trying to write a simple Java program that will take a directory of JPEGs, convert them to greyscale, and save them to the same folder. 我正在尝试编写一个简单的Java程序,该程序将使用JPEG目录,将其转换为灰度,然后将其保存到同一文件夹中。
My procedure is to set the red, green, and blue components of each pixel to that pixel's luminance value. 我的程序是将每个像素的红色,绿色和蓝色分量设置为该像素的亮度值。 The code runs fine and seems to do what I want. 代码运行良好,似乎可以满足我的要求。 If I view the completed image in a JFrame, it shows up black and white. 如果我在JFrame中查看完成的图像,它将显示为黑白。 However, when I save the image (using ImageIO.write()), for some reason, it becomes colorized and looks rather red. 但是,当我保存图像(使用ImageIO.write())时,由于某种原因,它会变成彩色并看起来相当红色。 I'd love to post the images but I guess my reputation is not good enough... 我很想发布图片,但我想我的声誉还不够好...
Since I can't put the images, I'll try to explain it as well as I can. 由于无法放置图像,因此我将尽力解释。 Here's what I know: 这是我所知道的:
Here's the relevant code I'm using if anyone would like to see it: 如果有人想看,这是我正在使用的相关代码:
import java.io.*;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.*;
public class ImageEZ {
public static void displayImage(BufferedImage img) {
class ImageFrame extends JFrame {
ImageFrame(BufferedImage img) {
super();
class ImagePanel extends JPanel {
BufferedImage image;
ImagePanel(BufferedImage image) {
this.image = ImageEZ.duplicate(image);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), this);
}
}
ImagePanel panel = new ImagePanel(img);
add(panel);
}
}
JFrame frame = new ImageFrame(img);
frame.setSize(img.getWidth(), img.getHeight());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static BufferedImage duplicate(BufferedImage img) {
BufferedImage dup = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
dup.setRGB(0, 0, img.getWidth(), img.getHeight(), ImageEZ.getRGB(img), 0, img.getWidth());
return dup;
}
public static int[] getRedArray(BufferedImage img) {
int[] tArray = ImageEZ.getRGB(img);
for (int i = 0; i < tArray.length; i++) {
tArray[i] = tArray[i] << 8;
tArray[i] = tArray[i] >>> 24;
}
return tArray;
}
public static int[] getRedArray(int[] tArray) {
int[] nArray = new int[tArray.length];
for (int i = 0; i < tArray.length; i++) {
nArray[i] = tArray[i] << 8;
nArray[i] = nArray[i] >>> 24;
}
return nArray;
}
public static int[] getGreenArray(BufferedImage img) {
int[] tArray = ImageEZ.getRGB(img);
for (int i = 0; i < tArray.length; i++) {
tArray[i] = tArray[i] << 16;
tArray[i] = tArray[i] >>> 24;
}
return tArray;
}
public static int[] getGreenArray(int[] tArray) {
int[] nArray = new int[tArray.length];
for (int i = 0; i < tArray.length; i++) {
nArray[i] = tArray[i] << 16;
nArray[i] = nArray[i] >>> 24;
}
return nArray;
}
public static int[] getBlueArray(BufferedImage img) {
int[] tArray = ImageEZ.getRGB(img);
for (int i = 0; i < tArray.length; i++) {
tArray[i] = tArray[i] << 24;
tArray[i] = tArray[i] >>> 24;
}
return tArray;
}
public static int[] getBlueArray(int[] tArray) {
int[] nArray = new int[tArray.length];
for (int i = 0; i < tArray.length; i++) {
nArray[i] = tArray[i] << 24;
nArray[i] = nArray[i] >>> 24;
}
return nArray;
}
public static int[] YBRtoRGB(int[] ybr) {
int[] y = getRedArray(ybr);
int[] r = getBlueArray(ybr);
int[] b = getGreenArray(ybr);
int[] red = new int[y.length];
int[] green = new int[y.length];
int[] blue = new int[y.length];
for (int i = 0; i < red.length; i++) {
red[i] = (int) (y[i] + 1.402*r[i]);
green[i] = (int) (y[i] + -.344*b[i] + -.714*r[i]);
blue[i] = (int) (y[i] + 1.772*b[i]);
}
int[] RGB = new int[red.length];
for (int i = 0; i < red.length; i++) {
RGB[i] = red[i] << 16 | green[i] << 8 | blue[i] | 255 << 24;
}
return RGB;
}
public static int[] getLumArray(BufferedImage img) {
int[] red = getRedArray(img); //Returns an array of the red values of the pixels
int[] green = getGreenArray(img);
int[] blue = getBlueArray(img);
int[] Y = new int[red.length];
for (int i = 0; i < red.length; i++) {
Y[i] = (int) (.299*red[i] + .587*green[i] + .114*blue[i]);
}
return Y;
}
// Converts an image to greyscale using the luminance of each pixel
public static BufferedImage deSaturate(BufferedImage original) {
BufferedImage deSaturated = new BufferedImage(original.getWidth(),
original.getHeight(),
BufferedImage.TYPE_INT_ARGB);
int[] Y = ImageEZ.getLumArray(original); //Returns an array of the luminances
for (int i = 0; i < Y.length; i++) {
Y[i] = 255 << 24 | Y[i] << 16;
}
int[] rgb = ImageEZ.YBRtoRGB(Y); //Converts the YCbCr colorspace to RGB
deSaturated.setRGB(0, 0, original.getWidth(), original.getHeight(),
rgb, 0, original.getWidth());
return deSaturated;
}
// Takes a folder of JPEGs and converts them to Greyscale
public static void main(String[] args) throws Exception {
File root = new File(args[0]);
File[] list = root.listFiles();
for (int i = 0; i < list.length; i++) {
BufferedImage a = ImageEZ.deSaturate(ImageIO.read(list[i]));
displayImage(a); //Displays the converted images.
boolean v = ImageIO.write(a, "jpg", new File(list[i].getParent() + "\\" + i + ".jpg"));
}
// Displays the first newly saved image
displayImage(ImageIO.read(new File(list[0].getParent() + "\\" + 0 + ".png")));
}
}
I just want to stress, this is not a question about alternative methods for turning making an image black and white. 我只想强调,这不是将图像变成黑白的替代方法的问题。 What I really want to know is why it works as a png but not as a jpg. 我真正想知道的是为什么它只能用作png而不是jpg。 Thanks a lot to all who read this far! 非常感谢所有阅读本文的人!
This is a known issue with ImageIO
. 这是ImageIO
的已知问题。
When saved/loaded as jpeg
, the API doesn't know how to handle the alpha component (as I understand the problem). 当保存/加载为jpeg
,API不知道如何处理alpha组件(据我了解的问题)。
The solution is to not write images with an alpha component to jpg
format, or use a non-alpha based image, such as TYPE_INT_RGB
instead... 解决方案是不要将具有alpha成分的图像写成jpg
格式,或者不使用基于非alpha的图像,例如TYPE_INT_RGB
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.