diff options
Diffstat (limited to 'src/com/android/gallery3d/filtershow/crop/CropLoader.java')
-rw-r--r-- | src/com/android/gallery3d/filtershow/crop/CropLoader.java | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/filtershow/crop/CropLoader.java b/src/com/android/gallery3d/filtershow/crop/CropLoader.java new file mode 100644 index 000000000..40254931f --- /dev/null +++ b/src/com/android/gallery3d/filtershow/crop/CropLoader.java @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2013 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.crop; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteException; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Rect; +import android.net.Uri; +import android.provider.MediaStore; +import android.util.Log; + +import com.android.gallery3d.common.Utils; +import com.android.gallery3d.exif.ExifInterface; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +/** + * This class contains reentrant static methods for loading a bitmap. + */ +public abstract class CropLoader { + public static final String LOGTAG = "CropLoader"; + public static final String JPEG_MIME_TYPE = "image/jpeg"; + 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; + + /** + * Returns the orientation of image at the given URI as one of 0, 90, 180, + * 270. + * + * @param uri URI of image to open. + * @param context context whose ContentResolver to use. + * @return the orientation of the image. Defaults to 0. + */ + public static int getMetadataOrientation(Uri uri, Context context) { + if (uri == null || context == null) { + throw new IllegalArgumentException("bad argument to getScaledBitmap"); + } + if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { + String mimeType = context.getContentResolver().getType(uri); + if (mimeType != JPEG_MIME_TYPE) { + return 0; + } + String path = uri.getPath(); + int orientation = 0; + ExifInterface exif = new ExifInterface(); + try { + exif.readExif(path); + orientation = ExifInterface.getRotationForOrientationValue( + exif.getTagIntValue(ExifInterface.TAG_ORIENTATION).shortValue()); + } catch (IOException e) { + Log.w(LOGTAG, "Failed to read EXIF orientation", e); + } + return orientation; + } + Cursor cursor = null; + try { + cursor = context.getContentResolver().query(uri, + new String[] { + MediaStore.Images.ImageColumns.ORIENTATION + }, + null, null, null); + if (cursor.moveToNext()) { + int ori = cursor.getInt(0); + + switch (ori) { + case 0: + return ORI_NORMAL; + case 90: + return ORI_ROTATE_90; + case 270: + return ORI_ROTATE_270; + case 180: + return ORI_ROTATE_180; + default: + return 0; + } + } + } catch (SQLiteException e) { + return 0; + } catch (IllegalArgumentException e) { + return 0; + } finally { + Utils.closeSilently(cursor); + } + return 0; + } + + /** + * Gets 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 set to the actual bounds of the stored bitmap. + * @return downsampled bitmap or null if this operation failed. + */ + public static Bitmap getConstrainedBitmap(Uri uri, Context context, int maxSideLength, + Rect originalBounds) { + if (maxSideLength <= 0 || originalBounds == null || uri == null || context == null) { + throw new IllegalArgumentException("bad argument to getScaledBitmap"); + } + InputStream is = null; + try { + // Get width and height of stored bitmap + is = context.getContentResolver().openInputStream(uri); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeStream(is, null, options); + int w = options.outWidth; + int h = options.outHeight; + originalBounds.set(0, 0, w, h); + + // If bitmap cannot be decoded, return null + if (w <= 0 || h <= 0) { + return null; + } + + options = new BitmapFactory.Options(); + + // Find best downsampling size + int imageSide = Math.max(w, h); + if (imageSide > maxSideLength) { + int shifts = 1 + Integer.numberOfLeadingZeros(maxSideLength) + - Integer.numberOfLeadingZeros(imageSide); + options.inSampleSize = 1 << shifts; + } + + // Make sure sample size is reasonable + if (0 >= (int) (Math.min(w, h) / options.inSampleSize)) { + return null; + } + + // Decode actual bitmap. + options.inMutable = true; + is.close(); + is = context.getContentResolver().openInputStream(uri); + return BitmapFactory.decodeStream(is, null, options); + } catch (FileNotFoundException e) { + Log.e(LOGTAG, "FileNotFoundException: " + uri, e); + } catch (IOException e) { + Log.e(LOGTAG, "IOException: " + uri, e); + } finally { + Utils.closeSilently(is); + } + return null; + } + + /** + * Gets a bitmap that has been downsampled using sampleSize. + * + * @param uri URI of image to open. + * @param context context whose ContentResolver to use. + * @param sampleSize downsampling amount. + * @return downsampled bitmap. + */ + public static Bitmap getBitmap(Uri uri, Context context, int sampleSize) { + if (uri == null || context == null) { + throw new IllegalArgumentException("bad argument to getScaledBitmap"); + } + InputStream is = null; + try { + is = context.getContentResolver().openInputStream(uri); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inMutable = true; + options.inSampleSize = sampleSize; + return BitmapFactory.decodeStream(is, null, options); + } catch (FileNotFoundException e) { + Log.e(LOGTAG, "FileNotFoundException: " + uri, e); + } finally { + Utils.closeSilently(is); + } + return null; + } + +} |