1

So I have a byte array representing pixel data (8bit grayscale). No header. No nothing. Just the data. I want to create a buffered image from this data. I did

image = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
image.getRaster().setDataElements(0, 0, w, h, data);
this.x = w;
this.y = h;
scalemode=false;
exactmode=true;

where w is just width in pixel,h is height in pixel,data is the byte array and image is BufferedImage

here is my paint method

 protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        int rx = (this.getWidth() - x) / 2;
        int ry = (this.getHeight() - y) / 2;

        g2d.drawImage(image, rx, ry,x,y, null);
    }

I, however, get this image (the real image is a fingerprint, which is mostly white pixel)

messed up image

What went wrong? I tried saving the data as is and then viewing it in Photoshop. The data is fine.

[edit] Never mind this problem. I fucked up in other part of the code and was not aware. Thank you for all inputs though

5
  • What type is data? Commented Aug 20, 2015 at 4:14
  • data is byte[] 1byte = 1pixel Commented Aug 20, 2015 at 4:15
  • draw every byte on each pixel... Commented Aug 20, 2015 at 5:27
  • Is that 1 pixel border part of the image? Commented Aug 20, 2015 at 6:42
  • no border is not the part of the image Commented Aug 20, 2015 at 8:15

3 Answers 3

2

It's hard to know exactly what is wrong, as you haven't posted enough information. We don't know w, h or what information is in your data. We don't know what the image should look like.

However, here's some code that does pretty much exactly what you are doing, and it works for me:

// Set up h/w and backing data
int w = 300;
int h = 200;
byte[] data = new byte[w * h];

// Create a smooth gradient
for (int y = 0; y < h; y++) {
    int off = y * w;

    for (int x = 0; x < w; x++) {
        data[off + x] = (byte) (Math.round((x / (double) w) * 127) 
                              + Math.round((y / (double) h) * 127));
    }
}

// Create BufferedImage from data
final BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
image.getRaster().setDataElements(0, 0, w, h, data);

// Show it all in a window
SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        JFrame frame = new JFrame(getClass().getSimpleName());
        frame.add(new JLabel(new ImageIcon(image)));

        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
});

Here is the result:

Image of JFrame from above code

Sign up to request clarification or add additional context in comments.

4 Comments

the image provided by Green Melon really looks like it has incorrect values for width and height..
I just tried testing the whole thing, and I found that if the image is created in a nice single main thread, the image is fine. However, when I created the image in mouse event listener thread, the image becomes garbled! I just realized that the data (the byte array) is already messed up so there is no way I can get it right. Do you know what might be the problem in reading from BufferedinputStream from listener thread? I used the code from here. Particularly, the upImg method
@GreenMellon Ok. No problem. :-) Reading from streams should work just as normal from the listener thread, but for the sake of a responsive UI it is strongly discouraged. Generally, all I/O should be done on a background thread. Anyway, glad you figured it out!
Turned out that the fingerprinting module I was working with actually modify its image buffer when it convert image to signature file. I am totally lost as to why (small memory?). So it had nothing to do with Java. Thanks for the tip though
1

draw every byte on each pixel...

BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
for (int dy = 0; dy < h; dy ++){
    for(int dx = 0; dx < w; dx ++){
        int index = dy*w + dx;
        int rgb = data[index];
        rgb = rgb << 24 & 0xFFFF; //BufferedImage.TYPE_BYTE_GRAY consideres only the red-channel;
        //rgb = 00 data[index] FF FF
        image.setRGB(dx,dy,rgb);
        }
    }
}

Comments

-1

you didn't set up your Buffer properly...

byte[] data = ... 
DataBufferByte db = new DataBufferByte(data, w*h);
image.getRaster().setDataElements(0, 0, w, h, db );

see http://docs.oracle.com/javase/7/docs/api/java/awt/image/WritableRaster.html#setDataElements%28int,%20int,%20java.lang.Object%29

6 Comments

The method you are looking for is setDataElements(x, y, w, h, data). And to quote the docs: "Sets the data for a rectangle of pixels from a primitive array of type TransferType" (emphasis mine). This answer is clearly incorrect. The OP's code is fine in this regard.
@haraldK yes, read on and you'll find " For image data supported by the Java 2D API, this will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE"... so where's the error?
You seem to think that DataBuffer.TYPE_BYTE == DataBufferByte. It isn't. A "primitive array of type DataBuffer.TYPE_BYTE" simply means byte[].
well, no that's now what i was thinking ^ ^ (DataBufferByte.getType() would return DataBuffer.TYPE_BYTE - but that's leading to no-where)...i'll aprechiate your example and accept that your code is working. As mentioned in an comment in your example i guess the OP has merely problems with not knowing width/height... @haraldK thanks for providing a good example...
I think so too. That is why I ask about the border. And for the record, your code above will crash at runtime, with the following exception: java.lang.ClassCastException: java.awt.image.DataBufferByte cannot be cast to [B. ;-)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.