使用 Raster.getPixel 时某些图像出错

Error with some Image using Raster.getPixel

我 运行 昨天使用 BufferedImage Lib 解决了这个问题,我得到了一个

java.lang.ArrayIndexOutOfBoundsException: 3

但仅适用于图片 "PNG" 我从网上获取,但如果我在 Paint 中制作自己的图片,则一切正常。我已经尝试查找问题,但看不出我哪里错了。

package grayandconvert;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;


public class JavaCodeProject { // remain if needed Kim
   private final String PATH = "C:\New folder\"; //
   private final String graypath = PATH + "oZPX0bbg.png"; // filename for Grayscale pic
   private final String imgpath = PATH + "oZPX0bb.png";      // filename for Orginal pic 
   private final String textpath =PATH + "filename.txt";   // filename for Output textfile
   private final String imgtype = "png";                    // image file type for Grascale "png" "jpg"


    public static void main(String[] args) 
    {
        JavaCodeProject main = new JavaCodeProject();  //new class for use of the metoth
        main.grayscale();
        main.convert();


    }


    public void convert()
    {
        try
        {
            BufferedImage image =ImageIO.read(new File(graypath)); // called the gray pic for image
            int[] pixel;                                // int array named pixel
            System.out.print(image.getHeight());
            System.out.print(image.getWidth());
            for (int y = 0; y < image.getHeight(); y++) // outer forloop to control Y axel image.getWidth
            {
                for (int x = 0; x < image.getWidth(); x++) //inner forloop to control X axel
                {
                    pixel = image.getRaster().getPixel(x, y, new int[3]); // gets the RGB data from the buffer
                    if(pixel[0]< 255 && pixel[1]< 255 && pixel[2]< 255)
                    {    
                        System.out.print(" Y");
                        writefile("Y");
                    }
                    else
                    {
                        System.out.print(" N");
                        writefile("N");
                    }
                }
            System.out.print(" L");
            System.out.println("");
            writefile("L");

            }
            System.out.print("S");
            writefile("S");


        }

    catch (IOException e) // never used it but it needs to be here
    {
    }


}

    public void writefile(String value)
    {
            String array = value; //named it array. i know right :P

            File file = new File(textpath); //path for new file.txt


            try
            {
                if (!file.exists()) // if file doesnt exists, then this will create it ;)
                {
                    file.createNewFile();
                }

                FileWriter fw = new FileWriter(file.getAbsoluteFile(),true);
                try (BufferedWriter bw = new BufferedWriter(fw)) {
                    bw.write(array,0,array.length());
                }
            }

            catch (IOException e) // if IO exceptions happens this outputs Stacktrace
            {

            }



    }

    public void grayscale()
    {
        BufferedImage img = null;


        try
        {
          File f = new File(imgpath); //org pic
          img = ImageIO.read(f);
        }
        catch(IOException e)
        {
          System.out.println(e);
        }





        for(int y = 0; y < img.getHeight(); y++)
        {
            for(int x = 0; x < img.getWidth(); x++)
            {
            int p = img.getRGB(x,y);

            int a = (p>>24)&0xff;
            int r = (p>>16)&0xff;
            int g = (p>>8)&0xff;
            int b = p&0xff;

            //calculate average
            int avg = (r+g+b)/3;

            //replace RGB value with avg
            p = (a<<24) | (avg<<16) | (avg<<8) | avg;

            img.setRGB(x, y, p);
            }
        }

        try
        {
          File f = new File(graypath); //gray pic
          ImageIO.write(img,imgtype,f);
        }
        catch(IOException e)
        {
          System.out.println(e);
        }
    }



}

I get the error 

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
    at java.awt.image.ComponentSampleModel.getPixel(ComponentSampleModel.java:750)
    at java.awt.image.Raster.getPixel(Raster.java:1519)
    at grayandconvert.JavaCodeProject.convert(JavaCodeProject.java:41)
    at grayandconvert.JavaCodeProject.main(JavaCodeProject.java:23)
128128C:\Users\clipcomet\Desktop\JavaApplication10\nbproject\build-impl.xml:1051: The following error occurred while executing this line:
C:\Users\clipcomet\Desktop\JavaApplication10\nbproject\build-impl.xml:805: Java returned: 1
BUILD FAILED (total time: 1 second)

我刚开始编程,我知道我正在使用一个我不完全了解但需要使用 BufferedImage 的 Lib,忽略我拥有的所有错误代码有人能告诉我为什么我只在某些图片上出现该错误

在某些情况下出现异常的原因是 Raster.getPixel(x, y, pixel) 试图将 像素 在 x, y 处的所有样本复制到 pixel数组。如果您从网上下载随机图片,您无法控制光栅每个像素有多少个样本,但您将 pixel 数组硬编码为 3 个元素。

来自 API 文档(强调我的):

ArrayIndexOutOfBoundsException - if the coordinates are not in bounds, or if iArray is too small to hold the output.

最有可能的是,出现异常的图像有 4 个分量并且是 RGBA(而来自 Paint 的图像有 3 个分量,RGB)。您可能会通过创建更大的数组(即 new int[4])来摆脱异常。

然而,解决这个问题的最好方法是完全不自己创建数组,而是将其留给 getPixel 方法,如下所示:

int[] pixel = null;
for (y...) {
    for (x...) {
        pixel = raster.getPixel(x, y, pixel);
        ...
    }
}

这也确保分配只发生一次,这显然有利于性能。


也就是说,您仍然需要处理这样一个事实:随机图像的每个像素可能没有预期的样本数。如果您的输入是灰色的或使用颜色图 (IndexColoModel),它将只有一个样本(并且您的 pixel[1]pixel[2] 数组将有一个 ArrayIndexOutOfBoundsExpcetion访问)。对于颜色图的情况,样本值与您在屏幕上看到的 RGB 值无关(它只是查找的索引 table)。

出于这些原因,您可能会发现仅使用 BufferedImage.getRGB(x, y) 方法更简单、更直观,该方法 总是 为您提供像素的 ARGB 值作为单打包 int 样本,sRGB 颜色 space.