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

时间:2016-08-25 08:12:01

标签: android memory bitmap png

我需要创建并保存单色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的内存似乎太过分了。

有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

您可以使用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();   
 }
  

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

这里有两件不同的事情。首先,浪费空间以便在内存中分配完整的图像 - 我的解决方案通过分配单行来解决这个问题。但是,除此之外,您正在犯一个概念上的错误:将内存中分配的空间与编码图像大小进行比较是没有意义的,因为PNG是一种压缩格式(单个彩色图像将被高度压缩)。由任何原始可编辑位图(Android中的Bitmap,ImageIO中的BufferedImage,我自己的PNGJ中的ImageLineByte或其他任何内容)分配的内存将永远不会被压缩,因此它将永远每个像素浪费4个字节 - 至少。你可以检查:1200x1200x4 = 5760000。

答案 1 :(得分:0)

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

它会更有效率。

虽然,您可以为视图设置颜色背景。

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

P.S。

ALPHA_8不存储颜色,只有alpha。这完全错了,请查看文档