diff options
Diffstat (limited to 'src/com/android/gallery3d/filtershow/cache/ImageLoader.java')
-rw-r--r-- | src/com/android/gallery3d/filtershow/cache/ImageLoader.java | 502 |
1 files changed, 0 insertions, 502 deletions
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java deleted file mode 100644 index b6c72fd9d..000000000 --- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * 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. - */ - -package com.android.gallery3d.filtershow.cache; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.database.Cursor; -import android.database.sqlite.SQLiteException; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.graphics.Matrix; -import android.graphics.Rect; -import android.net.Uri; -import android.provider.MediaStore; -import android.util.Log; -import android.webkit.MimeTypeMap; - -import com.adobe.xmp.XMPException; -import com.adobe.xmp.XMPMeta; -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.exif.ExifInterface; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.util.XmpUtilHelper; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; - -public final class ImageLoader { - - private static final String LOGTAG = "ImageLoader"; - - public static final String JPEG_MIME_TYPE = "image/jpeg"; - public static final int DEFAULT_COMPRESS_QUALITY = 95; - - public static final int ORI_NORMAL = ExifInterface.Orientation.TOP_LEFT; - public static final int ORI_ROTATE_90 = ExifInterface.Orientation.RIGHT_TOP; - public static final int ORI_ROTATE_180 = ExifInterface.Orientation.BOTTOM_LEFT; - public static final int ORI_ROTATE_270 = ExifInterface.Orientation.RIGHT_BOTTOM; - public static final int ORI_FLIP_HOR = ExifInterface.Orientation.TOP_RIGHT; - public static final int ORI_FLIP_VERT = ExifInterface.Orientation.BOTTOM_RIGHT; - public static final int ORI_TRANSPOSE = ExifInterface.Orientation.LEFT_TOP; - public static final int ORI_TRANSVERSE = ExifInterface.Orientation.LEFT_BOTTOM; - - private static final int BITMAP_LOAD_BACKOUT_ATTEMPTS = 5; - - private ImageLoader() {} - - /** - * Returns the Mime type for a Url. Safe to use with Urls that do not - * come from Gallery's content provider. - */ - public static String getMimeType(Uri src) { - String postfix = MimeTypeMap.getFileExtensionFromUrl(src.toString()); - String ret = null; - if (postfix != null) { - ret = MimeTypeMap.getSingleton().getMimeTypeFromExtension(postfix); - } - return ret; - } - - /** - * Returns the image's orientation flag. Defaults to ORI_NORMAL if no valid - * orientation was found. - */ - public static int getMetadataOrientation(Context context, Uri uri) { - if (uri == null || context == null) { - throw new IllegalArgumentException("bad argument to getOrientation"); - } - - // First try to find orientation data in Gallery's ContentProvider. - Cursor cursor = null; - try { - cursor = context.getContentResolver().query(uri, - new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, - null, null, null); - if (cursor != null && cursor.moveToNext()) { - int ori = cursor.getInt(0); - switch (ori) { - case 90: - return ORI_ROTATE_90; - case 270: - return ORI_ROTATE_270; - case 180: - return ORI_ROTATE_180; - default: - return ORI_NORMAL; - } - } - } catch (SQLiteException e) { - // Do nothing - } catch (IllegalArgumentException e) { - // Do nothing - } finally { - Utils.closeSilently(cursor); - } - - // Fall back to checking EXIF tags in file. - if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { - String mimeType = getMimeType(uri); - if (!JPEG_MIME_TYPE.equals(mimeType)) { - return ORI_NORMAL; - } - String path = uri.getPath(); - ExifInterface exif = new ExifInterface(); - try { - exif.readExif(path); - Integer tagval = exif.getTagIntValue(ExifInterface.TAG_ORIENTATION); - if (tagval != null) { - int orientation = tagval; - switch(orientation) { - case ORI_NORMAL: - case ORI_ROTATE_90: - case ORI_ROTATE_180: - case ORI_ROTATE_270: - case ORI_FLIP_HOR: - case ORI_FLIP_VERT: - case ORI_TRANSPOSE: - case ORI_TRANSVERSE: - return orientation; - default: - return ORI_NORMAL; - } - } - } catch (IOException e) { - Log.w(LOGTAG, "Failed to read EXIF orientation", e); - } - } - return ORI_NORMAL; - } - - /** - * Returns the rotation of image at the given URI as one of 0, 90, 180, - * 270. Defaults to 0. - */ - public static int getMetadataRotation(Context context, Uri uri) { - int orientation = getMetadataOrientation(context, uri); - switch(orientation) { - case ORI_ROTATE_90: - return 90; - case ORI_ROTATE_180: - return 180; - case ORI_ROTATE_270: - return 270; - default: - return 0; - } - } - - /** - * Takes an orientation and a bitmap, and returns the bitmap transformed - * to that orientation. - */ - public static Bitmap orientBitmap(Bitmap bitmap, int ori) { - Matrix matrix = new Matrix(); - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - if (ori == ORI_ROTATE_90 || - ori == ORI_ROTATE_270 || - ori == ORI_TRANSPOSE || - ori == ORI_TRANSVERSE) { - int tmp = w; - w = h; - h = tmp; - } - switch (ori) { - case ORI_ROTATE_90: - matrix.setRotate(90, w / 2f, h / 2f); - break; - case ORI_ROTATE_180: - matrix.setRotate(180, w / 2f, h / 2f); - break; - case ORI_ROTATE_270: - matrix.setRotate(270, w / 2f, h / 2f); - break; - case ORI_FLIP_HOR: - matrix.preScale(-1, 1); - break; - case ORI_FLIP_VERT: - matrix.preScale(1, -1); - break; - case ORI_TRANSPOSE: - matrix.setRotate(90, w / 2f, h / 2f); - matrix.preScale(1, -1); - break; - case ORI_TRANSVERSE: - matrix.setRotate(270, w / 2f, h / 2f); - matrix.preScale(1, -1); - break; - case ORI_NORMAL: - default: - return bitmap; - } - return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), - bitmap.getHeight(), matrix, true); - } - - /** - * Returns the bitmap for the rectangular region given by "bounds" - * if it is a subset of the bitmap stored at uri. Otherwise returns - * null. - */ - public static Bitmap loadRegionBitmap(Context context, Uri uri, BitmapFactory.Options options, - Rect bounds) { - InputStream is = null; - try { - is = context.getContentResolver().openInputStream(uri); - BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false); - Rect r = new Rect(0, 0, decoder.getWidth(), decoder.getHeight()); - // return null if bounds are not entirely within the bitmap - if (!r.contains(bounds)) { - return null; - } - return decoder.decodeRegion(bounds, options); - } catch (FileNotFoundException e) { - Log.e(LOGTAG, "FileNotFoundException for " + uri, e); - } catch (IOException e) { - Log.e(LOGTAG, "FileNotFoundException for " + uri, e); - } finally { - Utils.closeSilently(is); - } - return null; - } - - /** - * Returns the bounds of the bitmap stored at a given Url. - */ - public static Rect loadBitmapBounds(Context context, Uri uri) { - BitmapFactory.Options o = new BitmapFactory.Options(); - loadBitmap(context, uri, o); - return new Rect(0, 0, o.outWidth, o.outHeight); - } - - /** - * Loads a bitmap that has been downsampled using sampleSize from a given url. - */ - public static Bitmap loadDownsampledBitmap(Context context, Uri uri, int sampleSize) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inMutable = true; - options.inSampleSize = sampleSize; - return loadBitmap(context, uri, options); - } - - - /** - * Returns the bitmap from the given uri loaded using the given options. - * Returns null on failure. - */ - public static Bitmap loadBitmap(Context context, Uri uri, BitmapFactory.Options o) { - if (uri == null || context == null) { - throw new IllegalArgumentException("bad argument to loadBitmap"); - } - InputStream is = null; - try { - is = context.getContentResolver().openInputStream(uri); - return BitmapFactory.decodeStream(is, null, o); - } catch (FileNotFoundException e) { - Log.e(LOGTAG, "FileNotFoundException for " + uri, e); - } finally { - Utils.closeSilently(is); - } - return null; - } - - /** - * Loads a bitmap at a given URI that is downsampled so that both sides are - * smaller than maxSideLength. The Bitmap's original dimensions are stored - * in the rect originalBounds. - * - * @param uri URI of image to open. - * @param context context whose ContentResolver to use. - * @param maxSideLength max side length of returned bitmap. - * @param originalBounds If not null, set to the actual bounds of the stored bitmap. - * @param useMin use min or max side of the original image - * @return downsampled bitmap or null if this operation failed. - */ - public static Bitmap loadConstrainedBitmap(Uri uri, Context context, int maxSideLength, - Rect originalBounds, boolean useMin) { - if (maxSideLength <= 0 || uri == null || context == null) { - throw new IllegalArgumentException("bad argument to getScaledBitmap"); - } - // Get width and height of stored bitmap - Rect storedBounds = loadBitmapBounds(context, uri); - if (originalBounds != null) { - originalBounds.set(storedBounds); - } - int w = storedBounds.width(); - int h = storedBounds.height(); - - // If bitmap cannot be decoded, return null - if (w <= 0 || h <= 0) { - return null; - } - - // Find best downsampling size - int imageSide = 0; - if (useMin) { - imageSide = Math.min(w, h); - } else { - imageSide = Math.max(w, h); - } - int sampleSize = 1; - while (imageSide > maxSideLength) { - imageSide >>>= 1; - sampleSize <<= 1; - } - - // Make sure sample size is reasonable - if (sampleSize <= 0 || - 0 >= (int) (Math.min(w, h) / sampleSize)) { - return null; - } - return loadDownsampledBitmap(context, uri, sampleSize); - } - - /** - * Loads a bitmap at a given URI that is downsampled so that both sides are - * smaller than maxSideLength. The Bitmap's original dimensions are stored - * in the rect originalBounds. The output is also transformed to the given - * orientation. - * - * @param uri URI of image to open. - * @param context context whose ContentResolver to use. - * @param maxSideLength max side length of returned bitmap. - * @param orientation the orientation to transform the bitmap to. - * @param originalBounds set to the actual bounds of the stored bitmap. - * @return downsampled bitmap or null if this operation failed. - */ - public static Bitmap loadOrientedConstrainedBitmap(Uri uri, Context context, int maxSideLength, - int orientation, Rect originalBounds) { - Bitmap bmap = loadConstrainedBitmap(uri, context, maxSideLength, originalBounds, false); - if (bmap != null) { - bmap = orientBitmap(bmap, orientation); - } - return bmap; - } - - public static Bitmap getScaleOneImageForPreset(Context context, Uri uri, Rect bounds, - Rect destination) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inMutable = true; - if (destination != null) { - if (bounds.width() > destination.width()) { - int sampleSize = 1; - int w = bounds.width(); - while (w > destination.width()) { - sampleSize *= 2; - w /= sampleSize; - } - options.inSampleSize = sampleSize; - } - } - Bitmap bmp = loadRegionBitmap(context, uri, options, bounds); - return bmp; - } - - /** - * Loads a bitmap that is downsampled by at least the input sample size. In - * low-memory situations, the bitmap may be downsampled further. - */ - public static Bitmap loadBitmapWithBackouts(Context context, Uri sourceUri, int sampleSize) { - boolean noBitmap = true; - int num_tries = 0; - if (sampleSize <= 0) { - sampleSize = 1; - } - Bitmap bmap = null; - while (noBitmap) { - try { - // Try to decode, downsample if low-memory. - bmap = loadDownsampledBitmap(context, sourceUri, sampleSize); - noBitmap = false; - } catch (java.lang.OutOfMemoryError e) { - // Try with more downsampling before failing for good. - if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) { - throw e; - } - bmap = null; - System.gc(); - sampleSize *= 2; - } - } - return bmap; - } - - /** - * Loads an oriented bitmap that is downsampled by at least the input sample - * size. In low-memory situations, the bitmap may be downsampled further. - */ - public static Bitmap loadOrientedBitmapWithBackouts(Context context, Uri sourceUri, - int sampleSize) { - Bitmap bitmap = loadBitmapWithBackouts(context, sourceUri, sampleSize); - if (bitmap == null) { - return null; - } - int orientation = getMetadataOrientation(context, sourceUri); - bitmap = orientBitmap(bitmap, orientation); - return bitmap; - } - - /** - * Loads bitmap from a resource that may be downsampled in low-memory situations. - */ - public static Bitmap decodeResourceWithBackouts(Resources res, BitmapFactory.Options options, - int id) { - boolean noBitmap = true; - int num_tries = 0; - if (options.inSampleSize < 1) { - options.inSampleSize = 1; - } - // Stopgap fix for low-memory devices. - Bitmap bmap = null; - while (noBitmap) { - try { - // Try to decode, downsample if low-memory. - bmap = BitmapFactory.decodeResource( - res, id, options); - noBitmap = false; - } catch (java.lang.OutOfMemoryError e) { - // Retry before failing for good. - if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) { - throw e; - } - bmap = null; - System.gc(); - options.inSampleSize *= 2; - } - } - return bmap; - } - - public static XMPMeta getXmpObject(Context context) { - try { - InputStream is = context.getContentResolver().openInputStream( - MasterImage.getImage().getUri()); - return XmpUtilHelper.extractXMPMeta(is); - } catch (FileNotFoundException e) { - return null; - } - } - - /** - * Determine if this is a light cycle 360 image - * - * @return true if it is a light Cycle image that is full 360 - */ - public static boolean queryLightCycle360(Context context) { - InputStream is = null; - try { - is = context.getContentResolver().openInputStream(MasterImage.getImage().getUri()); - XMPMeta meta = XmpUtilHelper.extractXMPMeta(is); - if (meta == null) { - return false; - } - String namespace = "http://ns.google.com/photos/1.0/panorama/"; - String cropWidthName = "GPano:CroppedAreaImageWidthPixels"; - String fullWidthName = "GPano:FullPanoWidthPixels"; - - if (!meta.doesPropertyExist(namespace, cropWidthName)) { - return false; - } - if (!meta.doesPropertyExist(namespace, fullWidthName)) { - return false; - } - - Integer cropValue = meta.getPropertyInteger(namespace, cropWidthName); - Integer fullValue = meta.getPropertyInteger(namespace, fullWidthName); - - // Definition of a 360: - // GFullPanoWidthPixels == CroppedAreaImageWidthPixels - if (cropValue != null && fullValue != null) { - return cropValue.equals(fullValue); - } - - return false; - } catch (FileNotFoundException e) { - return false; - } catch (XMPException e) { - return false; - } finally { - Utils.closeSilently(is); - } - } -} |