【问题标题】:How to reduce the transparent bitmap size (not dimensions)如何减小透明位图大小(不是尺寸)
【发布时间】:2012-10-29 18:39:48
【问题描述】:

在我的 android 应用程序中,我正在处理画布位图(实际上它是来自三星 SPen SDK 的 SCanvas,但没关系),通常此类位图的 90-95% 区域是透明的,所以我希望有以 KB 为单位的位图大小不要太大。但似乎位图大小(以 KB 为单位)并不取决于它是简单的背景还是复杂的图片,所以例如,如果我有两张图片(对不起,我是新用户,我不能发布任何图片):

1) 空框(1000x700 px,背景透明,彩色边框)

2) 全画幅(1000x700 px,背景透明,彩色边框,里面有很多文字)

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

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

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

问题1:如果我需要显示20个ImageView对象,这样95%的透明图像,有什么办法不同时使用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),finalBitmap 的质量都是不可接受的。

对于处理具有大约 90% 的简单透明背景和 10% 的单色“数据”的图像的最佳方式有什么想法吗?

【问题讨论】:

  • 如果你使用 ImageView,你必须使用 Drawable 而不是 Bitmap。
  • 如果您使用资源,我会说这是更方便的方式。如果是字节数组,有什么好处? stackoverflow.com/a/7045044/1811746
  • 使用此代码将位图转换为可绘制对象。 BitmapDrawable bitmapDrawable=new BitmapDrawable(orginalBitmap); imageView.setImageDrawable(bitmapDrawable);
  • 考虑将它们一个一个打开,然后绘制到主位图上。所以只有2个图像同时加载到内存中。 p.s.尽可能保持样本大小。

标签: android image-processing bitmap transparency out-of-memory


【解决方案1】:

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

【讨论】:

  • 我确实使用 png 转换。假设您有 1000x700 的画布,背景透明,只有一个颜色像素 - “数据”。然后执行以下操作(粗略示例): 'code' canvas.getBitmap().compress(Bitmap.CompressFormat.PNG, 0, stream);byte[] item = stream.toByteArray();Bitmap finalBitmap = BitmapFactory.decodeByteArray(项目,0,项目。长度); 'code' 和 finalBitmap 的大小为 1.3MB。
  • 您的问题是存储位图还是显示它?压缩为 PNG 和解压缩对您没有帮助。如果最终需要使用位图,则无能为力。对于给定的分辨率和颜色深度,所有位图都具有相同的大小。如果只是为了展示,你为什么关心大小?如果你想存储它们,将它们存储为PNG,存储前不要解压。
  • 场景很简单:获取例如来自 DB 的 20 个 BLOB,将它们解码为您可以在 20 个 ImageView 中显示的任何内容,这些 ImageView 又在 ScrollView 中显示。这样我就有大约 20*1.3MB 的内存使用量——这意味着我需要在将 BLOB 存储到数据库之前以某种方式减小图像大小(而不是尺寸)。您知道如何在不丢失 alpha 层(图像的 90-95%)和过多质量的情况下做到这一点吗?
  • 使用 26MB 是一笔巨大的交易。也许不是在 PC 上,而是在 android 设备上,您将一次性耗尽所有可用的应用程序内存(在某些设备上 - 在所有设备上也好不到哪里去。)。
  • @zmiter.freeman 这是事实。 ARGB_4444 位图中的每个像素将占用 2 个字节,因此您的 1000x700 变为 1.37MB。解决它的唯一方法是在绝对需要显示之前不要将其保留为位图。
猜你喜欢
  • 2011-12-26
  • 2011-08-02
  • 1970-01-01
  • 1970-01-01
  • 2020-01-24
  • 2014-07-03
  • 1970-01-01
  • 2014-01-11
  • 2015-01-27
相关资源
最近更新 更多