在 Android 中创建和保存单色 PNG 位图时减少内存使用

Reducing memory usage while creating and saving a single color PNG bitmap in Android

我需要创建并保存单色 PNG 图像(用单色填充的位图)。

我正在创建位图:

public static Bitmap createColorSwatchBitmap(int width, int height, int color) {
    final Bitmap colorBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    colorBitmap.eraseColor(color);
    return colorBitmap;
}

并将其保存到设备存储上的文件中:

stream = new FileOutputStream(filePath);
success = bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);

如果我创建 1200x1200 位图,内存消耗为 5,760,000 字节 (5.76 MB),如 bitmap.getAllocationByteCount() 所报告。但是 PNG 文件大小只有 8,493 字节。

为一个只有 8 KB 的文件分配近 6 MB 的内存似乎太过分了。

有没有更好的方法?

您只用一种颜色填充位图。 为什么不直接将颜色存储在 SharedPreferences 中?

效率会高很多

不过,您可以只为视图设置颜色背景。

其他选项是创建具有必要颜色的 1x1 像素大小的位图,并将其设置为背景。它将成为视图的大小。

P.S.

ALPHA_8 不存储颜色,只存储 alpha。完全错误,查看文档

您可以使用 PNGJ 库(免责声明:我是作者)。因为是渐进保存图片,所以只需要分配一行。

例如:

 public static void create(OutputStream os,int cols,int rows,int r,int  g,int  b,int  a)  {     
        ImageInfo imi = new ImageInfo(cols, rows, 8, true); // 8 bits per channel, alpha
        PngWriter png = new PngWriter(os, imi);
        // just a hint to the coder to optimize compression+speed:
        png.setFilterType(FilterType.FILTER_NONE); 
        ImageLineByte iline = new ImageLineByte (imi);
        byte[] scanline = iline.getScanlineByte();// RGBA
        for (int col = 0,pos=0; col < imi.cols; col++) { 
           scanline[pos++]=(byte) r;  
           scanline[pos++]=(byte) g;
           scanline[pos++]=(byte) b;
           scanline[pos++]=(byte) a;
        }
        for (int row = 0; row < png.imgInfo.rows; row++) {
           png.writeRow(iline);
        }
        png.end();   
 }

It seems so overkill to allocate almost 6 MB of memory for a file that will only have 8 KB.

这里有两个不同的东西。首先,为了在内存中分配完整图像而浪费了 space - 我的解决方案通过分配一行来缓解这一点。但是,除此之外,您犯了一个概念错误:将内存中分配的 space 与编码图像大小进行比较是没有意义的,因为 PNG 是一种压缩格式(并且单个彩色图像将被高度压缩).任何原始可编辑位图(Android中的Bitmap、ImageIO中的BufferedImage、PNGJ中我自己的ImageLineByte等)分配的内存实际上永远不会被压缩,并且因此它总是会浪费每个像素 4 个字节 - 至少。你可以检查:1200x1200x4=5760000。