You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:52:43