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
19666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.BitmapManager;
20666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.Util;
21666ea1b28a76aeba74744148b15099254d918671Owen Lin
22666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.content.ContentResolver;
23666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.graphics.Bitmap;
24666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.graphics.BitmapFactory;
25666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.net.Uri;
26666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.os.ParcelFileDescriptor;
27666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.provider.MediaStore.Images;
28666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.util.Log;
29666ea1b28a76aeba74744148b15099254d918671Owen Lin
30666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.io.FileNotFoundException;
31666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.io.IOException;
32666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.io.InputStream;
33666ea1b28a76aeba74744148b15099254d918671Owen Lin
34666ea1b28a76aeba74744148b15099254d918671Owen Lin/**
35666ea1b28a76aeba74744148b15099254d918671Owen Lin * Represents a particular image and provides access to the underlying bitmap
36666ea1b28a76aeba74744148b15099254d918671Owen Lin * and two thumbnail bitmaps as well as other information such as the id, and
37666ea1b28a76aeba74744148b15099254d918671Owen Lin * the path to the actual image data.
38666ea1b28a76aeba74744148b15099254d918671Owen Lin */
39666ea1b28a76aeba74744148b15099254d918671Owen Linpublic abstract class BaseImage implements IImage {
40666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final String TAG = "BaseImage";
41666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final int UNKNOWN_LENGTH = -1;
42666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected ContentResolver mContentResolver;
43666ea1b28a76aeba74744148b15099254d918671Owen Lin
44666ea1b28a76aeba74744148b15099254d918671Owen Lin    // Database field
45666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected Uri mUri;
46666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected long mId;
47666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected String mDataPath;
48666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected final int mIndex;
49666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected String mMimeType;
50666ea1b28a76aeba74744148b15099254d918671Owen Lin    private final long mDateTaken;
51666ea1b28a76aeba74744148b15099254d918671Owen Lin    private String mTitle;
52666ea1b28a76aeba74744148b15099254d918671Owen Lin
53666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected BaseImageList mContainer;
54666ea1b28a76aeba74744148b15099254d918671Owen Lin
55666ea1b28a76aeba74744148b15099254d918671Owen Lin    private int mWidth = UNKNOWN_LENGTH;
56666ea1b28a76aeba74744148b15099254d918671Owen Lin    private int mHeight = UNKNOWN_LENGTH;
57666ea1b28a76aeba74744148b15099254d918671Owen Lin
58666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected BaseImage(BaseImageList container, ContentResolver cr,
59b62254a185d04ecfe2ddc837b7e0e54f0273c478Owen Lin            long id, int index, Uri uri, String dataPath, String mimeType,
60185a1a7c5f33ecc5cb9a36d23cecb719c8727178Chih-Chung Chang            long dateTaken, String title) {
61666ea1b28a76aeba74744148b15099254d918671Owen Lin        mContainer = container;
62666ea1b28a76aeba74744148b15099254d918671Owen Lin        mContentResolver = cr;
63666ea1b28a76aeba74744148b15099254d918671Owen Lin        mId = id;
64666ea1b28a76aeba74744148b15099254d918671Owen Lin        mIndex = index;
65666ea1b28a76aeba74744148b15099254d918671Owen Lin        mUri = uri;
66666ea1b28a76aeba74744148b15099254d918671Owen Lin        mDataPath = dataPath;
67666ea1b28a76aeba74744148b15099254d918671Owen Lin        mMimeType = mimeType;
68666ea1b28a76aeba74744148b15099254d918671Owen Lin        mDateTaken = dateTaken;
69666ea1b28a76aeba74744148b15099254d918671Owen Lin        mTitle = title;
70666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
71666ea1b28a76aeba74744148b15099254d918671Owen Lin
72666ea1b28a76aeba74744148b15099254d918671Owen Lin    public String getDataPath() {
73666ea1b28a76aeba74744148b15099254d918671Owen Lin        return mDataPath;
74666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
75666ea1b28a76aeba74744148b15099254d918671Owen Lin
76666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
77666ea1b28a76aeba74744148b15099254d918671Owen Lin    public boolean equals(Object other) {
78666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (other == null || !(other instanceof Image)) return false;
79666ea1b28a76aeba74744148b15099254d918671Owen Lin        return mUri.equals(((Image) other).mUri);
80666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
81666ea1b28a76aeba74744148b15099254d918671Owen Lin
82666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
83666ea1b28a76aeba74744148b15099254d918671Owen Lin    public int hashCode() {
84666ea1b28a76aeba74744148b15099254d918671Owen Lin        return mUri.hashCode();
85666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
86666ea1b28a76aeba74744148b15099254d918671Owen Lin
87666ea1b28a76aeba74744148b15099254d918671Owen Lin    public Bitmap fullSizeBitmap(int minSideLength, int maxNumberOfPixels) {
88666ea1b28a76aeba74744148b15099254d918671Owen Lin        return fullSizeBitmap(minSideLength, maxNumberOfPixels,
89666ea1b28a76aeba74744148b15099254d918671Owen Lin                IImage.ROTATE_AS_NEEDED, IImage.NO_NATIVE);
90666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
91666ea1b28a76aeba74744148b15099254d918671Owen Lin
92666ea1b28a76aeba74744148b15099254d918671Owen Lin    public Bitmap fullSizeBitmap(int minSideLength, int maxNumberOfPixels,
93666ea1b28a76aeba74744148b15099254d918671Owen Lin            boolean rotateAsNeeded, boolean useNative) {
94666ea1b28a76aeba74744148b15099254d918671Owen Lin        Uri url = mContainer.contentUri(mId);
95666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (url == null) return null;
96666ea1b28a76aeba74744148b15099254d918671Owen Lin
97666ea1b28a76aeba74744148b15099254d918671Owen Lin        Bitmap b = Util.makeBitmap(minSideLength, maxNumberOfPixels,
98666ea1b28a76aeba74744148b15099254d918671Owen Lin                url, mContentResolver, useNative);
99666ea1b28a76aeba74744148b15099254d918671Owen Lin
100666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (b != null && rotateAsNeeded) {
101666ea1b28a76aeba74744148b15099254d918671Owen Lin            b = Util.rotate(b, getDegreesRotated());
102666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
103666ea1b28a76aeba74744148b15099254d918671Owen Lin
104666ea1b28a76aeba74744148b15099254d918671Owen Lin        return b;
105666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
106666ea1b28a76aeba74744148b15099254d918671Owen Lin
107666ea1b28a76aeba74744148b15099254d918671Owen Lin    public InputStream fullSizeImageData() {
108666ea1b28a76aeba74744148b15099254d918671Owen Lin        try {
109666ea1b28a76aeba74744148b15099254d918671Owen Lin            InputStream input = mContentResolver.openInputStream(mUri);
110666ea1b28a76aeba74744148b15099254d918671Owen Lin            return input;
111666ea1b28a76aeba74744148b15099254d918671Owen Lin        } catch (IOException ex) {
112666ea1b28a76aeba74744148b15099254d918671Owen Lin            return null;
113666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
114666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
115666ea1b28a76aeba74744148b15099254d918671Owen Lin
116666ea1b28a76aeba74744148b15099254d918671Owen Lin    public Uri fullSizeImageUri() {
117666ea1b28a76aeba74744148b15099254d918671Owen Lin        return mUri;
118666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
119666ea1b28a76aeba74744148b15099254d918671Owen Lin
120666ea1b28a76aeba74744148b15099254d918671Owen Lin    public IImageList getContainer() {
121666ea1b28a76aeba74744148b15099254d918671Owen Lin        return mContainer;
122666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
123666ea1b28a76aeba74744148b15099254d918671Owen Lin
124666ea1b28a76aeba74744148b15099254d918671Owen Lin    public long getDateTaken() {
125666ea1b28a76aeba74744148b15099254d918671Owen Lin        return mDateTaken;
126666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
127666ea1b28a76aeba74744148b15099254d918671Owen Lin
128666ea1b28a76aeba74744148b15099254d918671Owen Lin    public int getDegreesRotated() {
129666ea1b28a76aeba74744148b15099254d918671Owen Lin        return 0;
130666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
131666ea1b28a76aeba74744148b15099254d918671Owen Lin
132666ea1b28a76aeba74744148b15099254d918671Owen Lin    public String getMimeType() {
133666ea1b28a76aeba74744148b15099254d918671Owen Lin        return mMimeType;
134666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
135666ea1b28a76aeba74744148b15099254d918671Owen Lin
136666ea1b28a76aeba74744148b15099254d918671Owen Lin    public String getTitle() {
137666ea1b28a76aeba74744148b15099254d918671Owen Lin        return mTitle;
138666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
139666ea1b28a76aeba74744148b15099254d918671Owen Lin
140666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void setupDimension() {
141666ea1b28a76aeba74744148b15099254d918671Owen Lin        ParcelFileDescriptor input = null;
142666ea1b28a76aeba74744148b15099254d918671Owen Lin        try {
143666ea1b28a76aeba74744148b15099254d918671Owen Lin            input = mContentResolver.openFileDescriptor(mUri, "r");
144666ea1b28a76aeba74744148b15099254d918671Owen Lin            BitmapFactory.Options options = new BitmapFactory.Options();
145666ea1b28a76aeba74744148b15099254d918671Owen Lin            options.inJustDecodeBounds = true;
146666ea1b28a76aeba74744148b15099254d918671Owen Lin            BitmapManager.instance().decodeFileDescriptor(
147666ea1b28a76aeba74744148b15099254d918671Owen Lin                    input.getFileDescriptor(), options);
148666ea1b28a76aeba74744148b15099254d918671Owen Lin            mWidth = options.outWidth;
149666ea1b28a76aeba74744148b15099254d918671Owen Lin            mHeight = options.outHeight;
150666ea1b28a76aeba74744148b15099254d918671Owen Lin        } catch (FileNotFoundException ex) {
151666ea1b28a76aeba74744148b15099254d918671Owen Lin            mWidth = 0;
152666ea1b28a76aeba74744148b15099254d918671Owen Lin            mHeight = 0;
153666ea1b28a76aeba74744148b15099254d918671Owen Lin        } finally {
154666ea1b28a76aeba74744148b15099254d918671Owen Lin            Util.closeSilently(input);
155666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
156666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
157666ea1b28a76aeba74744148b15099254d918671Owen Lin
158666ea1b28a76aeba74744148b15099254d918671Owen Lin    public int getWidth() {
159666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mWidth == UNKNOWN_LENGTH) setupDimension();
160666ea1b28a76aeba74744148b15099254d918671Owen Lin        return mWidth;
161666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
162666ea1b28a76aeba74744148b15099254d918671Owen Lin
163666ea1b28a76aeba74744148b15099254d918671Owen Lin    public int getHeight() {
164666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mHeight == UNKNOWN_LENGTH) setupDimension();
165666ea1b28a76aeba74744148b15099254d918671Owen Lin        return mHeight;
166666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
167666ea1b28a76aeba74744148b15099254d918671Owen Lin
168666ea1b28a76aeba74744148b15099254d918671Owen Lin    public Bitmap miniThumbBitmap() {
169666ea1b28a76aeba74744148b15099254d918671Owen Lin        Bitmap b = null;
170666ea1b28a76aeba74744148b15099254d918671Owen Lin        try {
171666ea1b28a76aeba74744148b15099254d918671Owen Lin            long id = mId;
1728aa3fbcf9a5a0d11acd48861f5167073e3554980Owen Lin            b = BitmapManager.instance().getThumbnail(mContentResolver, id,
1738aa3fbcf9a5a0d11acd48861f5167073e3554980Owen Lin                    Images.Thumbnails.MICRO_KIND, null, false);
174666ea1b28a76aeba74744148b15099254d918671Owen Lin        } catch (Throwable ex) {
175666ea1b28a76aeba74744148b15099254d918671Owen Lin            Log.e(TAG, "miniThumbBitmap got exception", ex);
176666ea1b28a76aeba74744148b15099254d918671Owen Lin            return null;
177666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
178666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (b != null) {
179666ea1b28a76aeba74744148b15099254d918671Owen Lin            b = Util.rotate(b, getDegreesRotated());
180666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
181666ea1b28a76aeba74744148b15099254d918671Owen Lin        return b;
182666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
183666ea1b28a76aeba74744148b15099254d918671Owen Lin
184666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected void onRemove() {
185666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
186666ea1b28a76aeba74744148b15099254d918671Owen Lin
187666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
188666ea1b28a76aeba74744148b15099254d918671Owen Lin    public String toString() {
189666ea1b28a76aeba74744148b15099254d918671Owen Lin        return mUri.toString();
190666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
191666ea1b28a76aeba74744148b15099254d918671Owen Lin}
192