Loading only part of a bitmap file in Android

后端 未结 5 789
醉话见心
醉话见心 2020-12-14 19:14

I would like to load a cropped version of a bitmap image into a Bitmap object, without loading the original bitmap as well.

Is this at all possible without writing c

相关标签:
5条回答
  • 2020-12-14 19:56

    You can load the scaled version of bitmap with out fully loading the bitmap using following algorithm

    • Calculate the maximum possible inSampleSize that still yields an image larger than your target.
    • Load the image using BitmapFactory.decodeFile(file, options), passing inSampleSize as an option.
    • Resize to the desired dimensions using Bitmap.createScaledBitmap().

    Check the following post Android: Resize a large bitmap file to scaled output file for further details.

    0 讨论(0)
  • 2020-12-14 19:59

    @RKN

    Your method can also throw OutOfMemoryError exception - if cropped bitmap exceeds VM.

    My method combines Yours and protection against this exeption: (l, t, r, b - % of image)

        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;
    }
    

    and returns max available bitmap or null

    0 讨论(0)
  • 2020-12-14 20:14

    It's actually very straightforward to do. Use

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

    Update: use BitmapRegionDecoder

    0 讨论(0)
  • 2020-12-14 20:14

    try this

    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);
    
    0 讨论(0)
  • 2020-12-14 20:16

    Use RapidDecoder.

    And simply do this

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

    It requires Android 2.2 or above.

    0 讨论(0)
提交回复
热议问题