1666ea1b28a76aeba74744148b15099254d918671Owen Lin/* 2666ea1b28a76aeba74744148b15099254d918671Owen Lin * Copyright (C) 2009 The Android Open Source Project 3666ea1b28a76aeba74744148b15099254d918671Owen Lin * 4666ea1b28a76aeba74744148b15099254d918671Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5666ea1b28a76aeba74744148b15099254d918671Owen Lin * you may not use this file except in compliance with the License. 6666ea1b28a76aeba74744148b15099254d918671Owen Lin * You may obtain a copy of the License at 7666ea1b28a76aeba74744148b15099254d918671Owen Lin * 8666ea1b28a76aeba74744148b15099254d918671Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9666ea1b28a76aeba74744148b15099254d918671Owen Lin * 10666ea1b28a76aeba74744148b15099254d918671Owen Lin * Unless required by applicable law or agreed to in writing, software 11666ea1b28a76aeba74744148b15099254d918671Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12666ea1b28a76aeba74744148b15099254d918671Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13666ea1b28a76aeba74744148b15099254d918671Owen Lin * See the License for the specific language governing permissions and 14666ea1b28a76aeba74744148b15099254d918671Owen Lin * limitations under the License. 15666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 16666ea1b28a76aeba74744148b15099254d918671Owen Lin 17666ea1b28a76aeba74744148b15099254d918671Owen Linpackage com.android.camera.gallery; 18666ea1b28a76aeba74744148b15099254d918671Owen Lin 198aa3fbcf9a5a0d11acd48861f5167073e3554980Owen Linimport com.android.camera.BitmapManager; 20666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.Util; 21666ea1b28a76aeba74744148b15099254d918671Owen Lin 22666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.content.ContentResolver; 23666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.content.ContentValues; 24666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.graphics.Bitmap; 25666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.graphics.BitmapFactory; 26666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.media.ExifInterface; 27666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.net.Uri; 28666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.provider.BaseColumns; 29666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.provider.MediaStore.Images; 30666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.provider.MediaStore.Images.ImageColumns; 31666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.util.Log; 32666ea1b28a76aeba74744148b15099254d918671Owen Lin 33666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.io.IOException; 34666ea1b28a76aeba74744148b15099254d918671Owen Lin 35666ea1b28a76aeba74744148b15099254d918671Owen Lin/** 36666ea1b28a76aeba74744148b15099254d918671Owen Lin * The class for normal images in gallery. 37666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 38666ea1b28a76aeba74744148b15099254d918671Owen Linpublic class Image extends BaseImage implements IImage { 39666ea1b28a76aeba74744148b15099254d918671Owen Lin private static final String TAG = "BaseImage"; 40666ea1b28a76aeba74744148b15099254d918671Owen Lin 41666ea1b28a76aeba74744148b15099254d918671Owen Lin private ExifInterface mExif; 42666ea1b28a76aeba74744148b15099254d918671Owen Lin 43666ea1b28a76aeba74744148b15099254d918671Owen Lin private int mRotation; 44666ea1b28a76aeba74744148b15099254d918671Owen Lin 45666ea1b28a76aeba74744148b15099254d918671Owen Lin public Image(BaseImageList container, ContentResolver cr, 46b62254a185d04ecfe2ddc837b7e0e54f0273c478Owen Lin long id, int index, Uri uri, String dataPath, 47185a1a7c5f33ecc5cb9a36d23cecb719c8727178Chih-Chung Chang String mimeType, long dateTaken, String title, 48666ea1b28a76aeba74744148b15099254d918671Owen Lin int rotation) { 49b62254a185d04ecfe2ddc837b7e0e54f0273c478Owen Lin super(container, cr, id, index, uri, dataPath, 50185a1a7c5f33ecc5cb9a36d23cecb719c8727178Chih-Chung Chang mimeType, dateTaken, title); 51666ea1b28a76aeba74744148b15099254d918671Owen Lin mRotation = rotation; 52666ea1b28a76aeba74744148b15099254d918671Owen Lin } 53666ea1b28a76aeba74744148b15099254d918671Owen Lin 54666ea1b28a76aeba74744148b15099254d918671Owen Lin @Override 55666ea1b28a76aeba74744148b15099254d918671Owen Lin public int getDegreesRotated() { 56666ea1b28a76aeba74744148b15099254d918671Owen Lin return mRotation; 57666ea1b28a76aeba74744148b15099254d918671Owen Lin } 58666ea1b28a76aeba74744148b15099254d918671Owen Lin 59666ea1b28a76aeba74744148b15099254d918671Owen Lin protected void setDegreesRotated(int degrees) { 60666ea1b28a76aeba74744148b15099254d918671Owen Lin if (mRotation == degrees) return; 61666ea1b28a76aeba74744148b15099254d918671Owen Lin mRotation = degrees; 62666ea1b28a76aeba74744148b15099254d918671Owen Lin ContentValues values = new ContentValues(); 63666ea1b28a76aeba74744148b15099254d918671Owen Lin values.put(ImageColumns.ORIENTATION, mRotation); 64666ea1b28a76aeba74744148b15099254d918671Owen Lin mContentResolver.update(mUri, values, null, null); 65666ea1b28a76aeba74744148b15099254d918671Owen Lin 66666ea1b28a76aeba74744148b15099254d918671Owen Lin //TODO: Consider invalidate the cursor in container 67666ea1b28a76aeba74744148b15099254d918671Owen Lin // ((BaseImageList) getContainer()).invalidateCursor(); 68666ea1b28a76aeba74744148b15099254d918671Owen Lin } 69666ea1b28a76aeba74744148b15099254d918671Owen Lin 70666ea1b28a76aeba74744148b15099254d918671Owen Lin public boolean isReadonly() { 71666ea1b28a76aeba74744148b15099254d918671Owen Lin String mimeType = getMimeType(); 72666ea1b28a76aeba74744148b15099254d918671Owen Lin return !"image/jpeg".equals(mimeType) && !"image/png".equals(mimeType); 73666ea1b28a76aeba74744148b15099254d918671Owen Lin } 74666ea1b28a76aeba74744148b15099254d918671Owen Lin 75666ea1b28a76aeba74744148b15099254d918671Owen Lin public boolean isDrm() { 76666ea1b28a76aeba74744148b15099254d918671Owen Lin return false; 77666ea1b28a76aeba74744148b15099254d918671Owen Lin } 78666ea1b28a76aeba74744148b15099254d918671Owen Lin 79666ea1b28a76aeba74744148b15099254d918671Owen Lin /** 80666ea1b28a76aeba74744148b15099254d918671Owen Lin * Replaces the tag if already there. Otherwise, adds to the exif tags. 81666ea1b28a76aeba74744148b15099254d918671Owen Lin * @param tag 82666ea1b28a76aeba74744148b15099254d918671Owen Lin * @param value 83666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 84666ea1b28a76aeba74744148b15099254d918671Owen Lin public void replaceExifTag(String tag, String value) { 85666ea1b28a76aeba74744148b15099254d918671Owen Lin if (mExif == null) { 86666ea1b28a76aeba74744148b15099254d918671Owen Lin loadExifData(); 87666ea1b28a76aeba74744148b15099254d918671Owen Lin } 88666ea1b28a76aeba74744148b15099254d918671Owen Lin mExif.setAttribute(tag, value); 89666ea1b28a76aeba74744148b15099254d918671Owen Lin } 90666ea1b28a76aeba74744148b15099254d918671Owen Lin 91666ea1b28a76aeba74744148b15099254d918671Owen Lin private void loadExifData() { 92666ea1b28a76aeba74744148b15099254d918671Owen Lin try { 93666ea1b28a76aeba74744148b15099254d918671Owen Lin mExif = new ExifInterface(mDataPath); 94666ea1b28a76aeba74744148b15099254d918671Owen Lin } catch (IOException ex) { 95666ea1b28a76aeba74744148b15099254d918671Owen Lin Log.e(TAG, "cannot read exif", ex); 96666ea1b28a76aeba74744148b15099254d918671Owen Lin } 97666ea1b28a76aeba74744148b15099254d918671Owen Lin } 98666ea1b28a76aeba74744148b15099254d918671Owen Lin 99666ea1b28a76aeba74744148b15099254d918671Owen Lin private void saveExifData() throws IOException { 100666ea1b28a76aeba74744148b15099254d918671Owen Lin if (mExif != null) { 101666ea1b28a76aeba74744148b15099254d918671Owen Lin mExif.saveAttributes(); 102666ea1b28a76aeba74744148b15099254d918671Owen Lin } 103666ea1b28a76aeba74744148b15099254d918671Owen Lin } 104666ea1b28a76aeba74744148b15099254d918671Owen Lin 105666ea1b28a76aeba74744148b15099254d918671Owen Lin private void setExifRotation(int degrees) { 106666ea1b28a76aeba74744148b15099254d918671Owen Lin try { 107666ea1b28a76aeba74744148b15099254d918671Owen Lin degrees %= 360; 108666ea1b28a76aeba74744148b15099254d918671Owen Lin if (degrees < 0) degrees += 360; 109666ea1b28a76aeba74744148b15099254d918671Owen Lin 110666ea1b28a76aeba74744148b15099254d918671Owen Lin int orientation = ExifInterface.ORIENTATION_NORMAL; 111666ea1b28a76aeba74744148b15099254d918671Owen Lin switch (degrees) { 112666ea1b28a76aeba74744148b15099254d918671Owen Lin case 0: 113666ea1b28a76aeba74744148b15099254d918671Owen Lin orientation = ExifInterface.ORIENTATION_NORMAL; 114666ea1b28a76aeba74744148b15099254d918671Owen Lin break; 115666ea1b28a76aeba74744148b15099254d918671Owen Lin case 90: 116666ea1b28a76aeba74744148b15099254d918671Owen Lin orientation = ExifInterface.ORIENTATION_ROTATE_90; 117666ea1b28a76aeba74744148b15099254d918671Owen Lin break; 118666ea1b28a76aeba74744148b15099254d918671Owen Lin case 180: 119666ea1b28a76aeba74744148b15099254d918671Owen Lin orientation = ExifInterface.ORIENTATION_ROTATE_180; 120666ea1b28a76aeba74744148b15099254d918671Owen Lin break; 121666ea1b28a76aeba74744148b15099254d918671Owen Lin case 270: 122666ea1b28a76aeba74744148b15099254d918671Owen Lin orientation = ExifInterface.ORIENTATION_ROTATE_270; 123666ea1b28a76aeba74744148b15099254d918671Owen Lin break; 124666ea1b28a76aeba74744148b15099254d918671Owen Lin } 125666ea1b28a76aeba74744148b15099254d918671Owen Lin 126666ea1b28a76aeba74744148b15099254d918671Owen Lin replaceExifTag(ExifInterface.TAG_ORIENTATION, 127666ea1b28a76aeba74744148b15099254d918671Owen Lin Integer.toString(orientation)); 128666ea1b28a76aeba74744148b15099254d918671Owen Lin saveExifData(); 129666ea1b28a76aeba74744148b15099254d918671Owen Lin } catch (Exception ex) { 130666ea1b28a76aeba74744148b15099254d918671Owen Lin Log.e(TAG, "unable to save exif data with new orientation " 131666ea1b28a76aeba74744148b15099254d918671Owen Lin + fullSizeImageUri(), ex); 132666ea1b28a76aeba74744148b15099254d918671Owen Lin } 133666ea1b28a76aeba74744148b15099254d918671Owen Lin } 134666ea1b28a76aeba74744148b15099254d918671Owen Lin 135666ea1b28a76aeba74744148b15099254d918671Owen Lin /** 136666ea1b28a76aeba74744148b15099254d918671Owen Lin * Save the rotated image by updating the Exif "Orientation" tag. 137666ea1b28a76aeba74744148b15099254d918671Owen Lin * @param degrees 138666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 139666ea1b28a76aeba74744148b15099254d918671Owen Lin public boolean rotateImageBy(int degrees) { 140666ea1b28a76aeba74744148b15099254d918671Owen Lin int newDegrees = (getDegreesRotated() + degrees) % 360; 141666ea1b28a76aeba74744148b15099254d918671Owen Lin setExifRotation(newDegrees); 142666ea1b28a76aeba74744148b15099254d918671Owen Lin setDegreesRotated(newDegrees); 143666ea1b28a76aeba74744148b15099254d918671Owen Lin 144666ea1b28a76aeba74744148b15099254d918671Owen Lin return true; 145666ea1b28a76aeba74744148b15099254d918671Owen Lin } 146666ea1b28a76aeba74744148b15099254d918671Owen Lin 147666ea1b28a76aeba74744148b15099254d918671Owen Lin private static final String[] THUMB_PROJECTION = new String[] { 148666ea1b28a76aeba74744148b15099254d918671Owen Lin BaseColumns._ID, 149666ea1b28a76aeba74744148b15099254d918671Owen Lin }; 150666ea1b28a76aeba74744148b15099254d918671Owen Lin 151666ea1b28a76aeba74744148b15099254d918671Owen Lin public Bitmap thumbBitmap(boolean rotateAsNeeded) { 152666ea1b28a76aeba74744148b15099254d918671Owen Lin Bitmap bitmap = null; 153666ea1b28a76aeba74744148b15099254d918671Owen Lin BitmapFactory.Options options = new BitmapFactory.Options(); 154666ea1b28a76aeba74744148b15099254d918671Owen Lin options.inDither = false; 155666ea1b28a76aeba74744148b15099254d918671Owen Lin options.inPreferredConfig = Bitmap.Config.ARGB_8888; 1568aa3fbcf9a5a0d11acd48861f5167073e3554980Owen Lin bitmap = BitmapManager.instance().getThumbnail(mContentResolver, mId, 1578aa3fbcf9a5a0d11acd48861f5167073e3554980Owen Lin Images.Thumbnails.MINI_KIND, options, false); 158666ea1b28a76aeba74744148b15099254d918671Owen Lin 159666ea1b28a76aeba74744148b15099254d918671Owen Lin if (bitmap != null && rotateAsNeeded) { 160666ea1b28a76aeba74744148b15099254d918671Owen Lin bitmap = Util.rotate(bitmap, getDegreesRotated()); 161666ea1b28a76aeba74744148b15099254d918671Owen Lin } 162666ea1b28a76aeba74744148b15099254d918671Owen Lin 163666ea1b28a76aeba74744148b15099254d918671Owen Lin return bitmap; 164666ea1b28a76aeba74744148b15099254d918671Owen Lin } 165666ea1b28a76aeba74744148b15099254d918671Owen Lin} 166