1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.camera.gallery;
18 
19 import com.android.camera.BitmapManager;
20 import com.android.camera.Util;
21 
22 import android.content.ContentResolver;
23 import android.content.ContentValues;
24 import android.graphics.Bitmap;
25 import android.graphics.BitmapFactory;
26 import android.media.ExifInterface;
27 import android.net.Uri;
28 import android.provider.BaseColumns;
29 import android.provider.MediaStore.Images;
30 import android.provider.MediaStore.Images.ImageColumns;
31 import android.util.Log;
32 
33 import java.io.IOException;
34 
35 /**
36  * The class for normal images in gallery.
37  */
38 public class Image extends BaseImage implements IImage {
39     private static final String TAG = "BaseImage";
40 
41     private ExifInterface mExif;
42 
43     private int mRotation;
44 
Image(BaseImageList container, ContentResolver cr, long id, int index, Uri uri, String dataPath, String mimeType, long dateTaken, String title, int rotation)45     public Image(BaseImageList container, ContentResolver cr,
46             long id, int index, Uri uri, String dataPath,
47             String mimeType, long dateTaken, String title,
48             int rotation) {
49         super(container, cr, id, index, uri, dataPath,
50                 mimeType, dateTaken, title);
51         mRotation = rotation;
52     }
53 
54     @Override
getDegreesRotated()55     public int getDegreesRotated() {
56         return mRotation;
57     }
58 
setDegreesRotated(int degrees)59     protected void setDegreesRotated(int degrees) {
60         if (mRotation == degrees) return;
61         mRotation = degrees;
62         ContentValues values = new ContentValues();
63         values.put(ImageColumns.ORIENTATION, mRotation);
64         mContentResolver.update(mUri, values, null, null);
65 
66         //TODO: Consider invalidate the cursor in container
67         // ((BaseImageList) getContainer()).invalidateCursor();
68     }
69 
isReadonly()70     public boolean isReadonly() {
71         String mimeType = getMimeType();
72         return !"image/jpeg".equals(mimeType) && !"image/png".equals(mimeType);
73     }
74 
isDrm()75     public boolean isDrm() {
76         return false;
77     }
78 
79     /**
80      * Replaces the tag if already there. Otherwise, adds to the exif tags.
81      * @param tag
82      * @param value
83      */
replaceExifTag(String tag, String value)84     public void replaceExifTag(String tag, String value) {
85         if (mExif == null) {
86             loadExifData();
87         }
88         mExif.setAttribute(tag, value);
89     }
90 
loadExifData()91     private void loadExifData() {
92         try {
93             mExif = new ExifInterface(mDataPath);
94         } catch (IOException ex) {
95             Log.e(TAG, "cannot read exif", ex);
96         }
97     }
98 
saveExifData()99     private void saveExifData() throws IOException {
100         if (mExif != null) {
101             mExif.saveAttributes();
102         }
103     }
104 
setExifRotation(int degrees)105     private void setExifRotation(int degrees) {
106         try {
107             degrees %= 360;
108             if (degrees < 0) degrees += 360;
109 
110             int orientation = ExifInterface.ORIENTATION_NORMAL;
111             switch (degrees) {
112                 case 0:
113                     orientation = ExifInterface.ORIENTATION_NORMAL;
114                     break;
115                 case 90:
116                     orientation = ExifInterface.ORIENTATION_ROTATE_90;
117                     break;
118                 case 180:
119                     orientation = ExifInterface.ORIENTATION_ROTATE_180;
120                     break;
121                 case 270:
122                     orientation = ExifInterface.ORIENTATION_ROTATE_270;
123                     break;
124             }
125 
126             replaceExifTag(ExifInterface.TAG_ORIENTATION,
127                     Integer.toString(orientation));
128             saveExifData();
129         } catch (Exception ex) {
130             Log.e(TAG, "unable to save exif data with new orientation "
131                     + fullSizeImageUri(), ex);
132         }
133     }
134 
135     /**
136      * Save the rotated image by updating the Exif "Orientation" tag.
137      * @param degrees
138      */
rotateImageBy(int degrees)139     public boolean rotateImageBy(int degrees) {
140         int newDegrees = (getDegreesRotated() + degrees) % 360;
141         setExifRotation(newDegrees);
142         setDegreesRotated(newDegrees);
143 
144         return true;
145     }
146 
147     private static final String[] THUMB_PROJECTION = new String[] {
148         BaseColumns._ID,
149     };
150 
thumbBitmap(boolean rotateAsNeeded)151     public Bitmap thumbBitmap(boolean rotateAsNeeded) {
152         Bitmap bitmap = null;
153         BitmapFactory.Options options = new BitmapFactory.Options();
154         options.inDither = false;
155         options.inPreferredConfig = Bitmap.Config.ARGB_8888;
156         bitmap = BitmapManager.instance().getThumbnail(mContentResolver, mId,
157                 Images.Thumbnails.MINI_KIND, options, false);
158 
159         if (bitmap != null && rotateAsNeeded) {
160             bitmap = Util.rotate(bitmap, getDegreesRotated());
161         }
162 
163         return bitmap;
164     }
165 }
166