0

EDIT 3:

    int rRows = result.length;
    int rColums = result[0].length;

    BufferedImage img = new BufferedImage(rColums, rRows, BufferedImage.TYPE_BYTE_GRAY);
    for (int r = 0; r < rRows; r++) {
        for (int t = 0; t < result[r].length; t++) {
            img.setRGB(t, r, result[r][t]);   

EDIT2:

Created the image like so....

 BufferedImage img = new BufferedImage(rColums, rRows,BufferedImage.TYPE_BYTE_GRAY)  


private static int[][] convertToArray(BufferedImage inputImage) {

final byte[] pixels = ((DataBufferByte) inputImage.getRaster().getDataBuffer()).getData(); 


final int width = inputImage.getWidth();

final int height = inputImage.getHeight();  
System.out.println("height" + height + "width");

int[][] result = new int[height][width];

for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel++)     {

 int argb = 0;

  argb = (int) pixels[pixel];


result[row][col] = argb;

col++;

if (col == width) {

 col = 0; 

 row++;

 }

 }

 return result;

                                                                                            

Edit:

I've realized what I'm trying to ask is how to go from signed grayscale to unsigned grayscale, as I said adding 256 didnt work for me and also that would still seem to leave the image to dark as it wont raise the value of the +127 signed values to 256 unsigned.(hopefully I've expressed that correctly.

As per title I've an int[][] extracted from a buffered image via

 ((DataBufferByte) inputImage.getRaster().getDataBuffer()).getData()

The array ranges from -128 to 127. The problem is that when I attempt to reconstruct the image based on the int[][] by passing it to BufferedImage, it comes out too dark, and more like a black and white(mostly black) image.

I saw suggestion to add 256 to each sub zero value of the byte[] produced by the DataBufferByte, in the process of converting byte[] to in[][], but this actually produces a totally black image and I dont really get the logic of it, Like wouldnt you want to shift the entire scale over by 128, rather than just the negative numbers??

Ciaran
  • 23
  • 6
  • Your question contains the raster data but says nothing about the ColorModel. You should address that in your question since that is the issue. [This](https://stackoverflow.com/questions/9131678/convert-a-rgb-image-to-grayscale-image-reducing-the-memory-in-java) or [This](https://stackoverflow.com/questions/6471340/how-do-i-desaturate-a-bufferedimage-in-java/6471524#6471524) or [This](https://stackoverflow.com/questions/32109428/java-greyscale-buffered-image) might help. – Randy Casburn May 24 '21 at 15:31
  • Do you mean like this------ BufferedImage img = new BufferedImage(rColums, rRows, BufferedImage.TYPE_BYTE_GRAY) --------------- This was how I created the new BufferedImage – Ciaran May 24 '21 at 15:34
  • *"The problem is that when I attempt to reconstruct the image based on the int[][] by passing it to BufferedImage, it comes out too dark"* How exactly do you do this? As @ThomasFritsch already correctly explained how to convert from signed to unsigned an back, it's just as likely the problem is in this part of the code. But we've only seen the other half. – Harald K May 24 '21 at 20:24
  • @HaraldK Okay didnt do good job of posting the question. Ive updated to include image construction. Thomas' answer has disappeared for me. – Ciaran May 25 '21 at 10:30

1 Answers1

1

When you're writing your conversion. You have a signed byte, and you need to convert it to an ARGB int.

int unsignedByte = pixels[pixel]&0xff;

Now that isn't quite finished because we need it to be argb/grayscale.

argb = ( unsignedByte << 16 ) + ( unsignedByte << 8 ) + unsignedByte;

I've ignored the A part and just added rgb components. There is quite some documentation on this though.

Here is a complete example you can play with.

import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
import java.util.HashSet;
import java.util.Set;
public class GrayScales{
    public static void main(String[] args){
        BufferedImage img = new BufferedImage( 256, 256, BufferedImage.TYPE_BYTE_GRAY );
        Graphics g = img.createGraphics();
        g.setColor( new Color( 128, 128, 128) );
        g.fillOval( 32, 32, 192, 192 );
        g.setColor( new Color( 255, 255, 255) );
        g.fillOval( 96, 96, 64, 64 );
        g.dispose();
        BufferedImage dup = new BufferedImage( 256, 256, BufferedImage.TYPE_BYTE_GRAY );
        byte[] pixels = ((DataBufferByte) img.getRaster().getDataBuffer()).getData();
        Set<Integer> ints = new HashSet<>();
        for(int i = 0; i<256; i++){
            for(int j = 0; j<256; j++){
                int px = (pixels[j*256 + i])&0xff;
                ints.add(px);
                int rgb = (px << 16) + (px << 8) + (px);
                dup.setRGB(i, j, rgb);
            }
        }
        System.out.println(ints);
        JFrame frame = new JFrame("compare");
        JLabel a = new JLabel( new ImageIcon( img ) );
        JLabel b = new JLabel( new ImageIcon(dup) );
        
        frame.add(a, BorderLayout.EAST);
        frame.add(b, BorderLayout.WEST);
        frame.pack();
        frame.setVisible(true);
    }
}
matt
  • 10,892
  • 3
  • 22
  • 34
  • That worked like 95+% , image is a bit darker but pretty much correct. Thank you. Does the fact that its a little dark means I need to work on the alpha component? Frankly I'm a little confused at what exactly all this means, I'm very new to programming so the documentation tends to leave me with more questions than answers and I'm just trying to piece together different fragments from things I find online. Is there any good book or site you would recommend for learning about this? Thanks again btw. – Ciaran May 25 '21 at 11:20
  • Ah I changed the BufferedImage to TYPE_INT_RGB and it displays perfectly. Still quite confused but happy that it working! – Ciaran May 25 '21 at 11:24
  • It isn't the alpha portion, you can add full alpha by using `int rgb = (255<<24) + (px << 16) + (px << 8) + (px);` It doesn't change anything for me though. – matt May 25 '21 at 11:25
  • I'm not sure of a good book. Graphics processing and color spaces can be quite in depth. Essentially you know the data type for your color model, byte. The method [setRGB](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/image/BufferedImage.html#setRGB(int,int,int)) assumes the value provided is a particular data type and color space. So when you do setRGB there is a calculation that converts the RGB value to an approximate value in your model. – matt May 25 '21 at 11:30
  • Its strange cause in my code the input image is TYPE_GRAY, yet when I use use setRGB() it doesnt display quite correctly unless the o/p BufferedImage is TYPE_INT_RGB. Anyway thanks very much for your assistance. – Ciaran May 25 '21 at 12:26
  • @Ciaran Yeah, setRGB is a weird method. We created a gray color (128, 128, 128) and we painted it with a Graphics object. This led to a byte value of 128. It would make sense that setRGB(i, j, gray.getRGB()); should produce the same gray value. It doesn't. What would produce the same gray value is to use 'getRGB' on source image instead of trying to convert it's backing data to a corresponding RGB integer. – matt May 25 '21 at 13:50