【问题标题】:Decode a part of Bitmap from file in Android在 Android 中从文件中解码位图的一部分
【发布时间】:2012-05-18 11:33:38
【问题描述】:

我有一个图像非常大的文件:例如 9000x9000。

由于堆大小,我无法将位图加载到内存中。但我只需要显示这个位图的一小部分,例如矩形宽度=100-200 和高度=200-400(子位图的结果大小=100x200)

如何从文件中检索此位图?

注意:我不想损失 100x200 图像的质量

谢谢

【问题讨论】:

    标签: java android bitmap


    【解决方案1】:

    有没有办法解决这个问题?

    例如,BitmapRegionDecoder

    它应该适用于 API10 及更高版本...

    用法:

    BitmapRegionDecoder.newInstance(...).decodeRegion(...)
    

    【讨论】:

    • 显然这是正确的答案。
    【解决方案2】:

    使用RapidDecoder 可以轻松完成。

    我实际上生成了一个 9000x9000 的 png,它的文件大小约为 80MB,并且成功加载了 200x400 大小的区域。

    import rapid.decoder.BitmapDecoder;
    
    Bitmap bitmap = BitmapDecoder.from("big-image.png")
                                 .region(145, 192, 145 + 200, 192 + 400)
                                 .decode();
    imageView.setImageBitmap(bitmap);
    

    它适用于 Android 2.2 及更高版本。

    【讨论】:

    • 哇,这听起来很有希望。整个解码是在 JNI 上完成的吗?支持哪些文件格式?它甚至支持 WebP 吗?是否包括人脸检测?
    • +1 非常好的库,图像质量也保持了 80%..并且适用于几乎所有设备
    【解决方案3】:

    我认为您可以使用 BitmapFactory 方法,该方法允许您指定要解码的 Rect。

    public static Bitmap decodeStream (InputStream is, Rect outPadding, BitmapFactory.Options opts)
    

    【讨论】:

    • outPadding 是一个输出参数
    • @Addev 我真的很有趣.. 所以你不认为在导入之前可以只取一些位图的矩形吗? :)
    • 在哪些情况下会填充 outPadding?什么时候9补丁?还有其他情况吗?还有,就算是9-patch,是什么意思,又会填什么?
    【解决方案4】:

    试试这个代码:

    public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) {
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(path, options);
    
            final int height = options.outHeight;
            final int width = options.outWidth;
            options.inPreferredConfig = Bitmap.Config.RGB_565;
            int inSampleSize = 1;
            if (height > reqHeight) {
                inSampleSize = Math.round((float) height / (float) reqHeight);
            }
            int expectedWidth = width / inSampleSize;
            if (expectedWidth > reqWidth) {
                inSampleSize = Math.round((float) width / (float) reqWidth);
            }
            options.inSampleSize = inSampleSize;
            options.inJustDecodeBounds = false;
            return BitmapFactory.decodeFile(path, options);
        }
    

    【讨论】:

      【解决方案5】:

      我不认为你可以。即使在 PC 上,我也看不出如何在不加载整个图像的情况下做到这一点:大多数图像格式(例如 PNG)都压缩了像素数据,因此您至少需要解压缩 IDAT 块才能开始执行此操作其他任何东西,基本上都会解码整个图像。

      在您的情况下,我会尝试让服务器为我做这件事。无论如何,您从哪里获得图像?不是来自服务器?然后尝试发出 WS 请求,该请求将为您提供图像的正确部分。如果图像不是来自服务器,您仍然可以将其发送到服务器以仅取回您想要的图像部分。

      【讨论】:

      • 感谢您的回答。我要做的是实现一个 MultiTouchImageView 并且仅加载由于缩放和滚动位置而可见的图像部分,从而允许加载大图像而不会降低质量并且不会导致内存崩溃。我该怎么做?
      • 在那种情况下,我认为由于移动设备的限制,您尝试做的事情在技术上根本不可能:如果不将整个图像加载到内存中,您将无法为用户提供良好的体验,并且只显示您需要的部分。即使您可以只加载图像的一部分,每次用户平移或缩放时都必须这样做......因为操作会很慢,所以用户体验无论如何都会很糟糕。做到这一点的唯一方法是对图像的大小设置一些上限。否则,恕我直言,您将无法做到。
      • 嗯,你说的很合乎逻辑,但是 Android 的图库如何加载那些允许以相同质量放大的大图像?
      • Android 的美妙之处在于您可以查看应用程序的源代码...包括Android 的Gallery 之一。这是链接github.com/CyanogenMod/android_packages_apps_Gallery/tree/… 我正在查看 BaseImage.java (在 galery 子目录中)和 Util.java 类(特别是 makeBitmap() 方法),在我看来他们正在做缩放... options.inSampleSize = computeSampleSize(选项,minSideLength,maxNumOfPixels); [...]
      • 这个答案已经过时或不正确。在Android API level 10中加载这种大小的图片子图是没有问题的。
      【解决方案6】:

      试试这个代码:

      private Bitmap decodeFile(File f) {
          Bitmap b = null;
          try {
              BitmapFactory.Options o = new BitmapFactory.Options();
              o.inJustDecodeBounds = true;
              FileInputStream fis = new FileInputStream(f);
              b=Bitmap.createBitmap(BitmapFactory.decodeStream(fis, null, o), 100, 200, 200, 400, null, null);
              fis.close();
          } catch (IOException e) {
          }
          return b;
      }
      

      不确定,但这可能会给你一些想法

      【讨论】:

      • 它给出了内存不足的错误,因为 BitmapFactory.decodeStream(fis, null, o) 在检索到整个 Bitmap 之前不会返回
      猜你喜欢
      • 1970-01-01
      • 2011-02-02
      • 2013-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-20
      • 1970-01-01
      相关资源
      最近更新 更多