如何通过Java BufferedImage.getSubimage获取指定区域的字节数组
提取8位灰度BufferedImage裁剪区域的独立字节数组
问题原因
getSubimage()返回的子图共享原图像的数据缓冲区,所以直接调用getData()会拿到整个原图的字节数组,而非仅裁剪区域的数据。要获取裁剪区域的独立字节数组,可通过以下两种方式实现:
方法一:手动提取裁剪区域字节(高效)
因为8位灰度图每个像素对应1个字节,可直接根据裁剪坐标从原字节数组中计算偏移量,逐行复制目标区域:
// 解析roiLimits参数:[x起始坐标, 裁剪宽度, y起始坐标, 裁剪高度] int xStart = roiLimits[0]; int cropWidth = roiLimits[1]; int yStart = roiLimits[2]; int cropHeight = roiLimits[3]; int originalWidth = img.getWidth(); // 初始化存储裁剪数据的数组(100*50=5000字节) byte[] outputBytes = new byte[cropWidth * cropHeight]; int outputIdx = 0; // 逐行复制裁剪区域的字节 for (int y = yStart; y < yStart + cropHeight; y++) { // 计算当前行在原数组中的起始偏移位置 int rowOffset = y * originalWidth + xStart; // 复制当前行的裁剪部分到输出数组 System.arraycopy(origBytes, rowOffset, outputBytes, outputIdx, cropWidth); outputIdx += cropWidth; }
这种方式无需创建额外图像对象,性能更高效。
方法二:创建独立BufferedImage(直观)
如果需要保留裁剪后的图像对象,可创建一个新的独立BufferedImage,将子图内容绘制进去,再提取数据:
int cropWidth = roiLimits[1]; int cropHeight = roiLimits[3]; // 创建新的独立8位灰度图,尺寸为裁剪区域大小 BufferedImage croppedImage = new BufferedImage(cropWidth, cropHeight, BufferedImage.TYPE_BYTE_GRAY); Graphics2D g = croppedImage.createGraphics(); try { // 将子图绘制到新图像中,完成数据复制 g.drawImage(roiSubImage, 0, 0, null); } finally { g.dispose(); } // 提取新图像的字节数组,此时仅包含裁剪区域数据 DataBufferByte croppedBuffer = (DataBufferByte) croppedImage.getRaster().getDataBuffer(); byte[] outputBytes = croppedBuffer.getData();
新图像拥有独立的数据缓冲区,提取的字节数组就是目标的5000字节数据。
内容的提问来源于stack exchange,提问作者WolfiG
相关产品推荐
相关产品推荐

