如何减小透明位图的大小(不是尺寸)

3
在我的安卓应用程序中,我正在处理画布位图(实际上是三星SPen SDK中的SCanvas,但这并不重要)。通常,这些位图的90-95%区域是透明的,因此我预计其文件大小不会太大。但似乎位图的文件大小(以KB为单位)与其是简单背景还是复杂图片无关,例如,如果我有两个图像:

1)空框架(1000x700像素,背景透明,颜色边框)

2)完整框架(1000x700像素,背景透明,颜色边框,内部有很多文本)

这两个位图的大小约为1.3MB。

但是,如果我将这些位图转换为字节数组,则第一个数组的大小约为第二个数组的11倍。

我必须将许多这样的图像作为BLOB存储在数据库中,并将它们显示为ImageView位图。

问题1:如果我需要显示20个带有95%透明图像的ImageView对象,是否有任何方法可以不同时使用20 * 1.3MB?对我来说,似乎只应该有1个alpha层+ 20个“数据”层。

问题2:是否有任何方法可以减小带有透明度的图像的大小(以KB为单位)而不会失去太多质量?我看到的唯一方法是使用inSampleSize = 2解码图像字节数组,然后创建一个缩放的位图以保持原始图像尺寸,类似于:

originalBitmap.compress(Bitmap.CompressFormat.PNG, 0, stream);
byte[] bitmapBytes = stream.toByteArray();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length, options);
int bWidth = options.outWidth;
int bHeight = options.outHeight;
options.inSampleSize = 2;
options.inPreferredConfig = Bitmap.Config.ARGB_4444;
options.inJustDecodeBounds = false;
Bitmap scaledBitmap = BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length, options);
Bitmap finalBitmap = Bitmap.createScaledBitmap(scaledBitmap, bWidth, bHeight, true);

但是无论我使用什么选项(inPreferredConfig、inDither),最终位图的质量都是不可接受的。

对于大约90%具有简单透明背景和10%单色“数据”的图片,您有没有其他处理方式的想法?


如果您正在使用ImageView,必须使用Drawable而不是Bitmap。 - Mohammad Ersan
1
如果你正在使用资源,我认为这是更方便的方法。对于字节数组,有什么好处呢?https://dev59.com/SGw05IYBdhLWcg3wxUj_#7045044 - zmiter.freeman
使用以下代码将位图转换为可绘制对象。BitmapDrawable bitmapDrawable = new BitmapDrawable(originalBitmap); imageView.setImageDrawable(bitmapDrawable); - Mohammad Ersan
考虑逐个打开它们,并绘制到主位图上。因此,同时只有2个图像加载在内存中。附注:尽可能使用insample大小。 - IAmGroot
1个回答

1
无论您使用什么格式,它在显示之前总是以原始未压缩(解码)数据结束,如果没有解码,您就无法在显示器上看到它。如果您担心内存问题,请尽量不要一直解码所有图像,只需解码需要显示的图像,并始终释放其他图像(不要保留对它们的引用)。

我使用PNG转换。假设您有一个带有透明背景和仅一个颜色像素“数据”的1000x700画布。然后您执行以下操作(粗略示例):'code' canvas.getBitmap().compress(Bitmap.CompressFormat.PNG, 0, stream);byte[] item = stream.toByteArray();Bitmap finalBitmap = BitmapFactory.decodeByteArray(item, 0, item.length); 'code',最终的finalBitmap大小为1.3MB。 - zmiter.freeman
1
你的问题是存储位图还是显示它?压缩为PNG格式再解压缩并不能帮助你。如果最终需要使用位图,那么你无能为力。对于给定分辨率和颜色深度,所有位图的大小都相同。如果只是用于显示,你为什么要关心大小呢?如果想要存储它们,以PNG格式存储,不要在存储之前解压缩。 - Zoltán
场景很简单:从数据库中获取20个BLOB,将它们解码为可以在20个ImageView中显示的任何内容,这些ImageView又位于ScrollView中。这样一来,我大约需要20*1.3MB的内存使用量 - 这意味着我需要在将BLOB存储到数据库之前以某种方式减小图像大小(而不是尺寸)。你有什么办法可以在不失去alpha层(它占图像的90-95%)和太多质量的情况下完成吗? - zmiter.freeman
1
使用26MB是一件大事。在PC上可能不算什么,但在Android设备上,您会一次性耗尽所有可用的应用内存(在某些设备上 - 并且在所有设备上并没有好多少)。 - IAmGroot
1
@zmiter.freeman 这是事实。ARGB_4444位图中的每个像素将占用2个字节,因此您的1000x700变成了1.37MB。唯一的解决方法是在绝对需要显示它之前不将其保留为位图。 - Mark Ransom
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接