【问题标题】:Android: bitmap.getByteCount() in API lesser than 12Android:API 中的 bitmap.getByteCount() 小于 12
【发布时间】:2012-09-16 20:59:10
【问题描述】:

当我在将图像保存到 SD 卡之前搜索如何查找图像的大小时,我发现了这个:

bitmap.getByteCount();

但该方法是在 API 12 中添加的,我正在使用 API 10。所以我再次发现了这一点:

getByteCount() 只是一种方便的方法,它完全按照您在 else 块中的操作。换句话说,如果你简单地重写 getSizeInBytes 总是返回 "bitmap.getRowBytes() * bitmap.getHeight()"

这里:

Where the heck is Bitmap getByteCount()?

所以,通过计算 bitmap.getRowBytes() * bitmap.getHeight(),我得到了 120000 (117 KB) 的值。

SD 卡上的图像大小为1.6 KB

我错过了什么?还是做错了?

谢谢

【问题讨论】:

  • 正如下面的评论中所述,我想知道这是否与内存中的(未压缩的)位图大小与磁盘上的(压缩的 PNG/JPG)大小有关。因此,由于我认为这是 LruCache 示例,117 KB 可能是更安全的选择。
  • 我在下面添加了更全面的答案,您计算正确

标签: android getimagesize


【解决方案1】:

这是另一种方法:

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

来自 IDE 的 getAllocationByteCount() 声明:

如果位图为 重用于解码其他较小尺寸的位图,或手动 重新配置。见重新配置(int,int,Bitmap.Config), setWidth(int)、setHeight(int)、setConfig(Bitmap.Config) 和 BitmapFactory.Options.inBitmap。如果在此未修改位图 方式,该值将与 getByteCount() 返回的值相同。

【讨论】:

    【解决方案2】:

    您为什么不尝试在 1024 之间进行划分?获取 KB 而不是 Bytes。

    【讨论】:

      【解决方案3】:

      你做得对!

      确定这些值是否有效的快速方法是这样记录:

      int numBytesByRow = bitmap.getRowBytes() * bitmap.getHeight();
      int numBytesByCount = bitmap.getByteCount();
      Log.v( TAG, "numBytesByRow=" + numBytesByRow ); 
      Log.v( TAG, "numBytesByCount=" + numBytesByCount ); 
      

      这给出了结果:

      03-29 17:31:10.493: V/ImageCache(19704): numBytesByRow=270000
      03-29 17:31:10.493: V/ImageCache(19704): numBytesByCount=270000
      

      所以两者都在计算相同的数字,我怀疑这是位图的内存大小。这与 JPGPNG 在磁盘上,因为它是完全未压缩的。


      有关更多信息,我们可以查看 AOSP 和示例项目中的源代码。这是 Android 开发者文档 Caching Bitmaps

      中示例项目 BitmapFun 中使用的文件

      AOSP ImageCache.java

      /**
       * Get the size in bytes of a bitmap in a BitmapDrawable.
       * @param value
       * @return size in bytes
       */
      @TargetApi(12)
      public static int getBitmapSize(BitmapDrawable value) {
          Bitmap bitmap = value.getBitmap();
      
          if (APIUtil.hasHoneycombMR1()) {
              return bitmap.getByteCount();
          }
          // Pre HC-MR1
          return bitmap.getRowBytes() * bitmap.getHeight();
      }
      

      正如你所看到的,这与他们使用的技术相同

      bitmap.getRowBytes() * bitmap.getHeight();
      

      参考资料:

      【讨论】:

      • +1 非常感谢您抽出宝贵的时间提供这么好的答案 :)
      • 对于不同的设备,它会给出不同的位图大小...有什么原因吗?
      • @KalpeshLakhani 不同的设备使用不同的颜色模式,因此为完整的未压缩图像占用不同的内存量。 Android SDK中列出的4种模式是ALPHA_8ARGB_4444ARGB_8888RGB_565。见Bitmap.Config
      【解决方案4】:

      SD 卡上的图像大小不同,因为它是压缩的。在设备上,它将取决于宽度/高度

      【讨论】:

        【解决方案5】:

        现在我正在使用这个:

        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        my_bitmap.compress(Bitmap.CompressFormat.PNG, 100, bao);
        byte[] ba = bao.toByteArray();
        int size = ba.length;
        

        获取总字节数作为大小。因为我在这里得到的值与 SD 卡上图像的大小(以字节为单位)完全匹配。

        【讨论】:

        • 因为磁盘上的大小与内存中的大小不同。当您有一个 Bitmap 对象时,它表示图像的完整像素数据,以便您可以将其显示在屏幕上。当您将文件作为信息保存在磁盘上时,这些信息可以通过 JPG 或 PNG 等压缩算法进行压缩。
        • 不要这样做!这可行,但对于LruMemoryCache(这是问题的来源)来说是个坏主意。这会再次将所有数据加载到内存中。
        • @pjco 在这里列出的所有方法中,这是唯一可以准确描述文件大小的方法,我需要它作为网络流量指示器。其中data 是位图:data.getByteCount()data.getRowBytes() * data.getHeight()data.getAllocationByteCount() 都返回比字节数组长度高得多的值。
        • @netinept,我想也许看看 File() 或 FileDescriptor() 来获得磁盘上的大小(我忘了这会起作用)会更好,不是吗?这个问题是针对与内存大小有关的LruMemoryCache 提出的。你的用例听起来有点不同。我认为这取决于您从哪里获得位图以及您正在使用它做什么。如果它对你有用,尽管这很好,谢谢你的评论:)
        【解决方案6】:

        你可以试试这个代码

        int pixels = bitmap.getHeight() * bitmap.getWidth();
        int bytesPerPixel = 0;
        switch(bitmap.getConfig()) {
        case ARGB_8888:
        bytesPerPixel = 4;
        break;
        case RGB_565:
        bytesPerPixel = 2; 
         break;
        case ARGB_4444:
        bytesPerPixel = 2; 
         break;
        case ALPHA_8 :
         bytesPerPixel = 1; 
         break;
        }
         int byteCount = pixels / bytesPerPixel;
        

        【讨论】:

        • 首先我想我可能会遗漏一些其他因素。但问题是我使用公式 bitmap.getHeight() * bitmap.getWidth(); 得到的值为 117 K.B(如果您将其称为像素,则为 120000),而 SD 卡上的图像大小仅为 1.6 k.B。所以如果我必须乘以 bytesPerPixel 我最终会得到一个更大的值:(
        【解决方案7】:

        什么都没有!您的 coden-p 显示了来自 Android-Source 的确切实现:

        http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/graphics/Bitmap.java#Bitmap.getByteCount%28%29

        我认为大小的差异是图像压缩(jpg等)的结果。

        【讨论】:

        • 但我没有压缩它。如果我使用 JPEG 格式,我将质量设置为 100。此外,我还尝试使用 PNG(无损),无论我将值设置为什么,它总是提供原始质量。
        • 即使质量设置为 100,它仍在被压缩 (stackoverflow.com/questions/7982409/…)。 getByteCount 方法与图像格式无关,它显示图像在 RAM 内存中占用了多少内存。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-18
        • 2016-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多