Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 97f96ef9 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change I7f9db307 into eclair-mr2

* changes:
  Modify the behavior of createThumbnailForEXIF() to: returning SizedThumbnailBitmap, which contains the downsampled bitmap either from the thumbnail in EXIF or the full image.
parents fcae6c71 6706caf9
Loading
Loading
Loading
Loading
+67 −37
Original line number Diff line number Diff line
@@ -35,9 +35,7 @@ import android.graphics.Rect;
import android.media.MediaMetadataRetriever;
import android.media.MediaFile.MediaFileType;

import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;

@@ -296,7 +294,7 @@ public class ThumbnailUtil {
     * @param uri URI of original image
     * @param origId image id
     * @param kind either MINI_KIND or MICRO_KIND
     * @param saveImage Whether to save MINI_KIND thumbnail obtained in this method.
     * @param saveMini Whether to save MINI_KIND thumbnail obtained in this method.
     * @return Bitmap
     */
    public static Bitmap createImageThumbnail(ContentResolver cr, String filePath, Uri uri,
@@ -306,20 +304,12 @@ public class ThumbnailUtil {
                ThumbnailUtil.THUMBNAIL_TARGET_SIZE : ThumbnailUtil.MINI_THUMB_TARGET_SIZE;
        int maxPixels = wantMini ?
                ThumbnailUtil.THUMBNAIL_MAX_NUM_PIXELS : ThumbnailUtil.MINI_THUMB_MAX_NUM_PIXELS;
        byte[] thumbData = null;
        SizedThumbnailBitmap sizedThumbnailBitmap = new SizedThumbnailBitmap();
        Bitmap bitmap = null;
        MediaFileType fileType = MediaFile.getFileType(filePath);
        if (fileType != null && fileType.fileType == MediaFile.FILE_TYPE_JPEG) {
            thumbData = createThumbnailFromEXIF(filePath, targetSize);
        }

        if (thumbData != null) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = computeSampleSize(options, targetSize, maxPixels);
            options.inDither = false;
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
            options.inJustDecodeBounds = false;
            bitmap = BitmapFactory.decodeByteArray(thumbData, 0, thumbData.length, options);
            createThumbnailFromEXIF(filePath, targetSize, maxPixels, sizedThumbnailBitmap);
            bitmap = sizedThumbnailBitmap.mBitmap;
        }

        if (bitmap == null) {
@@ -331,9 +321,11 @@ public class ThumbnailUtil {
        }

        if (saveMini) {
            if (thumbData != null) {
                ThumbnailUtil.storeThumbnail(cr, origId, thumbData, bitmap.getWidth(),
                        bitmap.getHeight());
            if (sizedThumbnailBitmap.mThumbnailData != null) {
                ThumbnailUtil.storeThumbnail(cr, origId,
                        sizedThumbnailBitmap.mThumbnailData,
                        sizedThumbnailBitmap.mThumbnailWidth,
                        sizedThumbnailBitmap.mThumbnailHeight);
            } else {
                ThumbnailUtil.storeThumbnail(cr, origId, bitmap);
            }
@@ -521,31 +513,69 @@ public class ThumbnailUtil {
        }
    }

    // Extract thumbnail in image that meets the targetSize criteria.
    static byte[] createThumbnailFromEXIF(String filePath, int targetSize) {
        if (filePath == null) return null;

        try {
            ExifInterface exif = new ExifInterface(filePath);
            if (exif == null) return null;
            byte [] thumbData = exif.getThumbnail();
            if (thumbData == null) return null;
            // Sniff the size of the EXIF thumbnail before decoding it. Photos
            // from the device will pass, but images that are side loaded from
            // other cameras may not.
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeByteArray(thumbData, 0, thumbData.length, options);
    // SizedThumbnailBitmap contains the bitmap, which is downsampled either from
    // the thumbnail in exif or the full image.
    // mThumbnailData, mThumbnailWidth and mThumbnailHeight are set together only if mThumbnail is not null.
    // The width/height of the sized bitmap may be different from mThumbnailWidth/mThumbnailHeight.
    private static class SizedThumbnailBitmap {
        public byte[] mThumbnailData;
        public Bitmap mBitmap;
        public int mThumbnailWidth;
        public int mThumbnailHeight;
    }

            int width = options.outWidth;
            int height = options.outHeight;
    // Creates a bitmap by either downsampling from the thumbnail in EXIF or the full image.
    // The functions returns a SizedThumbnailBitmap,
    // which contains a downsampled bitmap and the thumbnail data in EXIF if exists.
    private static void createThumbnailFromEXIF(String filePath, int targetSize,
            int maxPixels, SizedThumbnailBitmap sizedThumbBitmap) {
        if (filePath == null) return;

            if (width >= targetSize && height >= targetSize) {
                return thumbData;
        ExifInterface exif = null;
        byte [] thumbData = null;
        try {
            exif = new ExifInterface(filePath);
            if (exif != null) {
                thumbData = exif.getThumbnail();
            }
        } catch (IOException ex) {
            Log.w(TAG, ex);
        }
        return null;

        BitmapFactory.Options fullOptions = new BitmapFactory.Options();
        BitmapFactory.Options exifOptions = new BitmapFactory.Options();
        int exifThumbWidth = 0;
        int fullThumbWidth = 0;

        // Compute exifThumbWidth.
        if (thumbData != null) {
            exifOptions.inJustDecodeBounds = true;
            BitmapFactory.decodeByteArray(thumbData, 0, thumbData.length, exifOptions);
            exifOptions.inSampleSize = computeSampleSize(exifOptions, targetSize, maxPixels);
            exifThumbWidth = exifOptions.outWidth / exifOptions.inSampleSize;
        }

        // Compute fullThumbWidth.
        fullOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, fullOptions);
        fullOptions.inSampleSize = computeSampleSize(fullOptions, targetSize, maxPixels);
        fullThumbWidth = fullOptions.outWidth / fullOptions.inSampleSize;

        // Choose the larger thumbnail as the returning sizedThumbBitmap.
        if (exifThumbWidth > fullThumbWidth) {
            int width = exifOptions.outWidth;
            int height = exifOptions.outHeight;
            exifOptions.inJustDecodeBounds = false;
            sizedThumbBitmap.mBitmap = BitmapFactory.decodeByteArray(thumbData, 0,
                    thumbData.length, exifOptions);
            if (sizedThumbBitmap.mBitmap != null) {
                sizedThumbBitmap.mThumbnailData = thumbData;
                sizedThumbBitmap.mThumbnailWidth = width;
                sizedThumbBitmap.mThumbnailHeight = height;
            }
        } else {
            fullOptions.inJustDecodeBounds = false;
            sizedThumbBitmap.mBitmap = BitmapFactory.decodeFile(filePath, fullOptions);
        }
    }
}