yasharpm / InstaCropper

A View for cropping images that is similar to Instagram's crop which allows a range of aspect ratios instead of a solid ratio. Also an Activity for cropping is included.
377 stars 44 forks source link

About Bitmap memory allocation #11

Closed ZhouKanZ closed 4 years ago

ZhouKanZ commented 4 years ago

In your project ,MakeDrawableTask/doInBackground method , I am confused on the memory allocating, why 1 of eighth and why allowedMemoryToUse divide by 4 . i find some explanation, But still can't understand,Hope to get your mention!

' BitmapFactory.decodeStream(mContext.getContentResolver().openInputStream(mUri), null, options);

        mRawWidth = options.outWidth;
        mRawHeight = options.outHeight;

        int resultWidth = mRawWidth;
        int resultHeight = mRawHeight;

        Runtime.getRuntime().gc();

        long totalMemory = Runtime.getRuntime().maxMemory();
        long allowedMemoryToUse = totalMemory / 8;
        int maximumAreaPossibleAccordingToAvailableMemory = (int) (allowedMemoryToUse / 4);

        int targetArea = Math.min(mTargetWidth * mTargetHeight * 4, maximumAreaPossibleAccordingToAvailableMemory);

        int resultArea = resultWidth * resultHeight;

        while (resultArea > targetArea) {
            options.inSampleSize *= 2;

            resultWidth = mRawWidth / options.inSampleSize;
            resultHeight = mRawHeight / options.inSampleSize;

            resultArea = resultWidth * resultHeight;
        }

        options.inJustDecodeBounds = false;

        Bitmap bitmap = getBitmap(mContext, mUri, options);

'

yasharpm commented 4 years ago

Hi, I will try to explain it line by line. Hope you understand.

long totalMemory = Runtime.getRuntime().maxMemory(); This is the device's total memory.

long allowedMemoryToUse = totalMemory / 8; This is the memory available to the running app according to the documents.

int maximumAreaPossibleAccordingToAvailableMemory = (int) (allowedMemoryToUse / 4); This is the usual amount of memory that libraries acquire to do image processing.

The general idea is that I want to avoid "out of memory" exceptions. Meanwhile in order to be able to show the image with the highest resolution possible, I want to take as much memory as possible that doesn't create an "out of memory" risk.

int targetArea = Math.min(mTargetWidth * mTargetHeight * 4, maximumAreaPossibleAccordingToAvailableMemory); This is the maximum RAM that can (is allowed to) be consumed for the created bitmap. Note that ARGB bitmaps require one byte for each of A, R, G and B values. Hence 4 width height is the formula for the RAM consumption of a bitmap.

int resultArea = resultWidth * resultHeight; This is the RAM amount that the read image will require as a Bitmap.

while (resultArea > targetArea) We want the create Bitmap to consume less or equal amount of RAM than our maximum calculated.

options.inSampleSize *= 2; Image sample size can only be powers of 2. Means 1, 2, 4, 8, 16, etc. It means how many pixels BitmapFactory will ignore between each pixel that it puts into the bitmap.

I hope this explanation help you out. ;-)

ZhouKanZ commented 4 years ago

i had read some code about threadPool , realized some knowledge about cpu and Memory allocation. thk u very much