Example usage for android.graphics BitmapRegionDecoder recycle

List of usage examples for android.graphics BitmapRegionDecoder recycle

Introduction

In this page you can find the example usage for android.graphics BitmapRegionDecoder recycle.

Prototype

public void recycle() 

Source Link

Document

Frees up the memory associated with this region decoder, and mark the region decoder as "dead", meaning it will throw an exception if decodeRegion(), getWidth() or getHeight() is called.

Usage

From source file:com.facebook.imagepipeline.platform.DefaultDecoder.java

/**
 * Create a bitmap from an input stream.
 *
 * @param inputStream the InputStream/*from  w w  w  . j  ava 2  s  .  c o m*/
 * @param options the {@link android.graphics.BitmapFactory.Options} used to decode the stream
 * @param regionToDecode optional image region to decode or null to decode the whole image
 * @param transformToSRGB whether to allow color space transformation to sRGB at load time
 * @return the bitmap
 */
private CloseableReference<Bitmap> decodeFromStream(InputStream inputStream, BitmapFactory.Options options,
        @Nullable Rect regionToDecode, final boolean transformToSRGB) {
    Preconditions.checkNotNull(inputStream);
    int targetWidth = options.outWidth;
    int targetHeight = options.outHeight;
    if (regionToDecode != null) {
        targetWidth = regionToDecode.width() / options.inSampleSize;
        targetHeight = regionToDecode.height() / options.inSampleSize;
    }
    int sizeInBytes = getBitmapSize(targetWidth, targetHeight, options);
    final Bitmap bitmapToReuse = mBitmapPool.get(sizeInBytes);
    if (bitmapToReuse == null) {
        throw new NullPointerException("BitmapPool.get returned null");
    }
    options.inBitmap = bitmapToReuse;

    // Performs transformation at load time to sRGB.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && transformToSRGB) {
        options.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
    }

    Bitmap decodedBitmap = null;
    ByteBuffer byteBuffer = mDecodeBuffers.acquire();
    if (byteBuffer == null) {
        byteBuffer = ByteBuffer.allocate(DECODE_BUFFER_SIZE);
    }
    try {
        options.inTempStorage = byteBuffer.array();
        if (regionToDecode != null) {
            BitmapRegionDecoder bitmapRegionDecoder = null;
            try {
                bitmapToReuse.reconfigure(targetWidth, targetHeight, options.inPreferredConfig);
                bitmapRegionDecoder = BitmapRegionDecoder.newInstance(inputStream, true);
                decodedBitmap = bitmapRegionDecoder.decodeRegion(regionToDecode, options);
            } catch (IOException e) {
                FLog.e(TAG, "Could not decode region %s, decoding full bitmap instead.", regionToDecode);
            } finally {
                if (bitmapRegionDecoder != null) {
                    bitmapRegionDecoder.recycle();
                }
            }
        }
        if (decodedBitmap == null) {
            decodedBitmap = BitmapFactory.decodeStream(inputStream, null, options);
        }
    } catch (IllegalArgumentException e) {
        mBitmapPool.release(bitmapToReuse);
        // This is thrown if the Bitmap options are invalid, so let's just try to decode the bitmap
        // as-is, which might be inefficient - but it works.
        try {
            // We need to reset the stream first
            inputStream.reset();

            Bitmap naiveDecodedBitmap = BitmapFactory.decodeStream(inputStream);
            if (naiveDecodedBitmap == null) {
                throw e;
            }
            return CloseableReference.of(naiveDecodedBitmap, SimpleBitmapReleaser.getInstance());
        } catch (IOException re) {
            // We throw the original exception instead since it's the one causing this workaround in the
            // first place.
            throw e;
        }
    } catch (RuntimeException re) {
        mBitmapPool.release(bitmapToReuse);
        throw re;
    } finally {
        mDecodeBuffers.release(byteBuffer);
    }

    if (bitmapToReuse != decodedBitmap) {
        mBitmapPool.release(bitmapToReuse);
        decodedBitmap.recycle();
        throw new IllegalStateException();
    }

    return CloseableReference.of(decodedBitmap, mBitmapPool);
}

From source file:com.android.contacts.DynamicShortcuts.java

private Bitmap decodeStreamForShortcut(InputStream stream) throws IOException {
    final BitmapRegionDecoder bitmapDecoder = BitmapRegionDecoder.newInstance(stream, false);

    final int sourceWidth = bitmapDecoder.getWidth();
    final int sourceHeight = bitmapDecoder.getHeight();

    final int iconMaxWidth = mShortcutManager.getIconMaxWidth();
    final int iconMaxHeight = mShortcutManager.getIconMaxHeight();

    final int sampleSize = Math.min(BitmapUtil.findOptimalSampleSize(sourceWidth, mIconSize),
            BitmapUtil.findOptimalSampleSize(sourceHeight, mIconSize));
    final BitmapFactory.Options opts = new BitmapFactory.Options();
    opts.inSampleSize = sampleSize;//from  ww w  .ja  v a  2  s. c  om

    final int scaledWidth = sourceWidth / opts.inSampleSize;
    final int scaledHeight = sourceHeight / opts.inSampleSize;

    final int targetWidth = Math.min(scaledWidth, iconMaxWidth);
    final int targetHeight = Math.min(scaledHeight, iconMaxHeight);

    // Make it square.
    final int targetSize = Math.min(targetWidth, targetHeight);

    // The region is defined in the coordinates of the source image then the sampling is
    // done on the extracted region.
    final int prescaledXOffset = ((scaledWidth - targetSize) * opts.inSampleSize) / 2;
    final int prescaledYOffset = ((scaledHeight - targetSize) * opts.inSampleSize) / 2;

    final Bitmap bitmap = bitmapDecoder.decodeRegion(new Rect(prescaledXOffset, prescaledYOffset,
            sourceWidth - prescaledXOffset, sourceHeight - prescaledYOffset), opts);
    bitmapDecoder.recycle();

    if (!BuildCompat.isAtLeastO()) {
        return BitmapUtil.getRoundedBitmap(bitmap, targetSize, targetSize);
    }

    return bitmap;
}