I ran into the problem yesterday using the BufferedImage Lib, I get an error:
java.lang.ArrayIndexOutOfBoundsException: 3
but only for pictures "PNG" I get from the net, but if I make my own in Paint, it all works. I have tried looking up the problem but can't see where I'm wrong.
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 method
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 doesn't exist, 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)
I just started programming a bit ago and I know I'm using a Lib I don't know fully but needed to use the BufferedImage, ignoring all the bad code I have can someone tell me why i only get that error on some pics
The reason you get the exception in some cases, is that Raster.getPixel(x, y, pixel)
tries to copy all the samples for the pixel at x, y into the pixel
array. And you have no control over how many samples per pixel your raster has, if you download random pictures from the net, yet you hardcode the pixel
array to 3 elements.
From the API doc (emphasis mine):
ArrayIndexOutOfBoundsException
- if the coordinates are not in bounds, or ifiArray
is too small to hold the output.
Most likely, the images where you get the exception, have 4 components and are RGBA (while the ones from Paint have 3 components, RGB). You will probably get rid of the exception by creating a larger array (ie. new int[4]
).
However, the best way to fix the problem is to not create the array at all yourself, and instead leave that to the getPixel
method, like this:
int[] pixel = null;
for (y...) {
for (x...) {
pixel = raster.getPixel(x, y, pixel);
...
}
}
This also ensures that the allocation happens only once, which is obviously good for performance.
That said, you still need to handle the fact that a random image may not have the expected number of samples per pixel. If your input is gray or uses a color map (IndexColoModel
), it will only have one sample (and you'll have an ArrayIndexOutOfBoundsExpcetion
for your pixel[1]
and pixel[2]
array accesses). And for the color map case, the sample values is unrelated to the RGB value you see on screen (it's only an index into a lookup table).
For these reasons, you may find it easier and more intuitive to just use the BufferedImage.getRGB(x, y)
method, which always gives you the ARGB values of the pixel as a single packed int sample, in sRGB color space.