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

时间:2017-11-26 23:16:12

标签: java bufferedimage

我昨天使用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)

我刚刚开始编程,我知道即时通讯使用Lib我完全不知道但需要使用BufferedImage,忽略所有的错误代码我有人可以告诉我为什么我只在一些照片上得到错误

1 个答案:

答案 0 :(得分:0)

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

从API doc(强调我的):

  

ArrayIndexOutOfBoundsException - 如果坐标不在边界内,或如果iArray太小而无法容纳输出

最有可能的是,获得异常的图像有4个组件并且是RGBA(而Paint中的组件有3个组件,RGB)。您可能会通过创建一个更大的数组(即new int[4])来消除异常。

但是,解决问题的最佳方法是不要自己创建数组,而是将其留给getPixel方法,如下所示:

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

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

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

由于这些原因,您可能会发现使用BufferedImage.getRGB(x, y)方法更简单,更直观,始终为您提供像素的ARGB值作为单个压缩的int样本,在sRGB色彩空间。