1

我只是想看看是否有其他人注意到,当将图像加载到内存中时,完全相同的 C# 代码会使用更多内存来保存图像(大约是 Java 的 1.5 倍)。

此 Java 代码导致总内存大小为105.5 MB

Bitmap[] bitmaps = new Bitmap[100];

for (int i = 0; i < 100; i++)
{
    String root = Environment.getExternalStorageDirectory().getAbsolutePath();
    String imagePath = "/evolution/threesixty/216/Edaphosaurus_001.jpg";

    bitmaps[i] = BitmapFactory.decodeFile(root + imagePath);
}

此 C# 代码产生148.1 MB

Bitmap[] bitmaps = new Bitmap[100];

for (int i = 0; i < 100; i++)
{
    string root = Environment.ExternalStorageDirectory.AbsolutePath;
    string imagePath = "/evolution/threesixty/216/Edaphosaurus_001.jpg";

    bitmaps[i] = BitmapFactory.DecodeFile(root + imagePath);
}  

有人对为什么有任何想法吗?我知道 .NET 包装器可能会使用更多来保存额外的绑定数据或东西,但肯定不会那么多吗?

另外,作为一个附带问题:每个图像在磁盘上只有60 KB,为什么内存版本是1 MB?我知道我的加载方法不会进行任何采样/密度检查,但这不是目的。确定加载 <100KB 的图像不应超过 100KB 的内存空间?

这是我正在使用的图像(994x748px @ 300dpi):

图片

4

2 回答 2

4

100 张图像的 148.1 MB 数字正是我对此的预期。994 x 748 提供 743,512 像素;假设您使用的是每像素使用 2 个字节的格式(这对于图像的质量非常低,FWIW - RGB565 格式应该在几十年前在国际上被禁止),那么每张图像为您提供 1.481 MB。这当然比磁盘上的图像大小要大得多,因为图像文件是经过压缩的。

我不知道为什么 Java 版本只消耗 105.5 MB;据我所知,没有一种位图格式每像素使用 1.333 个字节。很可能您读错了内存使用情况,或者 Java 运行时将一些图像缓存到磁盘而不是将它们保存在内存中。

于 2012-06-18T14:07:34.797 回答
2

基于 Mono for Android 邮件列表的回复:

您正在加载的图像是 jpg 压缩的。位图是一种未压缩的格式。谷歌搜索显示典型的 JPEG 压缩比为 10:1 到 20:1,而不会损失明显的图像质量。60KB -> 1 MB 在该范围内。

还有一个:

将位图加载到内存中会对其进行解压缩,并且根据您加载的位图配置,它将占用比磁盘上压缩大小更多的内存。

在查看了有关压缩的信息之后(我不知道我脑子里发生了什么,因为我意识到压缩会使内存中的图像更小,以便保存和加载它,然后将其解压缩到内存中),我现在明白了事情是如何工作的; ) 当保存为位图时,图像被解压缩到几乎 2MB - 如果我查看 Irfanview 中的图像属性。

所以我现在正在做的是将样本大小设置为2并使用Bitmap.Config.Rgb565. 这将总图像大小减少到大约 30 MB,这要好得多。虽然质量不太好,但我可以在需要时加载更高分辨率的图像而用户不知道。

于 2012-06-18T13:56:57.540 回答