BufferedImage : extract subimage with same data

I would like to extract a rectangle of a BufferedImage.

Javadoc propose getSubImage(x,y,w,h) and getData(rectangle).

getData is cool but I don't want only the raster. I want the subimage as a BufferedImage object but I also need a modified version of it data array but the javadoc says

public BufferedImage getSubimage(int x,int y,int w,int h) : Returns a subimage defined by a specified rectangular region. The returned BufferedImage shares the same data array as the original image .

Q: how can I extract a subimage with a shrinked data array ?


Given a BufferedImage image, here's 3 ways to create a "deep" copy subimage:

// Create an image
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR);

// Fill with static
new Random().nextBytes(((DataBufferByte) image.getRaster().getDataBuffer()).getData());

Create an image around the already deep copy of the Raster you get from getData(rect) . This involves casting to WritableRaster , so it may break with some Java implementations or in the future. Should be quite fast, as you only copy the data once:

// Get sub-raster, cast to writable and translate it to 0,0
WritableRaster data = ((WritableRaster) image.getData(new Rectangle(25, 25, 50, 50))).createWritableTranslatedChild(0, 0);

// Create new image with data
BufferedImage subOne = new BufferedImage(image.getColorModel(), data, image.isAlphaPremultiplied(), null);

Another option, creating a sub image the "normal way", then copying the raster into a new image. Involves creating one sub-raster, still copies only once (and no casting):

// Get subimage "normal way"
BufferedImage subimage = image.getSubimage(25, 25, 50, 50);

// Create empty compatible image
BufferedImage subTwo = new BufferedImage(image.getColorModel(), image.getRaster().createCompatibleWritableRaster(50, 50), image.isAlphaPremultiplied(), null);

// Copy data into the new, empty image
subimage.copyData(subTwo.getRaster());

Finally, the easier route, just painting the subimage over a new empty image. Could be slightly slower, as it involves the rendering pipeline, but I think it should perform reasonably still.

// Get subimage "normal way"
BufferedImage subimage = image.getSubimage(25, 25, 50, 50);

// Create new empty image of same type
BufferedImage subThree = new BufferedImage(50, 50, image.getType());

// Draw the subimage onto the new, empty copy
Graphics2D g = subThree.createGraphics();
try {
    g.drawImage(subimage, 0, 0, null);
}
finally {
    g.dispose();
}

I had the same issue a long time ago, I didn't want a shared raster. The only solution I found was to create a BufferedImage that represents the sub-image, and then copy the pixels into the sub-image.

In order to have something really fast, I access directly the DataBuffer and I make array copies (line by line) using System.arraycopy()

链接地址: http://www.djcxy.com/p/40784.html

上一篇: 如何克隆C#中的通用列表?

下一篇: BufferedImage:用相同的数据提取子图像