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

Android如何直接读写Bitmap像素数据?或Canvas单像素读写方案

Android 高效操作Bitmap像素的方案

一、直接访问Bitmap的像素内存(推荐)

Android的Bitmap提供了lockPixels()方法,可直接获取像素缓冲区的内存地址,无需复制整个像素数组,和你在Windows下操作DIB的逻辑类似。

核心步骤:

  1. 确保Bitmap是可修改的(mutable):如果是从资源、文件加载的Bitmap,默认不可修改,需调用bitmap.copy(Bitmap.Config.ARGB_8888, true)生成可修改副本。
  2. 调用lockPixels()获取像素缓冲区的直接访问权,返回ByteBuffer(Java层)或内存指针(NDK层)。
  3. 根据Bitmap的像素格式计算像素偏移量,直接读写内存中的像素值。
  4. 操作完成后必须调用unlockPixels()释放锁,避免内存泄漏或Bitmap状态异常。

Java层代码示例(修改6×12的小区域):

// 假设已有原始Bitmap对象,先转为可修改副本
Bitmap mutableBitmap = originalBitmap.copy(Bitmap.Config.ARGB_8888, true);

// 锁定像素内存
ByteBuffer buffer = (ByteBuffer) mutableBitmap.lockPixels();
if (buffer != null) {
    int startX = 10; // 区域起始X坐标
    int startY = 20; // 区域起始Y坐标
    int width = 6;
    int height = 12;
    int stride = mutableBitmap.getRowBytes(); // 每行字节数(因内存对齐可能大于width*4)
    int pixelSize = 4; // ARGB_8888格式每个像素占4字节

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            // 计算当前像素的字节偏移量
            int offset = (startY + y) * stride + (startX + x) * pixelSize;
            // 写入ARGB像素值(示例为红色)
            buffer.putInt(offset, 0xFFFF0000);
        }
    }
    // 解锁像素内存
    mutableBitmap.unlockPixels();
}

注意事项:

  • 优先使用ARGB_8888格式,兼容性最好且内存访问逻辑简单;若用RGB_565等其他格式,需调整像素大小和读写方式。
  • 追求极致性能的话,可结合NDK用C/C++直接操作内存指针,效率比Java层更高。

二、用Canvas高效修改小区域

如果你的操作是批量修改矩形区域(比如6×12的单元),直接用Canvas配合Paint绘制更高效——底层会利用硬件加速,比手动操作像素更快。

代码示例:

// 创建可修改的Bitmap
Bitmap mutableBitmap = originalBitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(mutableBitmap);
Paint paint = new Paint();

// 绘制纯色填充的6×12区域(替换对应像素)
paint.setColor(Color.RED);
canvas.drawRect(startX, startY, startX + 6, startY + 12, paint);

// 清除该区域像素(设为透明)
paint.setColor(Color.TRANSPARENT);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(startX, startY, startX + 6, startY + 12, paint);

三、单个像素读写的优化

如果必须读写单个像素,不要频繁调用getPixel()和setPixel()——这两个方法每次都会锁/unlock Bitmap内存,开销极大。推荐两种优化方式:

  1. 一次性锁定内存后批量操作(参考第一部分的方案);
  2. 仅复制需要的小区域像素数组,修改后写回:
int[] pixels = new int[6 * 12];
// 仅复制6×12区域的像素到数组
mutableBitmap.getPixels(pixels, 0, 6, startX, startY, 6, 12);

// 修改数组中的像素值(示例为绿色)
for (int i = 0; i < pixels.length; i++) {
    pixels[i] = 0xFF00FF00;
}

// 将修改后的数组写回Bitmap
mutableBitmap.setPixels(pixels, 0, 6, startX, startY, 6, 12);

这种方式只复制目标区域,比getPixels()复制整个Bitmap的开销小很多。

内容的提问来源于stack exchange,提问作者theDickChuck

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 10:45:41