UriImage.java revision bd09a4b8c2d1f922f1459c4d7b61e7e87ed4ddf3
1/*
2 * Copyright (C) 2008 Esmertec AG.
3 * Copyright (C) 2008 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.mms.ui;
19
20import com.android.mms.MmsConfig;
21import com.android.mms.model.ImageModel;
22import com.google.android.mms.pdu.PduPart;
23import com.google.android.mms.util.SqliteWrapper;
24
25import android.content.Context;
26import android.database.Cursor;
27import android.graphics.Bitmap;
28import android.graphics.BitmapFactory;
29import android.graphics.Bitmap.CompressFormat;
30import android.net.Uri;
31import android.provider.MediaStore.Images;
32import android.provider.Telephony.Mms.Part;
33import android.text.TextUtils;
34import android.util.Config;
35import android.util.Log;
36import android.webkit.MimeTypeMap;
37
38import java.io.ByteArrayOutputStream;
39import java.io.FileNotFoundException;
40import java.io.IOException;
41import java.io.InputStream;
42
43public class UriImage {
44    private static final String TAG = "UriImage";
45    private static final boolean DEBUG = true;
46    private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
47
48    private final Context mContext;
49    private final Uri mUri;
50    private String mContentType;
51    private String mPath;
52    private String mSrc;
53    private int mWidth;
54    private int mHeight;
55
56    public UriImage(Context context, Uri uri) {
57        if ((null == context) || (null == uri)) {
58            throw new IllegalArgumentException();
59        }
60
61        String scheme = uri.getScheme();
62        if (scheme.equals("content")) {
63            initFromContentUri(context, uri);
64        } else if (uri.getScheme().equals("file")) {
65            initFromFile(context, uri);
66        }
67
68        mSrc = mPath.substring(mPath.lastIndexOf('/') + 1);
69        mContext = context;
70        mUri = uri;
71
72        decodeBoundsInfo();
73    }
74
75    private void initFromFile(Context context, Uri uri) {
76        MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
77        String extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString());
78        mContentType = mimeTypeMap.getMimeTypeFromExtension(extension);
79        if (mContentType == null) {
80            throw new IllegalArgumentException(
81                    "Unable to determine extension for " + uri.toString());
82        }
83        mPath = uri.getPath();
84    }
85
86    private void initFromContentUri(Context context, Uri uri) {
87        Cursor c = SqliteWrapper.query(context, context.getContentResolver(),
88                            uri, null, null, null, null);
89
90        if (c == null) {
91            throw new IllegalArgumentException(
92                    "Query on " + uri + " returns null result.");
93        }
94
95        try {
96            if ((c.getCount() != 1) || !c.moveToFirst()) {
97                throw new IllegalArgumentException(
98                        "Query on " + uri + " returns 0 or multiple rows.");
99            }
100
101            String filePath;
102            if (ImageModel.isMmsUri(uri)) {
103                filePath = c.getString(c.getColumnIndexOrThrow(Part.FILENAME));
104                if (TextUtils.isEmpty(filePath)) {
105                    filePath = c.getString(
106                            c.getColumnIndexOrThrow(Part._DATA));
107                }
108                mContentType = c.getString(
109                        c.getColumnIndexOrThrow(Part.CONTENT_TYPE));
110            } else {
111                filePath = c.getString(
112                        c.getColumnIndexOrThrow(Images.Media.DATA));
113                mContentType = c.getString(
114                        c.getColumnIndexOrThrow(Images.Media.MIME_TYPE));
115            }
116            mPath = filePath;
117        } finally {
118            c.close();
119        }
120    }
121
122    private void decodeBoundsInfo() {
123        InputStream input = null;
124        try {
125            input = mContext.getContentResolver().openInputStream(mUri);
126            BitmapFactory.Options opt = new BitmapFactory.Options();
127            opt.inJustDecodeBounds = true;
128            BitmapFactory.decodeStream(input, null, opt);
129            mWidth = opt.outWidth;
130            mHeight = opt.outHeight;
131        } catch (FileNotFoundException e) {
132            // Ignore
133            Log.e(TAG, "IOException caught while opening stream", e);
134        } finally {
135            if (null != input) {
136                try {
137                    input.close();
138                } catch (IOException e) {
139                    // Ignore
140                    Log.e(TAG, "IOException caught while closing stream", e);
141                }
142            }
143        }
144    }
145
146    public String getContentType() {
147        return mContentType;
148    }
149
150    public String getSrc() {
151        return mSrc;
152    }
153
154    public int getWidth() {
155        return mWidth;
156    }
157
158    public int getHeight() {
159        return mHeight;
160    }
161
162    public PduPart getResizedImageAsPart(int widthLimit, int heightLimit) {
163        PduPart part = new PduPart();
164
165        byte[] data = getResizedImageData(widthLimit, heightLimit);
166        if (data == null) {
167            if (LOCAL_LOGV) {
168                Log.v(TAG, "Resize image failed.");
169            }
170            return null;
171        }
172
173        part.setData(data);
174        part.setContentType(getContentType().getBytes());
175        String src = getSrc();
176        byte[] srcBytes = src.getBytes();
177        part.setContentLocation(srcBytes);
178        part.setFilename(srcBytes);
179        part.setContentId(src.substring(0, src.lastIndexOf(".")).getBytes());
180
181        return part;
182    }
183
184    private byte[] getResizedImageData(int widthLimit, int heightLimit) {
185        int outWidth = mWidth;
186        int outHeight = mHeight;
187
188        int s = 1;
189        while ((outWidth / s > widthLimit) || (outHeight / s > heightLimit)) {
190            s *= 2;
191        }
192        if (LOCAL_LOGV) {
193            Log.v(TAG, "outWidth=" + outWidth / s
194                    + " outHeight=" + outHeight / s);
195        }
196        BitmapFactory.Options options = new BitmapFactory.Options();
197        options.inSampleSize = s;
198
199        InputStream input = null;
200        try {
201            input = mContext.getContentResolver().openInputStream(mUri);
202            Bitmap b = BitmapFactory.decodeStream(input, null, options);
203            if (b == null) {
204                return null;
205            }
206
207            ByteArrayOutputStream os = new ByteArrayOutputStream();
208            b.compress(CompressFormat.JPEG, MessageUtils.IMAGE_COMPRESSION_QUALITY, os);
209            return os.toByteArray();
210        } catch (FileNotFoundException e) {
211            Log.e(TAG, e.getMessage(), e);
212            return null;
213        } finally {
214            if (input != null) {
215                try {
216                    input.close();
217                } catch (IOException e) {
218                    Log.e(TAG, e.getMessage(), e);
219                }
220            }
221        }
222    }
223}
224