解码后的位图字节大小是多少?

76

我如何确定/计算使用 BitmapFactory 解码后位图的字节大小?

我需要知道它占用多少内存空间,因为我正在我的应用程序中进行内存缓存/管理。(文件大小不足以判断,因为这些是 jpg/png 文件)

感谢任何解决方案!

更新:getRowBytes * getHeight 可能会奏效... 我将采用这种方式实现,直到有人提出反对意见。

4个回答

125
getRowBytes() * getHeight() 看起来对我来说已经很好了。
更新我的两年前的答案: 自API 12起,Bitmap有一种直接查询字节数的方法: http://developer.android.com/reference/android/graphics/Bitmap.html#getByteCount%28%29 ----示例代码
    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
    protected int sizeOf(Bitmap data) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
            return data.getRowBytes() * data.getHeight();
        } else {
            return data.getByteCount();
        }
    }

1
尝试这样做:original = BitmapFactory.decodeStream(getAssets().open("hd.jpg")); sizeOf(original);ByteArrayOutputStream out = new ByteArrayOutputStream(); original.compress(Bitmap.CompressFormat.WEBP, 50, out); Bitmap decoded = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray())); sizeOf(decoded);当我在您的方法内部进行调试时,即使第二张图像被压缩,我得到的字节数也是相同的!有任何意见吗? - TharakaNirmana
1
@TharakaNirmana 位图始终包含未压缩的图像。压缩仅用于缩小图像以保存到文件中。 - Ridcully
1
更新并添加getAllocationByteCount()的KitKat方法。请参阅http://developer.android.com/reference/android/graphics/Bitmap.html#getAllocationByteCount()。 - Itai Hanski
1
我有一张图片,但如果我在两个不同的设备上运行它,那么在两个设备上我得到的图片大小是不同的,有什么原因吗?例如,在Galaxy S Duos上它的大小是656 KB,在MOTO G设备上返回的是1136 KB。 - Kalpesh Lakhani
3
@Kalpesh,你的三星手机屏幕具有hdpi密度,而摩托罗拉手机则具有xhdpi密度,因此在这些型号上加载资源时会使用不同大小的资源。请查看Google显示密度桶文档。 - Patrick
我使用BitmapCompat.getAllocationByteCount(scaledBitmap)获取的分配字节数为3145728,但实际大小只有207kB。我做错了什么? - Aman Verma

62

最好只使用支持库:

int bitmapByteCount=BitmapCompat.getAllocationByteCount(bitmap)

但是如果您的Android项目至少使用minSdk为19(即Kitkat,表示4.4),则可以直接使用bitmap.getAllocationByteCount()


2
我使用BitmapCompat.getAllocationByteCount(scaledBitmap)获取的分配字节数为3145728,但实际大小只有207kB。我做错了什么? - Aman Verma
2
@Sniper 真正的大小指什么? 如果你是指文件大小,那么这是有道理的,因为文件是压缩的。现在没人会直接将图像放入未编码为JPG/PNG/WEBP格式的文件中。文件的大小不应该与解码后的图像一样大。每个图像的预估字节数为width*height*bytesPerPixel ,其中bytesPerPixel通常为4或2. 这意味着,如果您有一个1000x1000的图像,则可能需要约410001000= 4,000,000字节,即约4MB。 - android developer
我在onActivityResult中有一个位图,我想检查图像的大小并检查其是否大于5 mb,如果小于5 mb,则将其发送到我的服务器,否则提示用户拍摄新照片。 - Aman Verma
2
@Sniper 你将一个图像文件发送到服务器。通常这些文件是JPEG、PNG、WEBP等格式...所有这些格式的文件通常占用的存储空间都不到5MB,因为它们被压缩了。它们几乎总是比位图在内存中占用的存储空间少。只需使用file.length检查创建后的文件大小即可:https://developer.android.com/reference/java/io/File.html#length()。这与位图无关。位图的分辨率可能很高或很低。你所说的是文件本身。 - android developer
@Sniper如果您还有关于此方面的任何问题,可以随时问我 :) - android developer
显示剩余3条评论

22

这是使用KitKat的getAllocationByteCount()的2014版本,编写时考虑到编译器可以理解版本逻辑(因此不需要@TargetApi)。

/**
 * returns the bytesize of the give bitmap
 */
public static int byteSizeOf(Bitmap bitmap) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        return bitmap.getAllocationByteCount();
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
        return bitmap.getByteCount();
    } else {
        return bitmap.getRowBytes() * bitmap.getHeight();
    }
}
请注意,getAllocationByteCount() 的结果可能比getByteCount()的结果更大,如果一个位图被重用来解码较小尺寸的其他位图,或者通过手动重新配置。

是的,Picasso也使用这个函数来计算位图大小。 - wangzhengyi
我正在使用BitmapCompat.getAllocationByteCount(scaledBitmap)获取分配的字节数3145728,但实际大小为207kB。我做错了什么? - Aman Verma

8
public static int sizeOf(Bitmap data) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
        return data.getRowBytes() * data.getHeight();
    } else if (Build.VERSION.SDK_INT<Build.VERSION_CODES.KITKAT){
        return data.getByteCount();
    } else{
        return data.getAllocationByteCount();
    }
}

唯一与@user289463答案不同的是在KitKat及以上版本中使用getAllocationByteCount()

1
我使用BitmapCompat.getAllocationByteCount(scaledBitmap)获取到的内存分配字节数是3145728,但实际大小只有207kB。我做错了什么? - Aman Verma
3
那个207kB的值是文件在磁盘上存储时的压缩大小。当它被加载到内存中时,会被解压缩并使用你从函数中获取的字节计数。 - Bryan W

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