Konstantinos Kosyfarinis Konstantinos Kosyfarinis - 1 year ago 66
Java Question

Strange color changes to a BufferedImage after saving it as a PNG file with ImageIO.write

I've been trying to make a Java program that will allow some pixel colors to be changed to other colors in a

BufferedImage
, but the colors that are being drawn seem to be overlaid over the old ones. Here's what I mean:

Combined image of input.png and output.png

This is the code that's on the .java file at the moment:

static BufferedImage image = null;
static File file = null;
static int height;
static int width;
static int[][][] pixelStorage;
static int pixel;
static int getPixelDataOutput = 0;
static Random random = new Random();

public static void main(String args[]) throws IOException {

System.out.println("test");

try {
file = new File("C:\\Users\\kkosy\\Dev\\Java\\Random\\Images - Color Changer\\Images\\input.png");
}catch(Exception exception) {
System.out.println(exception);
}

image = ImageIO.read(file);

height = image.getHeight();
width = image.getWidth();

pixelStorage = new int[height][width][4];

for(int h = 0; h < height - 1; h++) {
for(int w = 0; w < width - 1; w++) {
savePixelData(w, h);
if(getPixelData(w,h,"r") == 0){
System.out.println();
printPixelData(w,h,"Before -- ");
setPixelData(w,h,255,0,0,255);
printPixelData(w,h,"After -- ");
}
}
}

try {
file = new File("C:\\Users\\kkosy\\Dev\\Java\\Random\\Images - Color Changer\\Images\\output.png");
ImageIO.write(image, "jpg", file);
}catch(Exception exception){
System.out.println(exception);
}

}

private static void savePixelData(int x, int y) {
pixel = image.getRGB(x,y);
pixelStorage[y][x][0] = (pixel >> 24) & 0xff;
pixelStorage[y][x][1] = (pixel >> 16) & 0xff;
pixelStorage[y][x][2] = (pixel >> 8) & 0xff;
pixelStorage[y][x][3] = pixel & 0xff;
//printPixelData(x,y,"");

}

private static void setPixelData(int x, int y, int alpha, int red, int green, int blue) {
int setPixel = (alpha << 24) | (red << 16) | (green << 8) | (blue);
image.setRGB(x, y, setPixel);
image.setRGB(x, y, new Color(red,green,blue).getRGB());
}

private static void printPixelData(int x, int y, String arguments) {
System.out.println(arguments + "" + pixelStorage[y][x][0] + " " + pixelStorage[y][x][1] + " " + pixelStorage[y][x][2] + " " + pixelStorage[y][x][3] + " ");
}

private static int getPixelData(int x, int y, String argb) {
switch(argb) {
case "a": {
getPixelDataOutput = pixelStorage[y][x][0];
break;
}
case "r": {
getPixelDataOutput = pixelStorage[y][x][1];
break;
}
case "g": {
getPixelDataOutput = pixelStorage[y][x][2];
break;
}
case "b": {
getPixelDataOutput = pixelStorage[y][x][3];
break;
}
}
return getPixelDataOutput;
}


I have no idea why it outputs such an image. Perhaps it's the
setRGB()
or something along those lines.

Answer Source

You are trying to create a PNG file, but this line...

ImageIO.write(image, "jpg", file);

...is trying to write a JPEG. According to the Unix file command, the output is indeed a JPEG... also with a bad case of dark cyan pixels.

When I changed "jpg" to "png", I got an output.png file that looked exactly the same as input.png.

I don't know what you want the output to look like (and I'm using a different input file) but this seems closer than the miscolored JPEG-in-PNG's-clothing.


Your log will be useless for debugging, because printPixelData always prints the values in pixelStorage. Since setPixelData only changes the values in image, you will always print the "before" values twice, and never the "after" values.

As an aside, all those static variables make tracing the program's execution much harder than it has to be. At least move what you can into methods (like height, width, and file, which are never used outside of main), and delete the ones you don't use at all (like getPixelDataOutput and random).


Probably unrelated, but the setPixelData method sets a pixel, and then immediately resets it to some other value:

private static void setPixelData(
  int x, int y,
  int alpha, int red, int green, int blue
) {
    int setPixel = (alpha << 24) | (red << 16) | (green << 8) | (blue);
    image.setRGB(x, y, setPixel);
    // Why overwrite the value you just set?
    image.setRGB(x, y, new Color(red,green,blue).getRGB());
}

This doesn't seem to change anything --- (my test image looked the same with or without the second call to setRGB --- but it's probably not what you wanted.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download