【问题标题】:Loading only part of a bitmap file in Android在 Android 中仅加载位图文件的一部分
【发布时间】:2011-02-02 12:33:12
【问题描述】:

我想将位图图像的裁剪版本加载到位图对象中,而不加载原始位图。

如果不编写自定义加载例程来处理原始数据,这是否可能?

谢谢, 桑德尔

【问题讨论】:

    标签: android performance graphics


    【解决方案1】:

    您可以使用以下算法在不完全加载位图的情况下加载位图的缩放版本

    • 计算仍然产生的最大可能 inSampleSize 图像大于您的目标。
    • 使用加载图像 BitmapFactory.decodeFile(file, options),将 inSampleSize 作为 选项。
    • 使用 Bitmap.createScaledBitmap()。

    查看以下帖子 Android: Resize a large bitmap file to scaled output file 了解更多详情。

    【讨论】:

      【解决方案2】:

      这实际上非常简单。使用

      Bitmap yourBitmap = Bitmap.createBitmap(sourceBitmap, x to start from, y to start from, width, height)

      更新:使用BitmapRegionDecoder

      【讨论】:

      • 谢谢史蒂夫,但这需要我先加载 sourceBitmap,我试图避免这样做,因为它太大而无法放入内存,我想使用位图没有被下采样。
      • 哎呀,你是对的,我没有正确阅读你问题的那一部分。我不确定如何在没有下采样的情况下做到这一点。事实上,一个非常相似的问题也在我自己的解决方法清单上!
      【解决方案3】:

      使用RapidDecoder

      只需这样做

      import rapid.decoder.BitmapDecoder;
      
      Rect bounds = new Rect(left, top, right, bottom);
      Bitmap bitmap = BitmapDecoder.from(getResources(), R.drawable.image)
              .region(bounds).decode();
      

      需要 Android 2.2 或更高版本。

      【讨论】:

        【解决方案4】:

        @RKN

        如果裁剪的位图超出 VM,您的方法也可能抛出 OutOfMemoryError 异常。

        我的方法结合了您的方法和针对此异常的保护: (l, t, r, b - 图像的百分比)

            Bitmap cropBitmap(ContentResolver cr, String file, float l, float t, float r, float b)
        {
            try 
            {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
        
                // First decode with inJustDecodeBounds=true to check dimensions
                BitmapFactory.decodeFile(file, options);
                int oWidth = options.outWidth;
                int oHeight = options.outHeight;
        
                InputStream istream = cr.openInputStream(Uri.fromFile(new File(file)));
        
                BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(istream, false);
                if (decoder != null)
                {
                    options = new BitmapFactory.Options();
        
                    int startingSize = 1;
                    if ((r - l) * oWidth * (b - t) * oHeight > 2073600)
                        startingSize = (int) ((r - l) * oWidth * (b - t) * oHeight / 2073600) + 1;
        
                    for (options.inSampleSize = startingSize; options.inSampleSize <= 32; options.inSampleSize++)
                    {
                        try
                        {
                            return decoder.decodeRegion(new Rect((int) (l * oWidth), (int) (t * oHeight), (int) (r * oWidth), (int) (b * oHeight)), options);    
                        }
                        catch (OutOfMemoryError e)
                        {
                            Continue with for loop if OutOfMemoryError occurs
                        }
                    }
                }
                else
                    return null;
            }
            catch (FileNotFoundException e)
            {
                e.printStackTrace();
            }
            catch (IOException e) 
            {
                e.printStackTrace();
            }
        
            return null;
        }
        

        并返回最大可用位图或 null

        【讨论】:

        • 如果startingSize > 32 最初是因为输入图像太大怎么办?
        【解决方案5】:

        试试这个

        InputStream istream =   null;
        try {
             istream = this.getContentResolver().openInputStream(yourBitmapUri);
        } catch (FileNotFoundException e1) {
             e1.printStackTrace();
        }
        
        BitmapRegionDecoder decoder     =   null;
        try {
            decoder = BitmapRegionDecoder.newInstance(istream, false);
        } catch (IOException e) {
            e.printStackTrace();
        }
        Bitmap bMap = decoder.decodeRegion(new Rect(istream, x to start from, y to start from, x to end with, y to end with), null);    
        imageView.setImageBitmap(bMap);
        

        【讨论】:

        • oops..sorry.. 还有一件事此方法适用于 sdk 版本 2.3 或更高版本...
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多