【问题标题】:Optimal use of BitmapFactory.Options.inSampleSize for speed优化使用 BitmapFactory.Options.inSampleSize 以提高速度
【发布时间】:2011-06-17 01:09:59
【问题描述】:

感谢 Schermvliegeranddev.org 上向 this 提问,

我只是将他的问题复制给 SO,因为没有人在其他网站上回复,我也面临同样的问题。

我想知道在显示图像的速度方面,BitmapFactory.Options.inSampleSize 的最佳用途是什么。
文档提到使用 2 的幂的值,所以我正在使用 2、4、8、16 等。

我想知道的事情是:

  1. 我应该重新采样到仍然大于屏幕分辨率的最小尺寸,还是应该缩小到刚好足以避免OutOfMemoryError的尺寸?
  2. 如何计算在不耗尽内存的情况下仍可显示的图像的最大尺寸?图像的颜色深度以及显示的深度是否也起作用?
  3. 通过两种机制显示图像是否有效(BitmapFactory 用于大文件,setImageURI() 用于较小文件)顺便说一下,我使用的是ImageSwitcher
  4. 是否有助于在应用程序的开头创建 BitmapBitmapFactory.OptionsinTempStorage 或仅在需要时动态创建它们?

【问题讨论】:

    标签: android bitmap bitmapfactory


    【解决方案1】:

    您应该始终尝试加载和预缩放图像,以使它们尽可能接近最终显示的尺寸。在绘制时缩放图像非常昂贵,应该不惜一切代价避免。

    考虑到图像的内存成本,是的,颜色深度起着非常重要的作用。 ALPHA_8 格式的图像每个像素使用 1 个字节,RGB_565 或 ARGB_4444 格式的图像每个像素使用 2 个字节,ARGB_8888 格式的图像每个像素使用 4 个字节。显示的深度根本不重要。您应始终尝试使用 ARGB_8888 以获得最佳质量,但如果您的图像不透明,565 就足够了。

    【讨论】:

    • 当您说“在绘图时缩放图像非常昂贵”时,这是否也包括 options.inSampleSize?
    • inSampleSize 用于在加载时缩放图像,而不是在绘制时。这是预缩放图像的一种非常好的方法。
    • 我们正在使用 ARGB_8888 ,它在三星 Galaxy Note 2 上产生了一个非常模糊的图像,但它在其他设备上运行良好,带上它 ARGB_4444 导致三星 Galaxy Note 2 和 Pad 3110 上的应用程序崩溃,由于 outOfMemoryError。你能帮我们解决这个问题吗?
    【解决方案2】:

    您提出了很好的问题,但这完全取决于您的需求以及您使用的内存量。 我建议查看此链接以获取有关位图的许多提示:http://developer.android.com/training/displaying-bitmaps/index.html

    简而言之,您应该考虑缓存、下采样,并尽可能使用足够好的位图格式。

    以下是我对您问题的回答:

    1. 为什么不两者兼而有之?如果您认为可能存在 OOM,请尝试回收旧的、未使用的位图,然后再次检查。

    2. 您可以计算位图的(估计)大小:

      宽*高*bytesPerPixel

      其中 bytesPerPixel 通常为 4 或 2(取决于位图格式)。

    3. 从未使用过 setImageURI ,所以我帮不了你。我建议在后台线程中下载图像(使用 asyncTask 是一种方法)并在准备好时显示它们。

    4. 如果你知道的只有几个不会占用太多内存,我想没关系。我仍然认为缓存会更好。

    【讨论】:

      【解决方案3】:

      在这里你可以调用用户定义的方法shrinkmehtod,它实际上将字符串文件路径和高度和宽度发送到方法中。

       Bitmap bit=shrinkmethod(arrpath1[position], 100, 100);
      
      
                  //iv.setImageURI(Uri.parse(arrpath1[position]));
                  iv.setImageBitmap(bit);
      

      这是用户定义的以编程方式减小图像大小的方法。

      Bitmap shrinkmethod(String file,int width,int height){
              BitmapFactory.Options bitopt=new BitmapFactory.Options();
              bitopt.inJustDecodeBounds=true;
              Bitmap bit=BitmapFactory.decodeFile(file, bitopt);
      
              int h=(int) Math.ceil(bitopt.outHeight/(float)height);
              int w=(int) Math.ceil(bitopt.outWidth/(float)width);
      
              if(h>1 || w>1){
                  if(h>w){
                      bitopt.inSampleSize=h;
      
                  }else{
                      bitopt.inSampleSize=w;
                  }
              }
              bitopt.inJustDecodeBounds=false;
              bit=BitmapFactory.decodeFile(file, bitopt);
      
      
      
              return bit;
      
          }
      

      我希望这会帮助您减小尺寸。

      【解决方案4】:

      您好尝试使用此逻辑计算 inSampleSize

      private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
          val (height: Int, width: Int) = options.run { outHeight to outWidth }
          var inSampleSize = 1
      
          if (height > reqHeight || width > reqWidth) {
              val halfHeight: Int = height / 2
              val halfWidth: Int = width / 2
      
              // Calculate the largest inSampleSize value that is a power of 2 and keeps both
              // height and width larger than the requested height and width.
              while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
                  inSampleSize *= 2
              }
          }
      
          return inSampleSize
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-24
        • 2021-07-23
        相关资源
        最近更新 更多