Following are two functions that make the core of the program for reading from an image and persisting the RGB values in a 2D matrix or in a array of objects of a class . I find it easier to store it in a linkedList .
-> getRGBList
private List<ImageRGB> getRGBList(BufferedImage bufferedImage) {
List<ImageRGB> rgbValues = new LinkedList<ImageRGB>();
ImageRGB.setImageProperties(bufferedImage);
for (int i = 0; i < bufferedImage.getWidth(); i++) {
for (int j = 0; j < bufferedImage.getHeight(); j++) {
Color color = new Color(bufferedImage.getRGB(i, j));
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
rgbValues.add(new ImageRGB(red, blue, green));
}
}
return rgbValues;
}
The above function takes the BufferedImage object , i will tell you later how that object was created .
- Sets the ImageProperties height , width and image type of the image
- Iterates over the each pixel in the image and get it's pixel data in RGB (bufferedImage.getRGB(i,j) , wrap it over the Color object and retrieve the red , green and blue components of the pixel.
- I create an RGB object out of this value and add it to the linkedList of the Object.
After the end of execution of this method , we iterated over the rows of the image for each column of the image , i.e. iterate for each pixel in the height , for each pixel in the width and collected RGB values and stored them in an object . Now you can chose to persist this in database or serialize to a file or you name . I let it be in the memory for now .
-> generateImage
private void generateImage(List<ImageRGB> rgbValues, File destination) {
try {
int k = -1;
BufferedImage image = new BufferedImage(ImageRGB.getWidth(), ImageRGB.getHeight(), ImageRGB.getImageType());
for (int i = 0; i < image.getWidth(); i++) {
for (int j = 0; j < image.getHeight(); j++) {
k++;
ImageRGB rgb = rgbValues.get(k);
Color color = new Color(rgb.getRed(), rgb.getGreen(), rgb.getBlue());
image.setRGB(i, j, color.getRGB());
}
}
ImageIO.write(image, "jpg", destination);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void generateImage(List<ImageRGB> rgbValues, File destination) {
try {
int k = -1;
BufferedImage image = new BufferedImage(ImageRGB.getWidth(), ImageRGB.getHeight(), ImageRGB.getImageType());
for (int i = 0; i < image.getWidth(); i++) {
for (int j = 0; j < image.getHeight(); j++) {
k++;
ImageRGB rgb = rgbValues.get(k);
Color color = new Color(rgb.getRed(), rgb.getGreen(), rgb.getBlue());
image.setRGB(i, j, color.getRGB());
}
}
ImageIO.write(image, "jpg", destination);
} catch (Exception ex) {
ex.printStackTrace();
}
}
- The above function is used to generate the image back from it's pixel values at each pixel.
- The function takes the LinkedList we created in the previous method and an output File object to save the file .
- It creates a Buffered Image object out of the Image Properties we had set in the previous method.
- Iterates over each of the rows for each of the pixel in the width of the image , as we did in the previous method , generate the Color at that pixel after retrieving the RGB components from the ImageRGB object & set the pixel value at that pixel in the bufferedImage object.
- After all the iterations are done , write the image to the destination.
Do you get the exact image back , i bet you do , and it is indeed smart .
Lastly you need a main method to execute the above two methods and i would do the following
public class ImageProcessor {
public static void main(String[] args) throws IOException {
String srcFile = "C:\\Users\\adee\\Desktop\\src.jpg";
String destFile = "C:\\Users\\adee\\Desktop\\destination.jpg";
ImageProcessor iP = new ImageProcessor();
BufferedImage bi = ImageIO.read(new File(srcFile));
List<ImageRGB> rgbValues = iP.getRGBList(bi);
iP.generateImage(rgbValues, new File(destFile));
}
....
....
public class ImageProcessor {
public static void main(String[] args) throws IOException {
String srcFile = "C:\\Users\\adee\\Desktop\\src.jpg";
String destFile = "C:\\Users\\adee\\Desktop\\destination.jpg";
ImageProcessor iP = new ImageProcessor();
BufferedImage bi = ImageIO.read(new File(srcFile));
List<ImageRGB> rgbValues = iP.getRGBList(bi);
iP.generateImage(rgbValues, new File(destFile));
}
....
....
- The above piece of code simply uses the javax.imageio libraries to read an image file and create a BufferedImage out of it which is passed to our method 1 to process the image.
Some more interesting things you can try out is to get the contents of the image as a byte array
byte[] bytes = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();
bufferedImage.getRaster() is an object of a class representing a rectangular array of pixels. A Raster encapsulates a DataBuffer that stores the sample values and a SampleModel that describes how to locate a given sample value in a DataBuffer.
You can read more about Raster here .
Another interesting thing you could have done is , create a 2D array of number of rows = (height * width) of the Buffered Image and 3 columns representing the R G B components and iterating the same way over the Buffered Image and creating a 2D matrix out of the Image , and that would have made the program really cool . However i like to store it in an Object of RGB class for my convenience.
Lastly let me throw some light on RGB color space .The red, green and blue use 8 bits each, which have integer values from 0 to 255. This makes 256*256*256=16777216 possible colors. You can play around with the RGB values retrieved from the image and increase or decrease it for creating the image again , make sure it doesn't go beyond 255 and it doesn't go below 0. The newly generated image will be a totally new color
I hope you learnt something cool today .
Happy Coding