簡體   English   中英

Java ImageIO.write正在為灰度圖像着色

[英]Java ImageIO.write is Colorizing a Greyscale Image

我遇到了困擾我數日的問題。 希望這里有人可以幫助我了解正在發生的事情。 我正在嘗試編寫一個簡單的Java程序,該程序將使用JPEG目錄,將其轉換為灰度,然后將其保存到同一文件夾中。

我的程序是將每個像素的紅色,綠色和藍色分量設置為該像素的亮度值。 代碼運行良好,似乎可以滿足我的要求。 如果我在JFrame中查看完成的圖像,它將顯示為黑白。 但是,當我保存圖像(使用ImageIO.write())時,由於某種原因,它會變成彩色並看起來相當紅色。 我很想發布圖片,但我想我的聲譽還不夠好...

由於無法放置圖像,因此我將盡力解釋。 這是我所知道的:

  • 如果我使用Java程序查看新創建的圖像,則它會根據需要顯示為黑白。
  • 如果我保存圖像並嘗試使用外部程序查看它,則它根本不會出現黑白圖像,而看起來像是原始圖像的縮小版本。
  • 如果使用Java程序打開同一張保存的圖像(應該是黑白的但不是),則確實確實是黑白的。
  • 如果我將文件另存為png,則一切正常。

如果有人想看,這是我正在使用的相關代碼:

    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")));
    }
}

我只想強調,這不是將圖像變成黑白的替代方法的問題。 我真正想知道的是為什么它只能用作png而不是jpg。 非常感謝所有閱讀本文的人!

這是ImageIO的已知問題。

當保存/加載為jpeg ,API不知道如何處理alpha組件(據我了解的問題)。

解決方案是不要將具有alpha成分的圖像寫成jpg格式,或者不使用基於非alpha的圖像,例如TYPE_INT_RGB

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM