My teacher gave us a task to make a class that takes an 640x480 bmp colored image, to convert it in grayscale image, I found some sources with ideas so i did it. But there's a problem because it seems that it makes it cause it doesn't give me error, but the output doesn't appear. I think it's my code. My code is
import java.io.*;
public class Grayscale{
FileInputStream image;
FileOutputStream img;
byte[] datos;
int gray;
public Grayscale(String nombre)throws Exception{
this.image = new FileInputStream(nombre);
this.img = img;
this.datos = new byte[image.available()];
this.gray = gray;
}
public void gray()throws Exception{
image.read(datos);
img = new FileOutputStream("grayscaleprueba.bmp");
for (int i = 0; i
gray = (byte)(datos[i]*0.3 + datos[i+1]*0.59 + datos[i+2]);
datos[i] = (byte)gray;
datos[i+1] = (byte)gray;
datos[i+2] = (byte)gray;
}
img.write(datos);
}
}
解决方案
There are some problems apart from those that @joni mentioned. This problem is a bit deeper than what it first seems to be.
BMP file format
The BMP format has a header. You should skip (or probably update) the header before doing the image transformation.
color table: you assume a "straight" palette: the color index the same as the RGB value. But this might be different... (BTW: If the picture uses a color table, then you could alter only that to get a grayscale image however...)
how many bits per pixel are there? You assumed that it is 24 bits per pixel, in a 8-8-8 distribution. This is not guarranteed... The header provides this info.
compression: yep, the image might be compressed - you'd have to decode it to do anything with the pixel values themselves.
Loop
You deal with 3 bytes for each pixel, and you loop through the file in the increments of 1. The resulting image might happen to be quite interesting to watch through 3D glasses, but will mean some strange image appearing.
for (int i = 0; i
gray = (byte)(datos[i]*0.3 + datos[i+1]*0.59 + datos[i+2]);
datos[i] = (byte)gray;
datos[i+1] = (byte)gray;
datos[i+2] = (byte)gray;
}
Signed byte
Byte in Java is signed. It goes from -128 to 127, so your arithmetic is not valid. For each byte, I'd use it as an int, and add 128 to it before summing them with weights. Then after summing, subtract the 128, and then cast to byte.
Pixel transformation values range
You sum up 3 numbers in the saem range, and would want to get a number in the range itself. However, your weights don't reflect this: the weights should add up to 1. For starters, I'd use 0.33 for all values (that does not give perfect color weights,but should technically works).
//using double to have some precision
double temp = datos[i]/3.0d + datos[i+1]/3.0d + datos[i]/3.0d;
gray = (byte)(Math.round(temp)-128); //rounding to Long, and converting to byt value range