Main.java Source code

Java tutorial

Introduction

Here is the source code for Main.java

Source

//package com.java2s;
/*
 * Copyright 2014 Yaroslav Mytkalyk
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.File;
import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import android.annotation.SuppressLint;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

public class Main {
    private static final Set<SoftReference<Bitmap>> sReusableBitmaps = Collections
            .synchronizedSet(new HashSet<SoftReference<Bitmap>>());

    @NonNull
    private static Bitmap decodeSampledBitmap(@NonNull final File file, final int reqWidth) {

        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        BitmapFactory.decodeFile(file.getAbsolutePath(), options);

        options.inJustDecodeBounds = false;
        options.inMutable = true;

        if (options.outWidth != -1 && options.outHeight != -1) {
            final int originalSize = (options.outHeight > options.outWidth) ? options.outWidth : options.outHeight;
            options.inSampleSize = originalSize / reqWidth;
        }

        final Bitmap inBitmap = getBitmapFromReusableSet(options);
        if (inBitmap != null) {
            options.inBitmap = inBitmap;
        }

        return BitmapFactory.decodeFile(file.getAbsolutePath(), options);
    }

    /**
     * Returns reusable bitmap, if exists
     *
     * @param options Options to look against
     * @return reusable bitmap, if exists
     */
    @Nullable
    private static Bitmap getBitmapFromReusableSet(@NonNull final BitmapFactory.Options options) {
        Bitmap bitmap = null;

        if (sReusableBitmaps != null && sReusableBitmaps.isEmpty()) {
            synchronized (sReusableBitmaps) {
                final Iterator<SoftReference<Bitmap>> iterator = sReusableBitmaps.iterator();
                Bitmap item;

                while (iterator.hasNext()) {
                    item = iterator.next().get();

                    if (item != null && item.isMutable()) {
                        // Check to see it the item can be used for inBitmap.
                        if (canUseForInBitmap(item, options)) {
                            bitmap = item;

                            // Remove from reusable set so it can't be used again.
                            iterator.remove();
                            break;
                        }
                    } else {
                        // Remove from the set if the reference has been cleared.
                        iterator.remove();
                    }
                }
            }
        }
        return bitmap;
    }

    @SuppressLint("NewApi")
    private static boolean canUseForInBitmap(@NonNull final Bitmap candidate,
            @NonNull final BitmapFactory.Options targetOptions) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // From Android 4.4 (KitKat) onward we can re-use if the byte size of
            // the new bitmap is smaller than the reusable bitmap candidate
            // allocation byte count.
            final int width = targetOptions.outWidth / targetOptions.inSampleSize;
            final int height = targetOptions.outHeight / targetOptions.inSampleSize;
            final int byteCount = width * height * getBytesPerPixel(candidate.getConfig());
            return byteCount <= candidate.getAllocationByteCount();
        }

        // On earlier versions, the dimensions must match exactly and the inSampleSize must be 1
        return candidate.getWidth() == targetOptions.outWidth && candidate.getHeight() == targetOptions.outHeight
                && targetOptions.inSampleSize == 1;
    }

    /**
     * Returns the byte usage per pixel of a bitmap based on its configuration.
     *
     * @return byte usage per pixel
     */
    private static int getBytesPerPixel(@NonNull final Bitmap.Config config) {
        switch (config) {
        case ARGB_8888:
            return 4;

        case RGB_565:
        case ARGB_4444:
            return 2;

        default:
            return 1;
        }
    }
}