Marcono1234 Marcono1234 - 2 months ago 28
Java Question

How to read data array of sub image raster

In this question ("get pixel array from image") the answer was to get the data of the raster:

int[] pixels = ((DataBufferInt) bufferedImage.getRaster().getDataBuffer()).getData();


However, when you use this for sub images it will return the data array of the base image:


Returns a subimage defined by a specified rectangular region. The
returned BufferedImage shares the same data array as the original
image
.


The methods
getTileGridXOffset()
and
getTileGridYOffset()
return the offset despite being described as


Returns the x offset of the tile grid relative to the origin, For
example, the x coordinate of the location of tile (0, 0). This is
always zero.



but it looks like the field
scanlineStride
of the raster which would be required to get the index in the array cannot be accessed.




Other solutions



Would it be faster and easier then to use
getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)
?




Concrete example



BufferedImage baseBufferedImage = new BufferedImage(2048, 2048, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = baseBufferedImage.createGraphics();
graphics.setColor(Color.BLUE);
graphics.fillRect(512, 512, 100, 100);
graphics.dispose();

BufferedImage subBufferedImage = baseBufferedImage.getSubimage(512, 512, 100, 100);
int[] subBufferedImageData = ((DataBufferInt) subBufferedImage.getRaster().getDataBuffer()).getData();
// This is not 255 despite the pixel at 0,0 in subBufferedImage being blue
System.out.print(subBufferedImageData[0] & 0xFF);

Answer

If you need the sub image (as a BufferedImage), you can do:

BufferedImage subBufferedImage = baseBufferedImage.getSubimage(512, 512, 100, 100);
// NOTE: getData() creates a copy of the raster/databuffer in contrast to getRaster()
int[] subBufferedImageData = ((DataBufferInt) subBufferedImage.getData(new Rectangle(0, 0, 100, 100)).getDataBuffer()).getData();
System.out.print(subBufferedImageData[0] & 0xFF);

Otherwise, you can simply skip the sub image, and create a copy of the requested region of the raster directly, like this:

// Creates a copy of the sub region from the raster/databuffer
int[] subBufferedImageData = ((DataBufferInt) baseBufferedImage.getData(new Rectangle(512, 512, 100, 100)).getDataBuffer()).getData();
System.out.print(subBufferedImageData[0] & 0xFF);

Both examples will print 255, and have arrays containing all blue pixels.

Wether or not you find using getRGB easier to use is completely subjective and up to you. The above code is likely to be faster, or worst case as fast (I'm leaving the actual testing to you).