Loading gallerycommon/src/com/android/gallery3d/common/BitmapUtils.java +17 −32 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ import java.lang.reflect.Method; public class BitmapUtils { private static final String TAG = "BitmapUtils"; private static final int COMPRESS_JPEG_QUALITY = 90; private static final int DEFAULT_JPEG_QUALITY = 90; public static final int UNCONSTRAINED = -1; private BitmapUtils(){} Loading Loading @@ -94,7 +94,7 @@ public class BitmapUtils { : initialSize / 8 * 8; } // Fin the min x that 1 / x <= scale // Find the min x that 1 / x >= scale public static int computeSampleSizeLarger(float scale) { int initialSize = (int) FloatMath.floor(1f / scale); if (initialSize <= 1) return 1; Loading @@ -104,7 +104,7 @@ public class BitmapUtils { : initialSize / 8 * 8; } // Find the max x that 1 / x >= scale. // Find the max x that 1 / x <= scale. public static int computeSampleSize(float scale) { Utils.assertTrue(scale > 0); int initialSize = Math.max(1, (int) FloatMath.ceil(1 / scale)); Loading Loading @@ -146,27 +146,15 @@ public class BitmapUtils { return resizeBitmapByScale(bitmap, scale, recycle); } // Resize the bitmap if each side is >= targetSize * 2 public static Bitmap resizeDownIfTooBig( Bitmap bitmap, int targetSize, boolean recycle) { int srcWidth = bitmap.getWidth(); int srcHeight = bitmap.getHeight(); float scale = Math.max( (float) targetSize / srcWidth, (float) targetSize / srcHeight); if (scale > 0.5f) return bitmap; return resizeBitmapByScale(bitmap, scale, recycle); } public static Bitmap resizeDownAndCropCenter(Bitmap bitmap, int size, boolean recycle) { public static Bitmap resizeAndCropCenter(Bitmap bitmap, int size, boolean recycle) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); int minSide = Math.min(w, h); if (w == h && minSide <= size) return bitmap; size = Math.min(size, minSide); if (w == size && h == size) return bitmap; // scale the image so that the shorter side equals to the target; // the longer side will be center-cropped. float scale = (float) size / Math.min(w, h); float scale = Math.max((float) size / bitmap.getWidth(), (float) size / bitmap.getHeight()); Bitmap target = Bitmap.createBitmap(size, size, getConfig(bitmap)); int width = Math.round(scale * bitmap.getWidth()); int height = Math.round(scale * bitmap.getHeight()); Loading Loading @@ -247,11 +235,14 @@ public class BitmapUtils { return null; } public static byte[] compressBitmap(Bitmap bitmap) { ByteArrayOutputStream os = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, COMPRESS_JPEG_QUALITY, os); return os.toByteArray(); public static byte[] compressToBytes(Bitmap bitmap) { return compressToBytes(bitmap, DEFAULT_JPEG_QUALITY); } public static byte[] compressToBytes(Bitmap bitmap, int quality) { ByteArrayOutputStream baos = new ByteArrayOutputStream(65536); bitmap.compress(CompressFormat.JPEG, quality, baos); return baos.toByteArray(); } public static boolean isSupportedByRegionDecoder(String mimeType) { Loading @@ -266,10 +257,4 @@ public class BitmapUtils { mimeType = mimeType.toLowerCase(); return mimeType.equals("image/jpeg"); } public static byte[] compressToBytes(Bitmap bitmap, int quality) { ByteArrayOutputStream baos = new ByteArrayOutputStream(65536); bitmap.compress(CompressFormat.JPEG, quality, baos); return baos.toByteArray(); } } gallerycommon/src/com/android/gallery3d/common/Utils.java +5 −5 Original line number Diff line number Diff line Loading @@ -16,22 +16,17 @@ package com.android.gallery3d.common; import android.app.PendingIntent; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.database.Cursor; import android.os.Build; import android.os.Environment; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.StatFs; import android.text.TextUtils; import android.util.Log; import java.io.Closeable; import java.io.InterruptedIOException; import java.util.Random; public class Utils { private static final String TAG = "Utils"; Loading Loading @@ -336,4 +331,9 @@ public class Utils { int length = Math.min(s.length(), MASK_STRING.length()); return IS_DEBUG_BUILD ? s : MASK_STRING.substring(0, length); } // This method should be ONLY used for debugging. public static void debug(String message, Object ... args) { Log.v(DEBUG_TAG, String.format(message, args)); } } src/com/android/gallery3d/app/AbstractGalleryActivity.java +8 −9 Original line number Diff line number Diff line Loading @@ -16,15 +16,6 @@ package com.android.gallery3d.app; import com.android.gallery3d.R; import com.android.gallery3d.data.DataManager; import com.android.gallery3d.data.ImageCacheService; import com.android.gallery3d.ui.GLRoot; import com.android.gallery3d.ui.GLRootView; import com.android.gallery3d.ui.PositionRepository; import com.android.gallery3d.util.ThreadPool; import android.app.ActionBar; import android.app.Activity; import android.app.AlertDialog; import android.content.BroadcastReceiver; Loading @@ -39,6 +30,13 @@ import android.os.Bundle; import android.view.Window; import android.view.WindowManager; import com.android.gallery3d.R; import com.android.gallery3d.data.DataManager; import com.android.gallery3d.ui.BitmapPool; import com.android.gallery3d.ui.GLRoot; import com.android.gallery3d.ui.GLRootView; import com.android.gallery3d.util.ThreadPool; public class AbstractGalleryActivity extends Activity implements GalleryActivity { @SuppressWarnings("unused") private static final String TAG = "AbstractGalleryActivity"; Loading Loading @@ -177,6 +175,7 @@ public class AbstractGalleryActivity extends Activity implements GalleryActivity } finally { mGLRootView.unlockRenderThread(); } BitmapPool.clear(); } @Override Loading src/com/android/gallery3d/data/DecodeUtils.java +54 −29 Original line number Diff line number Diff line Loading @@ -16,20 +16,17 @@ package com.android.gallery3d.data; import com.android.gallery3d.common.BitmapUtils; import com.android.gallery3d.common.Utils; import com.android.gallery3d.util.ThreadPool.CancelListener; import com.android.gallery3d.util.ThreadPool.JobContext; import android.content.ContentResolver; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; import android.graphics.BitmapRegionDecoder; import android.graphics.Rect; import android.net.Uri; import android.os.ParcelFileDescriptor; import android.util.FloatMath; import com.android.gallery3d.common.BitmapUtils; import com.android.gallery3d.common.Utils; import com.android.gallery3d.util.ThreadPool.CancelListener; import com.android.gallery3d.util.ThreadPool.JobContext; import java.io.FileDescriptor; import java.io.FileInputStream; Loading @@ -40,27 +37,29 @@ public class DecodeUtils { private static class DecodeCanceller implements CancelListener { Options mOptions; public DecodeCanceller(Options options) { mOptions = options; } @Override public void onCancel() { mOptions.requestCancelDecode(); } } public static Bitmap requestDecode(JobContext jc, FileDescriptor fd, Options options) { public static Bitmap decode(JobContext jc, FileDescriptor fd, Options options) { if (options == null) options = new Options(); jc.setCancelListener(new DecodeCanceller(options)); return ensureGLCompatibleBitmap( BitmapFactory.decodeFileDescriptor(fd, null, options)); } public static Bitmap requestDecode(JobContext jc, byte[] bytes, Options options) { return requestDecode(jc, bytes, 0, bytes.length, options); public static Bitmap decode(JobContext jc, byte[] bytes, Options options) { return decode(jc, bytes, 0, bytes.length, options); } public static Bitmap requestDecode(JobContext jc, byte[] bytes, int offset, public static Bitmap decode(JobContext jc, byte[] bytes, int offset, int length, Options options) { if (options == null) options = new Options(); jc.setCancelListener(new DecodeCanceller(options)); Loading @@ -68,13 +67,13 @@ public class DecodeUtils { BitmapFactory.decodeByteArray(bytes, offset, length, options)); } public static Bitmap requestDecode(JobContext jc, final String filePath, Options options, int targetSize) { public static Bitmap decodeThumbnail( JobContext jc, String filePath, Options options, int targetSize, int type) { FileInputStream fis = null; try { fis = new FileInputStream(filePath); FileDescriptor fd = fis.getFD(); return requestDecode(jc, fd, options, targetSize); return decodeThumbnail(jc, fd, options, targetSize, type); } catch (Exception ex) { Log.w(TAG, ex); return null; Loading @@ -83,8 +82,8 @@ public class DecodeUtils { } } public static Bitmap requestDecode(JobContext jc, FileDescriptor fd, Options options, int targetSize) { public static Bitmap decodeThumbnail( JobContext jc, FileDescriptor fd, Options options, int targetSize, int type) { if (options == null) options = new Options(); jc.setCancelListener(new DecodeCanceller(options)); Loading @@ -92,14 +91,40 @@ public class DecodeUtils { BitmapFactory.decodeFileDescriptor(fd, null, options); if (jc.isCancelled()) return null; options.inSampleSize = BitmapUtils.computeSampleSizeLarger( options.outWidth, options.outHeight, targetSize); int w = options.outWidth; int h = options.outHeight; if (type == MediaItem.TYPE_MICROTHUMBNAIL) { // We center-crop the original image as it's micro thumbnail. In this case, // we want to make sure the shorter side >= "targetSize". float scale = (float) targetSize / Math.min(w, h); options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); // For an extremely wide image, e.g. 300x30000, we may got OOM when decoding // it for TYPE_MICROTHUMBNAIL. So we add a max number of pixels limit here. final int MAX_PIXEL_COUNT = 640000; // 400 x 1600 if ((w / options.inSampleSize) * (h / options.inSampleSize) > MAX_PIXEL_COUNT) { options.inSampleSize = BitmapUtils.computeSampleSize( FloatMath.sqrt((float) MAX_PIXEL_COUNT / (w * h))); } } else { // For screen nail, we only want to keep the longer side >= targetSize. float scale = (float) targetSize / Math.max(w, h); options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); } options.inJustDecodeBounds = false; Bitmap result = BitmapFactory.decodeFileDescriptor(fd, null, options); // We need to resize down if the decoder does not support inSampleSize. // (For example, GIF images.) result = BitmapUtils.resizeDownIfTooBig(result, targetSize, true); if (result == null) return null; // We need to resize down if the decoder does not support inSampleSize // (For example, GIF images) float scale = (float) targetSize / (type == MediaItem.TYPE_MICROTHUMBNAIL ? Math.min(result.getWidth(), result.getHeight()) : Math.max(result.getWidth(), result.getHeight())); if (scale <= 0.5) result = BitmapUtils.resizeBitmapByScale(result, scale, true); return ensureGLCompatibleBitmap(result); } Loading @@ -110,7 +135,7 @@ public class DecodeUtils { * Note: The returned image may be resized down. However, both width and height must be * larger than the <code>targetSize</code>. */ public static Bitmap requestDecodeIfBigEnough(JobContext jc, byte[] data, public static Bitmap decodeIfBigEnough(JobContext jc, byte[] data, Options options, int targetSize) { if (options == null) options = new Options(); jc.setCancelListener(new DecodeCanceller(options)); Loading Loading @@ -138,7 +163,7 @@ public class DecodeUtils { return newBitmap; } public static BitmapRegionDecoder requestCreateBitmapRegionDecoder( public static BitmapRegionDecoder createBitmapRegionDecoder( JobContext jc, byte[] bytes, int offset, int length, boolean shareable) { if (offset < 0 || length <= 0 || offset + length > bytes.length) { Loading @@ -156,7 +181,7 @@ public class DecodeUtils { } } public static BitmapRegionDecoder requestCreateBitmapRegionDecoder( public static BitmapRegionDecoder createBitmapRegionDecoder( JobContext jc, String filePath, boolean shareable) { try { return BitmapRegionDecoder.newInstance(filePath, shareable); Loading @@ -166,7 +191,7 @@ public class DecodeUtils { } } public static BitmapRegionDecoder requestCreateBitmapRegionDecoder( public static BitmapRegionDecoder createBitmapRegionDecoder( JobContext jc, FileDescriptor fd, boolean shareable) { try { return BitmapRegionDecoder.newInstance(fd, shareable); Loading @@ -176,7 +201,7 @@ public class DecodeUtils { } } public static BitmapRegionDecoder requestCreateBitmapRegionDecoder( public static BitmapRegionDecoder createBitmapRegionDecoder( JobContext jc, InputStream is, boolean shareable) { try { return BitmapRegionDecoder.newInstance(is, shareable); Loading src/com/android/gallery3d/data/ImageCacheRequest.java +15 −10 Original line number Diff line number Diff line Loading @@ -16,15 +16,16 @@ package com.android.gallery3d.data; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import com.android.gallery3d.app.GalleryApp; import com.android.gallery3d.common.BitmapUtils; import com.android.gallery3d.data.ImageCacheService.ImageData; import com.android.gallery3d.ui.BitmapPool; import com.android.gallery3d.util.ThreadPool.Job; import com.android.gallery3d.util.ThreadPool.JobContext; import android.graphics.Bitmap; import android.graphics.BitmapFactory; abstract class ImageCacheRequest implements Job<Bitmap> { private static final String TAG = "ImageCacheRequest"; Loading Loading @@ -53,8 +54,14 @@ abstract class ImageCacheRequest implements Job<Bitmap> { if (data != null) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_8888; Bitmap bitmap = DecodeUtils.requestDecode(jc, data.mData, data.mOffset, data.mData.length - data.mOffset, options); Bitmap bitmap; if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { bitmap = BitmapPool.decode(jc, BitmapPool.TYPE_MICRO_THUMB, data.mData, data.mOffset, data.mData.length - data.mOffset, options); } else { bitmap = DecodeUtils.decode(jc, data.mData, data.mOffset, data.mData.length - data.mOffset, options); } if (bitmap == null && !jc.isCancelled()) { Log.w(TAG, "decode cached failed " + debugTag); } Loading @@ -69,15 +76,13 @@ abstract class ImageCacheRequest implements Job<Bitmap> { } if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { bitmap = BitmapUtils.resizeDownAndCropCenter(bitmap, mTargetSize, true); bitmap = BitmapUtils.resizeAndCropCenter(bitmap, mTargetSize, true); } else { bitmap = BitmapUtils.resizeDownBySideLength(bitmap, mTargetSize, true); bitmap = BitmapUtils.resizeDownBySideLength(bitmap, mTargetSize, true); } if (jc.isCancelled()) return null; byte[] array = BitmapUtils.compressBitmap(bitmap); byte[] array = BitmapUtils.compressToBytes(bitmap); if (jc.isCancelled()) return null; cacheService.putImageData(mPath, mType, array); Loading Loading
gallerycommon/src/com/android/gallery3d/common/BitmapUtils.java +17 −32 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ import java.lang.reflect.Method; public class BitmapUtils { private static final String TAG = "BitmapUtils"; private static final int COMPRESS_JPEG_QUALITY = 90; private static final int DEFAULT_JPEG_QUALITY = 90; public static final int UNCONSTRAINED = -1; private BitmapUtils(){} Loading Loading @@ -94,7 +94,7 @@ public class BitmapUtils { : initialSize / 8 * 8; } // Fin the min x that 1 / x <= scale // Find the min x that 1 / x >= scale public static int computeSampleSizeLarger(float scale) { int initialSize = (int) FloatMath.floor(1f / scale); if (initialSize <= 1) return 1; Loading @@ -104,7 +104,7 @@ public class BitmapUtils { : initialSize / 8 * 8; } // Find the max x that 1 / x >= scale. // Find the max x that 1 / x <= scale. public static int computeSampleSize(float scale) { Utils.assertTrue(scale > 0); int initialSize = Math.max(1, (int) FloatMath.ceil(1 / scale)); Loading Loading @@ -146,27 +146,15 @@ public class BitmapUtils { return resizeBitmapByScale(bitmap, scale, recycle); } // Resize the bitmap if each side is >= targetSize * 2 public static Bitmap resizeDownIfTooBig( Bitmap bitmap, int targetSize, boolean recycle) { int srcWidth = bitmap.getWidth(); int srcHeight = bitmap.getHeight(); float scale = Math.max( (float) targetSize / srcWidth, (float) targetSize / srcHeight); if (scale > 0.5f) return bitmap; return resizeBitmapByScale(bitmap, scale, recycle); } public static Bitmap resizeDownAndCropCenter(Bitmap bitmap, int size, boolean recycle) { public static Bitmap resizeAndCropCenter(Bitmap bitmap, int size, boolean recycle) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); int minSide = Math.min(w, h); if (w == h && minSide <= size) return bitmap; size = Math.min(size, minSide); if (w == size && h == size) return bitmap; // scale the image so that the shorter side equals to the target; // the longer side will be center-cropped. float scale = (float) size / Math.min(w, h); float scale = Math.max((float) size / bitmap.getWidth(), (float) size / bitmap.getHeight()); Bitmap target = Bitmap.createBitmap(size, size, getConfig(bitmap)); int width = Math.round(scale * bitmap.getWidth()); int height = Math.round(scale * bitmap.getHeight()); Loading Loading @@ -247,11 +235,14 @@ public class BitmapUtils { return null; } public static byte[] compressBitmap(Bitmap bitmap) { ByteArrayOutputStream os = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, COMPRESS_JPEG_QUALITY, os); return os.toByteArray(); public static byte[] compressToBytes(Bitmap bitmap) { return compressToBytes(bitmap, DEFAULT_JPEG_QUALITY); } public static byte[] compressToBytes(Bitmap bitmap, int quality) { ByteArrayOutputStream baos = new ByteArrayOutputStream(65536); bitmap.compress(CompressFormat.JPEG, quality, baos); return baos.toByteArray(); } public static boolean isSupportedByRegionDecoder(String mimeType) { Loading @@ -266,10 +257,4 @@ public class BitmapUtils { mimeType = mimeType.toLowerCase(); return mimeType.equals("image/jpeg"); } public static byte[] compressToBytes(Bitmap bitmap, int quality) { ByteArrayOutputStream baos = new ByteArrayOutputStream(65536); bitmap.compress(CompressFormat.JPEG, quality, baos); return baos.toByteArray(); } }
gallerycommon/src/com/android/gallery3d/common/Utils.java +5 −5 Original line number Diff line number Diff line Loading @@ -16,22 +16,17 @@ package com.android.gallery3d.common; import android.app.PendingIntent; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.database.Cursor; import android.os.Build; import android.os.Environment; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.StatFs; import android.text.TextUtils; import android.util.Log; import java.io.Closeable; import java.io.InterruptedIOException; import java.util.Random; public class Utils { private static final String TAG = "Utils"; Loading Loading @@ -336,4 +331,9 @@ public class Utils { int length = Math.min(s.length(), MASK_STRING.length()); return IS_DEBUG_BUILD ? s : MASK_STRING.substring(0, length); } // This method should be ONLY used for debugging. public static void debug(String message, Object ... args) { Log.v(DEBUG_TAG, String.format(message, args)); } }
src/com/android/gallery3d/app/AbstractGalleryActivity.java +8 −9 Original line number Diff line number Diff line Loading @@ -16,15 +16,6 @@ package com.android.gallery3d.app; import com.android.gallery3d.R; import com.android.gallery3d.data.DataManager; import com.android.gallery3d.data.ImageCacheService; import com.android.gallery3d.ui.GLRoot; import com.android.gallery3d.ui.GLRootView; import com.android.gallery3d.ui.PositionRepository; import com.android.gallery3d.util.ThreadPool; import android.app.ActionBar; import android.app.Activity; import android.app.AlertDialog; import android.content.BroadcastReceiver; Loading @@ -39,6 +30,13 @@ import android.os.Bundle; import android.view.Window; import android.view.WindowManager; import com.android.gallery3d.R; import com.android.gallery3d.data.DataManager; import com.android.gallery3d.ui.BitmapPool; import com.android.gallery3d.ui.GLRoot; import com.android.gallery3d.ui.GLRootView; import com.android.gallery3d.util.ThreadPool; public class AbstractGalleryActivity extends Activity implements GalleryActivity { @SuppressWarnings("unused") private static final String TAG = "AbstractGalleryActivity"; Loading Loading @@ -177,6 +175,7 @@ public class AbstractGalleryActivity extends Activity implements GalleryActivity } finally { mGLRootView.unlockRenderThread(); } BitmapPool.clear(); } @Override Loading
src/com/android/gallery3d/data/DecodeUtils.java +54 −29 Original line number Diff line number Diff line Loading @@ -16,20 +16,17 @@ package com.android.gallery3d.data; import com.android.gallery3d.common.BitmapUtils; import com.android.gallery3d.common.Utils; import com.android.gallery3d.util.ThreadPool.CancelListener; import com.android.gallery3d.util.ThreadPool.JobContext; import android.content.ContentResolver; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; import android.graphics.BitmapRegionDecoder; import android.graphics.Rect; import android.net.Uri; import android.os.ParcelFileDescriptor; import android.util.FloatMath; import com.android.gallery3d.common.BitmapUtils; import com.android.gallery3d.common.Utils; import com.android.gallery3d.util.ThreadPool.CancelListener; import com.android.gallery3d.util.ThreadPool.JobContext; import java.io.FileDescriptor; import java.io.FileInputStream; Loading @@ -40,27 +37,29 @@ public class DecodeUtils { private static class DecodeCanceller implements CancelListener { Options mOptions; public DecodeCanceller(Options options) { mOptions = options; } @Override public void onCancel() { mOptions.requestCancelDecode(); } } public static Bitmap requestDecode(JobContext jc, FileDescriptor fd, Options options) { public static Bitmap decode(JobContext jc, FileDescriptor fd, Options options) { if (options == null) options = new Options(); jc.setCancelListener(new DecodeCanceller(options)); return ensureGLCompatibleBitmap( BitmapFactory.decodeFileDescriptor(fd, null, options)); } public static Bitmap requestDecode(JobContext jc, byte[] bytes, Options options) { return requestDecode(jc, bytes, 0, bytes.length, options); public static Bitmap decode(JobContext jc, byte[] bytes, Options options) { return decode(jc, bytes, 0, bytes.length, options); } public static Bitmap requestDecode(JobContext jc, byte[] bytes, int offset, public static Bitmap decode(JobContext jc, byte[] bytes, int offset, int length, Options options) { if (options == null) options = new Options(); jc.setCancelListener(new DecodeCanceller(options)); Loading @@ -68,13 +67,13 @@ public class DecodeUtils { BitmapFactory.decodeByteArray(bytes, offset, length, options)); } public static Bitmap requestDecode(JobContext jc, final String filePath, Options options, int targetSize) { public static Bitmap decodeThumbnail( JobContext jc, String filePath, Options options, int targetSize, int type) { FileInputStream fis = null; try { fis = new FileInputStream(filePath); FileDescriptor fd = fis.getFD(); return requestDecode(jc, fd, options, targetSize); return decodeThumbnail(jc, fd, options, targetSize, type); } catch (Exception ex) { Log.w(TAG, ex); return null; Loading @@ -83,8 +82,8 @@ public class DecodeUtils { } } public static Bitmap requestDecode(JobContext jc, FileDescriptor fd, Options options, int targetSize) { public static Bitmap decodeThumbnail( JobContext jc, FileDescriptor fd, Options options, int targetSize, int type) { if (options == null) options = new Options(); jc.setCancelListener(new DecodeCanceller(options)); Loading @@ -92,14 +91,40 @@ public class DecodeUtils { BitmapFactory.decodeFileDescriptor(fd, null, options); if (jc.isCancelled()) return null; options.inSampleSize = BitmapUtils.computeSampleSizeLarger( options.outWidth, options.outHeight, targetSize); int w = options.outWidth; int h = options.outHeight; if (type == MediaItem.TYPE_MICROTHUMBNAIL) { // We center-crop the original image as it's micro thumbnail. In this case, // we want to make sure the shorter side >= "targetSize". float scale = (float) targetSize / Math.min(w, h); options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); // For an extremely wide image, e.g. 300x30000, we may got OOM when decoding // it for TYPE_MICROTHUMBNAIL. So we add a max number of pixels limit here. final int MAX_PIXEL_COUNT = 640000; // 400 x 1600 if ((w / options.inSampleSize) * (h / options.inSampleSize) > MAX_PIXEL_COUNT) { options.inSampleSize = BitmapUtils.computeSampleSize( FloatMath.sqrt((float) MAX_PIXEL_COUNT / (w * h))); } } else { // For screen nail, we only want to keep the longer side >= targetSize. float scale = (float) targetSize / Math.max(w, h); options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); } options.inJustDecodeBounds = false; Bitmap result = BitmapFactory.decodeFileDescriptor(fd, null, options); // We need to resize down if the decoder does not support inSampleSize. // (For example, GIF images.) result = BitmapUtils.resizeDownIfTooBig(result, targetSize, true); if (result == null) return null; // We need to resize down if the decoder does not support inSampleSize // (For example, GIF images) float scale = (float) targetSize / (type == MediaItem.TYPE_MICROTHUMBNAIL ? Math.min(result.getWidth(), result.getHeight()) : Math.max(result.getWidth(), result.getHeight())); if (scale <= 0.5) result = BitmapUtils.resizeBitmapByScale(result, scale, true); return ensureGLCompatibleBitmap(result); } Loading @@ -110,7 +135,7 @@ public class DecodeUtils { * Note: The returned image may be resized down. However, both width and height must be * larger than the <code>targetSize</code>. */ public static Bitmap requestDecodeIfBigEnough(JobContext jc, byte[] data, public static Bitmap decodeIfBigEnough(JobContext jc, byte[] data, Options options, int targetSize) { if (options == null) options = new Options(); jc.setCancelListener(new DecodeCanceller(options)); Loading Loading @@ -138,7 +163,7 @@ public class DecodeUtils { return newBitmap; } public static BitmapRegionDecoder requestCreateBitmapRegionDecoder( public static BitmapRegionDecoder createBitmapRegionDecoder( JobContext jc, byte[] bytes, int offset, int length, boolean shareable) { if (offset < 0 || length <= 0 || offset + length > bytes.length) { Loading @@ -156,7 +181,7 @@ public class DecodeUtils { } } public static BitmapRegionDecoder requestCreateBitmapRegionDecoder( public static BitmapRegionDecoder createBitmapRegionDecoder( JobContext jc, String filePath, boolean shareable) { try { return BitmapRegionDecoder.newInstance(filePath, shareable); Loading @@ -166,7 +191,7 @@ public class DecodeUtils { } } public static BitmapRegionDecoder requestCreateBitmapRegionDecoder( public static BitmapRegionDecoder createBitmapRegionDecoder( JobContext jc, FileDescriptor fd, boolean shareable) { try { return BitmapRegionDecoder.newInstance(fd, shareable); Loading @@ -176,7 +201,7 @@ public class DecodeUtils { } } public static BitmapRegionDecoder requestCreateBitmapRegionDecoder( public static BitmapRegionDecoder createBitmapRegionDecoder( JobContext jc, InputStream is, boolean shareable) { try { return BitmapRegionDecoder.newInstance(is, shareable); Loading
src/com/android/gallery3d/data/ImageCacheRequest.java +15 −10 Original line number Diff line number Diff line Loading @@ -16,15 +16,16 @@ package com.android.gallery3d.data; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import com.android.gallery3d.app.GalleryApp; import com.android.gallery3d.common.BitmapUtils; import com.android.gallery3d.data.ImageCacheService.ImageData; import com.android.gallery3d.ui.BitmapPool; import com.android.gallery3d.util.ThreadPool.Job; import com.android.gallery3d.util.ThreadPool.JobContext; import android.graphics.Bitmap; import android.graphics.BitmapFactory; abstract class ImageCacheRequest implements Job<Bitmap> { private static final String TAG = "ImageCacheRequest"; Loading Loading @@ -53,8 +54,14 @@ abstract class ImageCacheRequest implements Job<Bitmap> { if (data != null) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_8888; Bitmap bitmap = DecodeUtils.requestDecode(jc, data.mData, data.mOffset, data.mData.length - data.mOffset, options); Bitmap bitmap; if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { bitmap = BitmapPool.decode(jc, BitmapPool.TYPE_MICRO_THUMB, data.mData, data.mOffset, data.mData.length - data.mOffset, options); } else { bitmap = DecodeUtils.decode(jc, data.mData, data.mOffset, data.mData.length - data.mOffset, options); } if (bitmap == null && !jc.isCancelled()) { Log.w(TAG, "decode cached failed " + debugTag); } Loading @@ -69,15 +76,13 @@ abstract class ImageCacheRequest implements Job<Bitmap> { } if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { bitmap = BitmapUtils.resizeDownAndCropCenter(bitmap, mTargetSize, true); bitmap = BitmapUtils.resizeAndCropCenter(bitmap, mTargetSize, true); } else { bitmap = BitmapUtils.resizeDownBySideLength(bitmap, mTargetSize, true); bitmap = BitmapUtils.resizeDownBySideLength(bitmap, mTargetSize, true); } if (jc.isCancelled()) return null; byte[] array = BitmapUtils.compressBitmap(bitmap); byte[] array = BitmapUtils.compressToBytes(bitmap); if (jc.isCancelled()) return null; cacheService.putImageData(mPath, mType, array); Loading