I'm trying to create a program that generates an image and colors each pixel to the same value, then saves the file to a.PNG. I am currently receiving a Coordinate out of bounds error, and have tried several things to debug it. I think that the issue is linked to some third-party code written by my lecturer, as I have printed the p-value, which is negative, though I believe it needs to be between 0 and 255.
Currently, it is not generating any PNG file.
Can someone advise me on how to fix this code?
import java.util.Scanner;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
public class Lab_Week8_ImageFromText {
public static void main(String[] args) throws Exception {
int image_width = 3;
int image_height = 3;
String output_file_path = ("image.png");
String input_file_path = "";
int r = 10;
int b = 10;
int g = 10;
BufferedImage imagetowrite = imageFromText(image_width, image_height, input_file_path, output_file_path, r, g, b);
File f = new File (output_file_path);
ImageIO.write(imagetowrite, "png", f);
}
public static BufferedImage imageFromText (int image_width, int image_height, String input_file_path, String output_file_path, int r, int g, int b) throws IOException{
if(image_width <= 0 || image_height <= 0) {
System.err.println("Width and Height have to be strictly positive!");
return null;
}
System.out.println("Hello");
BufferedImage image = new BufferedImage (image_width, image_height, BufferedImage.TYPE_INT_ARGB);
int x = 1;
int y = 1;
for (x = 1; x <= image_width; x++)
{//System.out.println (x);
for (y = 1; y <= image_height; y++){//System.out.println(y);
setPixel(image, x, y, r, g, b);
}}
System.out.println("Hello 2" + image);
return image;
}
public static void setPixel(BufferedImage image, int x, int y, int r, int g, int b) {
/*
* Test cases for error management
*/
if(x < 0 || y < 0) {
System.err.println("Coordinates (x, y) cannot be negative numbers!");
return;
}
if(r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
System.err.println("Colour values (r, g, b) have to be between 0 and 255!");
return;
}
/*
* Set the alpha value for the pixel, i.e. the transparency of the pixel, to its max value
*/
int a = 255;
/*
* Write the different value of the pixel, i.e. the colours red, green, blue and alpha.
* The different colour values are all stored into a single integer using byte operators.
* a = x << y means write the value of x as bytes at the address y in the object a.
* a = o1 | o2 means a will be composed by o1 and o2, where o1 and o2 are binary operators.
* It is necessary to use this operator because the setRGB method of BufferedImage
* take only one integer that have to hold all the colour values for one given pixel.
*/
int p = (a << 24) | (r << 16) | (g << 8) | b;
/*
* Use the setRGB method from BufferedImage to write the new pixel value (i.e. colour) to the image
*/
image.setRGB(x, y, p);
System.out.println(p);
}
}
Here is the output of p and the error message:
Hello
-16119286
-16119286
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Coordinate out of bounds!
at sun.awt.image.IntegerInterleavedRaster.setDataElements(IntegerInterleavedRaster.java:301)
at java.awt.image.BufferedImage.setRGB(BufferedImage.java:1016)
at Lab_Week8_ImageFromText.setPixel(Lab_Week8_ImageFromText.java:79)
at Lab_Week8_ImageFromText.imageFromText(Lab_Week8_ImageFromText.java:44)
at Lab_Week8_ImageFromText.main(Lab_Week8_ImageFromText.java:22)
The issue here is a common misconception with array indexing for novice programmers. The majority of modern programming languages (critically including Java) index an array with length size
with the first element at index 0
, and the last element at size-1
.
In both of your loops in your program quoted below, you permit the index to equal the length/size
of the array. This means that at some point, the program will try to access the element at size
.
for (x = 1; x <= image_width; x++){
//System.out.println (x);
for (y = 1; y <= image_height; y++){
//System.out.println(y);
setPixel(image, x, y, r, g, b);
}
}
So, to correct these loops, you'll want to set up the bounds like this:
for (x = 0; x < image_width; x++){
//System.out.println (x);
for (y = 0; y < image_height; y++){
//System.out.println(y);
setPixel(image, x, y, r, g, b);
}
}
Note that we now start at 0
and end at image_whatever - 1
, meaning that the last call inside both of your loops would effectively be something like this:
setPixel(image, image_width-1, image_height-1, r, g, b);
I hope this helps you understand your mistake.