Convert an image to a 2D array and then get the image back in Java

17,691

I think the reason image is completely black is that SampleModel for Raster is wrong. Here is what i did with your code:

private SampleModel sampleModel;

public int[][] compute(File file)
{
    ...
    sampleModel = raster.getSampleModel();
    ...
}

public java.awt.Image getImage(int pixels[][])
{
    ...
    WritableRaster raster= Raster.createWritableRaster(sampleModel, new Point(0,0));
    for(int i=0;i<w;i++)
    {
        for(int j=0;j<h;j++)
        {
            raster.setSample(i,j,0,pixels[i][j]);
        }
    }

    BufferedImage image=new BufferedImage(w,h,BufferedImage.TYPE_BYTE_GRAY);
    image.setData(raster);
    ...
}

And this worked for me fine. My understanding is that BufferedImage.TYPE_BYTE_GRAY does not select exactly what you need. Something different might work better, but i don't know how exactly those types correspond to color/sample model. And if you know which sample model you need you can just use it:

WritableRaster raster= Raster.createWritableRaster(new PixelInterleavedSampleModel(0, w, h, 1, 1920, new int[] {0}), new Point(0,0));
Share:
17,691
Wayne Rooney
Author by

Wayne Rooney

I am a passionate programmer and just started to learn from SO.

Updated on June 05, 2022

Comments

  • Wayne Rooney
    Wayne Rooney almost 2 years

    I want to convert an image to a 2D array of pixels, do some operations on it and then convert the resulting 2D array back to image. But I am always getting a pure black image as a result. I cannot figure out where I am going wrong. Here is what I am doing.All operations need to be done on a 8 bit grayscale image.

    • Firstly I get the 2D array of pixels.

      public int[][] compute(File file)
      {
      try 
      {
          BufferedImage img= ImageIO.read(file);
          Raster raster=img.getData();
          int w=raster.getWidth(),h=raster.getHeight();
          int pixels[][]=new int[w][h];
          for (int x=0;x<w;x++)
          {
              for(int y=0;y<h;y++)
              {
                  pixels[x][y]=raster.getSample(x,y,0);
              }
          }
      
          return pixels;
      
      }
      catch (Exception e)
      {
          e.printStackTrace();
      }
      return null;
      }
      
    • Then I do some operations on the pixels array

    • Next I convert the array back to the image.

      public java.awt.Image getImage(int pixels[][])
      {
           int w=pixels.length;
           int h=pixels[0].length;
           BufferedImage image=new BufferedImage(w,h,BufferedImage.TYPE_BYTE_GRAY);
           WritableRaster raster=(WritableRaster)image.getData();
           for(int i=0;i<w;i++)
           {
               for(int j=0;j<h;j++)
               {
                   raster.setSample(i,j,0,pixels[i][j]);
               }
           }
      
      File output=new File("check.jpg");
      try {
          ImageIO.write(image,"jpg",output);
      }
      catch (Exception e)
      {
          e.printStackTrace();
      }
      return image;
      }
      

    But I get a complete black image and I am sure that it is not complete black. What should I do to get the correct results?

    EDIT - After applying efan's solution, when I save the image to a file, suppose the pixel value of (0,0) is 68 then on computing the pixel value from the same file it changes sometimes to 70 sometimes to 71.. There is small distortion to each pixel.But it spoils the image as a whole. Is there any fix ?

  • Wayne Rooney
    Wayne Rooney about 11 years
    Thank You for the answer. Now I do not get the black image, but I do not get back the original image even on calling the getImage(int [][]) function just after creating the pixels array without making any changes. And moreover I get the same image even after changing many pixels. Can you tell me the reason and correction. Thank You
  • efan
    efan about 11 years
    I'm not sure I understood this correctly, but have you tried to use getPixel(), setPixel() instead of using getSample(), setSample()? Sample contains only partial info about pixel(e.g. only red from RGB).
  • Wayne Rooney
    Wayne Rooney about 11 years
    AFAIK for grayscale images R=G=B. I have used both the methods. Suppose that the pixel value is 71. Then I modify it to say 70 and write to an image. After that when I read the image back I get some different values like 68, 69 or 70.
  • efan
    efan about 11 years
    Grayscale have only one band in a sample, so yes there should be no difference when using getPixel, getSample(sorry if this was misleading). Also i tried the code several times, and indeed what i got for my specific pixel was not what i set. But this was only for jpg. And as jpg is lossy compression this is kind of expected. Have you tried to use something different than "jpg"? Both png and bmp worked fine for me.
  • Wayne Rooney
    Wayne Rooney about 11 years
    Thank you.. With png images it works perfectly. I was working with LSB's and so compression in jpg images was making my work difficult. This solves the problem.
  • Arjun Prakash
    Arjun Prakash about 9 years
    get only a black and white image.