I don't understand a code to load picture in java

114 Views Asked by At

I am working with OpenCV in java, but I don't understand part of a class that loads pictures in java:

public class ImageProcessor {
  public BufferedImage toBufferedImage(Mat matrix){
    int type = BufferedImage.TYPE_BYTE_GRAY;
    if ( matrix.channels() > 1 ) {
        type = BufferedImage.TYPE_3BYTE_BGR;
    }
    int bufferSize = matrix.channels()*matrix.cols()*matrix.rows();
    byte [] buffer = new byte[bufferSize];
    matrix.get(0,0,buffer); // get all the pixels
    BufferedImage image = new BufferedImage(matrix.cols(),matrix.rows(),type);                    
    final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
    System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);  
    return image;
  }

Main class sends a Mat object to this class.

The result sends BufferedImage but I don't understand targetPixels because this class doesn't use it somewhere else. But whenever I comment targetPixels and System.arraycopy, result shows black picture.

I want to know what's targetPixels - and what does it do?

3

There are 3 best solutions below

2
GhostCat On BEST ANSWER

The point is less about that array, but the methods that get you there.

You start here: getRaster(). That is supposed to return a WritableRaster ... and so on.

That class is using from getDataBuffer() from the Raster class; and there we find:

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.

What happens in essence here: that Image object, in the end has an array of bytes that are supposed to contain certain information.

That assignment:

final byte[] targetPixels = ...

retrieves a reference to that internal data; and then arrayCopy() is used to copy data into that array.

For the record: that doesn't look like a good approach - as it only works when this copy action really affects the internals of that Image object. But what if that last call getData() would create a copy of the internal data?

In other words: this code tries to gain direct access to internal data of some object; and then manipulate that internal data.

Even if that works today, it is not robust; and might break easily in the future. The other thing: note that this code does a unconditional cast (DataBufferByte). That code throws a RuntimeException if the the buffer doesn't have exactly that type.

Probably that is "all fine"; since it is all related to "AWT" classes which probably exist for ages; and will not change at all any more. But as said; this code has various potential issues.

0
Steve Smith On

targetPixels is the main image data (i.e. the pixels) of your new image. The actual image is created when the pixeldata is copied from buffer into targetPixels.

0
Bartha Barna On

targetPixels is the array of bytes from your newly created BufferedImage, those bytes are empty thus you need to copy the bytes from the buffer to it with System.arraycopy.. :)