Below is the following code that reads in RGB values using BufferedImage, and then simply writes them back out again to file. The resultant image is perfect, and looks good. No worries there.
I run a print test to print out the first 10 RBG int values. This is to test the "test.png" file, and then to test the resultant image - "new-test.png".
For some reason I am getting different RBG values between the two files.
E.g. (The first 3 RGB int values)
test.png : -16704215, -16704215, -16704215
new-test.png : -16638935, -16638935, -16573142
Can anyone identify to why I am getting different RBG values that printed out for both test files?
try
{
BufferedImage imgBuf = ImageIO.read(new File("test.png"));//also testing with GIFs, JPEGs
int w = imgBuf.getWidth();
int h = imgBuf.getHeight();
int[] RGBarray = imgBuf.getRGB(0,0,w,h,null,0,w);
//Arrays to store their respective component values
int [][] redPixels = new int [h][w];
int [][] greenPixels = new int [h][w];
int [][] bluePixels = new int [h][w];
for(int i=0; i<=10; i++)
{
//print out the first 10 RGB int values - testing purposes
System.out.println(RGBarray[i]);
}
//Separate the RGB int values into 3 array, red, green and blue ....
int x=0;
for(int row=0; row<h; row++)
{
for(int col=0; col<w; col++)
{
redPixels[row][col] = ((RGBarray[x]>>16)&0xff);
greenPixels[row][col] = ((RGBarray[x]>>8)&0xff);
bluePixels[row][col] = (RGBarray[x]&0xff);
x++;
}
}
//set pixels back using the setRBG() ...
BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
for(int row=0; row<h; row++)
{
for(int col=0; col<w; col++)
{
//use bit shifting to re-form the RGB int again
int rgb = (redPixels[row][col] & 0xff) << 16 | (greenPixels[row][col] & 0xff) << 8 | (bluePixels[row][col] & 0xff);
bufferedImage.setRGB(col, row, rgb);
}
}
}
catch(IOException i){}; // This exception format is only temporary !
Here is small modification of your code that also saves the image and then reads it back again. With this code I get exactly the same int values before and after.
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.junit.Test;
public class PngReadWriteTest {
#Test
public void test(){
try
{
BufferedImage imgBuf = ImageIO.read(new File("test.png"));//also testing with GIFs, JPEGs
int w = imgBuf.getWidth();
int h = imgBuf.getHeight();
int[] RGBarray = imgBuf.getRGB(0,0,w,h,null,0,w);
//Arrays to store their respective component values
int [][] redPixels = new int [h][w];
int [][] greenPixels = new int [h][w];
int [][] bluePixels = new int [h][w];
System.out.println("IMAGE FIRST READ:");
printPixelValues(imgBuf);
//Separate the RGB int values into 3 array, red, green and blue ....
int x=0;
for(int row=0; row<h; row++)
{
for(int col=0; col<w; col++)
{
redPixels[row][col] = ((RGBarray[x]>>16)&0xff);
greenPixels[row][col] = ((RGBarray[x]>>8)&0xff);
bluePixels[row][col] = (RGBarray[x]&0xff);
x++;
}
}
//set pixels back using the setRBG() ...
BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
for(int row=0; row<h; row++)
{
for(int col=0; col<w; col++)
{
//use bit shifting to re-form the RGB int again
int rgb = (redPixels[row][col] & 0xff) << 16 | (greenPixels[row][col] & 0xff) << 8 | (bluePixels[row][col] & 0xff);
bufferedImage.setRGB(col, row, rgb);
}
}
System.out.println("IMAGE BEFORE SAVE:");
printPixelValues(bufferedImage);
//Save image as png
ImageIO.write(bufferedImage, "png", new File("new-test.png"));
BufferedImage newImage = ImageIO.read(new File("new-test.png"));//also testing with GIFs, JPEGs
System.out.println("IMAGE AFTER SECOND READ:");
printPixelValues(newImage);
}
catch(IOException i){}; // This exception format is only temporary !
}
private void printPixelValues(BufferedImage image){
int w = image.getWidth();
int h = image.getHeight();
int[] RGBarray = image.getRGB(0,0,w,h,null,0,w);
for(int i=0; i<=10; i++)
{
//print out the first 10 RGB int values - testing purposes
System.out.println(RGBarray[i]);
}
}
}
This will only work if you use PNG since it is lossless. If you use JPG you will not get the same result since it is lossy. when you save the file as a JPG it will not result in a file containing the exact same bytes as in your first image. The level of compression will affect the image. So even if the files looks just the same by eye, they will not be exactly the same.
Related
I have a code that puts an image in a pixel matrix.I have to split this image into four parts and get 4 different image files for these parts.
Then I have to do some image processing on it and then join those parts back together in a single image.
Please help me in achieving this.
Note:the image is colored and we want to just split it into 4 equal parts and then get it back as one.No changes needed.Here is the code to get four matrices of intensities.But I don't know what to do with it.It might be that there is no need of it at all.
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
class Optimization
{
public static void main(String[] args) throws IOException
{
BufferedImage hugeImage = ImageIO.read(new File("comp.jpg"));
final byte[] pixels = ((DataBufferByte) hugeImage.getRaster().getDataBuffer()).getData();
int width = hugeImage.getWidth();
int height = hugeImage.getHeight();
if(width%2!=0)
width=width-1;
if(height%2!=0)
height=height-1;
//System.out.print(width+" "+height);
int intensity[][]=new int[width][height];
int b1[][]=new int[width/2][height/2];
int b2[][]=new int[width/2][height/2];
int b3[][]=new int[width/2][height/2];
int b4[][]=new int[width/2][height/2];
int x1=0,y1=0,x2=0,y2=0,x3=0,x4=0,y3=0,y4=0;
final int pixelLength = 3;
for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel += pixelLength)
{
int a1,a2,a3;
a3= ((int) pixels[pixel] & 0xff); // blue
a2= (((int) pixels[pixel + 1] & 0xff)); // green
a1= (((int) pixels[pixel + 2] & 0xff)); // red
int i=(a1+a2+a3)/3;
intensity[col][row]=i;
if((col<=width/2-1)&&(row<=height/2-1))
{
b1[x1][y1]=i;
x1++;
if(col==width/2-1)
{
x1=0;
y1++;
}
}
if((col<width)&&(row<=height/2-1)&&(col>width/2-1))
{
b2[x2][y2]=i;
x2++;
if(col==width-1)
{
x2=0;
y2++;
}
}
if((col<width/2)&&(row<height)&&(row>=height/2))
{
b3[x3][y3]=i;
x3++;
if(col==width/2-1)
{
x3=0;
y3++;
}
}
if((col>width/2-1)&&(row>height/2-1))
{
b4[x4][y4]=i;
x4++;
if(col==width-1)
{
x4=0;
y4++;
}
}
col++;
if (col == width)
{
col = 0;
row++;
}
}
for(int m=0;m<height/2;m++)
{
for(int n=0;n<width/2;n++)
{
System.out.print(b1[n][m]+" ");
}
System.out.println();
}
}
}
java.awt.Image provides you getSubimage(int x, int y, int w, int h)
"Returns a subimage defined by a specified rectangular region." You just return four equal regions and thats it.
You can use getSubImage(int x, int y, int w, int h), but you will get an image that shares the same raster than the original image, meaning that if you modify the new sub-image, then you also modify the original image. If it's not problematic for you, then use it.
Else, as you have already accessed the DataBuffer (good idea), here is a simple code to do what you want (I just make DataBuffer copies, and it works when the image dimensions are odd):
BufferedImage image = ... ;
BufferedImage q1 = new BufferedImage(image.getWidth()/2, image.getHeight()/2, image.getType()) ;
BufferedImage q2 = new BufferedImage(image.getWidth()-image.getWidth()/2, image.getHeight()/2, image.getType()) ;
BufferedImage q3 = new BufferedImage(image.getWidth()/2, image.getHeight()-image.getHeight()/2, image.getType()) ;
BufferedImage q4 = new BufferedImage(image.getWidth()-image.getWidth()/2, image.getHeight()-image.getHeight()/2, image.getType()) ;
byte[] bb = ((DataBufferByte)image.getRaster().getDataBuffer()).getData() ;
byte[] bbq1 = ((DataBufferByte)q1.getRaster().getDataBuffer()).getData() ;
byte[] bbq2 = ((DataBufferByte)q2.getRaster().getDataBuffer()).getData() ;
byte[] bbq3 = ((DataBufferByte)q3.getRaster().getDataBuffer()).getData() ;
byte[] bbq4 = ((DataBufferByte)q4.getRaster().getDataBuffer()).getData() ;
for (int y=0 ; y < q1.getHeight() ; y++) // Fill Q1 and Q2
{
System.arraycopy(bb, y*image.getWidth(), bbq1, y*q1.getWidth(), q1.getWidth()) ;
System.arraycopy(bb, y*image.getWidth()+q1.getWidth(), bbq2, y*q2.getWidth(), q2.getWidth()) ;
}
for (int y=0 ; y < q3.getHeight() ; y++) // Fill Q3 and Q4
{
System.arraycopy(bb, (y+q1.getHeight())*image.getWidth(), bbq3, y*q3.getWidth(), q3.getWidth()) ;
System.arraycopy(bb, (y+q1.getHeight())*image.getWidth()+q3.getWidth(), bbq4, y*q4.getWidth(), q4.getWidth()) ;
}
Given an image file, say of PNG format, how to I get an array of int [r,g,b,a] representing the pixel located at row i, column j?
So far I am starting here:
private static int[][][] getPixels(BufferedImage image) {
final byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
final int width = image.getWidth();
final int height = image.getHeight();
int[][][] result = new int[height][width][4];
// SOLUTION GOES HERE....
}
Thanks in advance!
You need to get the packed pixel value as an int, you can then use Color(int, boolean) to build a color object from which you can extract the RGBA values, for example...
private static int[][][] getPixels(BufferedImage image) {
int[][][] result = new int[height][width][4];
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
Color c = new Color(image.getRGB(i, j), true);
result[y][x][0] = c.getRed();
result[y][x][1] = c.getGreen();
result[y][x][2] = c.getBlue();
result[y][x][3] = c.getAlpha();
}
}
}
It's not the most efficient method, but it is one of the simplest
BufferedImages have a method called getRGB(int x, int y) which returns an int where each byte is the components of the pixel (alpha, red, green and blue). If you dont want to do the bitwise operators yourself you can use Colors.getRed/Green/Blue methods by creating a new instance of Java.awt.Color with the int from getRGB.
You can do this in a loop to fill the three-dimensional array.
This is my code for this problem:
File f = new File(filePath);//image path with image name like "lena.jpg"
img = ImageIO.read(f);
if (img==null) //if img null return
return;
//3d array [x][y][a,r,g,b]
int [][][]pixel3DArray= new int[img.getWidth()][img.getHeight()][4];
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
int px = img.getRGB(x,y); //get pixel on x,y location
//get alpha;
pixel3DArray[x][y][0] =(px >> 24)& 0xff; //shift number and mask
//get red
pixel3DArray[x][y][1] =(px >> 16)& 0xff;
//get green
pixel3DArray[x][y][2] =(px >> 8)& 0xff;
//get blue
pixel3DArray[x][y][3] =(px >> 0)& 0xff;
}
}
I have a 2D array which contains the RGB values. I need to create a valid image from these pixel values and save it. I have given the 2D array below. I wanted to implement this part in my project, so please help me with this. Thank you.
int[] pixels = new int[imageSize * 3];
int k = 0;
for(int i=0; i<height; i++)
{
for(int j=0; j<width; j++)
{
if(k<imageSize*3)
{
pixels[k] = r[i][j];
pixels[k+1] = g[i][j];
pixels[k+2] = b[i][j];
}
k = k+3;
}
}
You can build a BufferedImage of type BufferedImage.TYPE_INT_RGB. This type represents a color as an int where:
3rd byte (16-23) is red,
2nd byte (8-15) is green and
1st byte (7-0) is blue.
You can get the pixel RGB value as follows:
int rgb = red;
rgb = (rgb << 8) + green;
rgb = (rgb << 8) + blue;
Example (Ideone full example code):
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int rgb = r[y][x];
rgb = (rgb << 8) + g[y][x];
rgb = (rgb << 8) + b[y][x];
image.setRGB(x, y, rgb);
}
}
File outputFile = new File("/output.bmp");
ImageIO.write(image, "bmp", outputFile);
I have 3 2D matrices of the same size (let say 200 rows and 300 columns). Every matrix represent the value of one of the three "basic" color (red, green and blue). The values of the matrix can be between 0 and 255. Now I want to combine these matrices to show them as a colored image (200 by 300 pixels). How can I do it in JAVA?
First :you can create Color from this values like:
Color c = new Color(red, green, blue, alpha);
Note that:
red is the value of Matrics1
green is the value of Matrics2
blue is the value of Matrics3
Then create new image :
BufferedImage image = new BufferedImage(200/*Width*/, 300/*height*/, BufferedImage.TYPE_INT_ARGB);
then set the value on the image Like this:
image.setRGB(x, y, c.getRGB());
This is the code for this steps ,Try it :
public class Main {
public static void main(String args[]) throws IOException {
int red[][] = new int[200][300];
int green[][] = new int[200][300];
int blue[][] = new int[200][300];
/////////////////set this matrices
BufferedImage image = new BufferedImage(200/*Width*/, 300/*height*/, BufferedImage.TYPE_INT_ARGB);
for (int i = 0; i < 200; i++) {
for (int j = 0; j < 300; j++) {
Color c = new Color(red[i][j], green[i][j], blue[i][j]);
image.setRGB(i, j, c.getRGB());
}
}
ImageIO.write(image, "jpg", new File("/////////////image path.jpg"));
}
}
I want to convert a color image to grayscale.First I getting the data of color image and change this data but when I want to create a gary image from this data I have a error like this...
getData() maethod:
public double[] getData(BufferedImage a){
double[] data2=new double[h*w];
int red=0,green=0,blue=0;
int counter=0;
for(int w1=0;w1<w;w1++){
for(int h1=0;h1<h;h1++){
int rgb=a.getRGB(w1,h1);
red=(rgb)>> 16;
green=(rgb)>>8;
blue=(rgb);
data2[counter]=(red+green+blue)/3;
counter++;
}
}
return data2;
}
createimage() method:
void createImage(){
double[] data1=getData(colorImage);
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
WritableRaster raster = image.getRaster();
int counter = 0 ;
for(int i = 0; i<h; i++){
for(int j = 0; j<w; j++){
raster.setSample(i, j, 0, data1[counter]);
counter++;
}
}
}
as it looks for me, the i and j in the setSample call must be swapped. (or w and h in BufferedImage)