How do I scale a streaming bitmap in-place without reading the whole image first?

前端 未结 2 2126
甜味超标
甜味超标 2020-12-01 05:00

I have an Android application that is very image intensive. I\'m currently using Bitmap.createScaledBitmap() to scale the image to a desired size. However, this method requi

2条回答
  •  一整个雨季
    2020-12-01 05:24

    Here is my version, based on @emmby solution (thanks man!) I've included a second phase where you take the reduced bitmap and scale it again to match exactly your desired dimensions. My version takes a file path rather than a stream.

    protected Bitmap createScaledBitmap(String filePath, int desiredBitmapWith, int desiredBitmapHeight) throws IOException, FileNotFoundException {
        BufferedInputStream imageFileStream = new BufferedInputStream(new FileInputStream(filePath));
        try {
            // Phase 1: Get a reduced size image. In this part we will do a rough scale down
            int sampleSize = 1;
            if (desiredBitmapWith > 0 && desiredBitmapHeight > 0) {
                final BitmapFactory.Options decodeBoundsOptions = new BitmapFactory.Options();
                decodeBoundsOptions.inJustDecodeBounds = true;
                imageFileStream.mark(64 * 1024);
                BitmapFactory.decodeStream(imageFileStream, null, decodeBoundsOptions);
                imageFileStream.reset();
                final int originalWidth = decodeBoundsOptions.outWidth;
                final int originalHeight = decodeBoundsOptions.outHeight;
                // inSampleSize prefers multiples of 2, but we prefer to prioritize memory savings
                sampleSize = Math.max(1, Math.max(originalWidth / desiredBitmapWith, originalHeight / desiredBitmapHeight));
            }
            BitmapFactory.Options decodeBitmapOptions = new BitmapFactory.Options();
            decodeBitmapOptions.inSampleSize = sampleSize;
            decodeBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565; // Uses 2-bytes instead of default 4 per pixel
    
            // Get the roughly scaled-down image
            Bitmap bmp = BitmapFactory.decodeStream(imageFileStream, null, decodeBitmapOptions);
    
            // Phase 2: Get an exact-size image - no dimension will exceed the desired value
            float ratio = Math.min((float)desiredBitmapWith/ (float)bmp.getWidth(), (float)desiredBitmapHeight/ (float)bmp.getHeight());
            int w =(int) ((float)bmp.getWidth() * ratio);
            int h =(int) ((float)bmp.getHeight() * ratio);
            return Bitmap.createScaledBitmap(bmp, w,h, true);
    
        } catch (IOException e) {
            throw e;
        } finally {
            try {
                imageFileStream.close();
            } catch (IOException ignored) {
            }
        }
    }
    

提交回复
热议问题