DecodeUtils.java revision c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814d
1/*
2 * Copyright (C) 2010 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
17package com.android.gallery3d.data;
18
19import com.android.gallery3d.common.BitmapUtils;
20import com.android.gallery3d.common.Utils;
21import com.android.gallery3d.util.ThreadPool.CancelListener;
22import com.android.gallery3d.util.ThreadPool.JobContext;
23
24import android.content.ContentResolver;
25import android.graphics.Bitmap;
26import android.graphics.Bitmap.Config;
27import android.graphics.BitmapFactory;
28import android.graphics.BitmapFactory.Options;
29import android.graphics.BitmapRegionDecoder;
30import android.graphics.Rect;
31import android.net.Uri;
32import android.os.ParcelFileDescriptor;
33
34import java.io.FileDescriptor;
35import java.io.FileInputStream;
36
37public class DecodeUtils {
38    private static final String TAG = "DecodeService";
39
40    private static class DecodeCanceller implements CancelListener {
41        Options mOptions;
42        public DecodeCanceller(Options options) {
43            mOptions = options;
44        }
45        public void onCancel() {
46            mOptions.requestCancelDecode();
47        }
48    }
49
50    public static Bitmap requestDecode(JobContext jc, final String filePath,
51            Options options) {
52        if (options == null) options = new Options();
53        jc.setCancelListener(new DecodeCanceller(options));
54        return ensureGLCompatibleBitmap(
55                BitmapFactory.decodeFile(filePath, options));
56    }
57
58    public static Bitmap requestDecode(JobContext jc, FileDescriptor fd, Options options) {
59        if (options == null) options = new Options();
60        jc.setCancelListener(new DecodeCanceller(options));
61        return ensureGLCompatibleBitmap(
62                BitmapFactory.decodeFileDescriptor(fd, null, options));
63    }
64
65    public static Bitmap requestDecode(JobContext jc, byte[] bytes,
66            Options options) {
67        return requestDecode(jc, bytes, 0, bytes.length, options);
68    }
69
70    public static Bitmap requestDecode(JobContext jc, byte[] bytes, int offset,
71            int length, Options options) {
72        if (options == null) options = new Options();
73        jc.setCancelListener(new DecodeCanceller(options));
74        return ensureGLCompatibleBitmap(
75                BitmapFactory.decodeByteArray(bytes, offset, length, options));
76    }
77
78    public static Bitmap requestDecode(JobContext jc, final String filePath,
79            Options options, int targetSize) {
80        FileInputStream fis = null;
81        try {
82            fis = new FileInputStream(filePath);
83            FileDescriptor fd = fis.getFD();
84            return requestDecode(jc, fd, options, targetSize);
85        } catch (Exception ex) {
86            Log.w(TAG, ex);
87            return null;
88        } finally {
89            Utils.closeSilently(fis);
90        }
91    }
92
93    public static Bitmap requestDecode(JobContext jc, FileDescriptor fd,
94            Options options, int targetSize) {
95        if (options == null) options = new Options();
96        jc.setCancelListener(new DecodeCanceller(options));
97
98        options.inJustDecodeBounds = true;
99        BitmapFactory.decodeFileDescriptor(fd, null, options);
100        if (jc.isCancelled()) return null;
101
102        options.inSampleSize = BitmapUtils.computeSampleSizeLarger(
103                options.outWidth, options.outHeight, targetSize);
104        options.inJustDecodeBounds = false;
105        return ensureGLCompatibleBitmap(
106                BitmapFactory.decodeFileDescriptor(fd, null, options));
107    }
108
109    public static Bitmap requestDecode(JobContext jc,
110            FileDescriptor fileDescriptor, Rect paddings, Options options) {
111        if (options == null) options = new Options();
112        jc.setCancelListener(new DecodeCanceller(options));
113        return ensureGLCompatibleBitmap(BitmapFactory.decodeFileDescriptor
114                (fileDescriptor, paddings, options));
115    }
116
117    // TODO: This function should not be called directly from
118    // DecodeUtils.requestDecode(...), since we don't have the knowledge
119    // if the bitmap will be uploaded to GL.
120    public static Bitmap ensureGLCompatibleBitmap(Bitmap bitmap) {
121        if (bitmap == null || bitmap.getConfig() != null) return bitmap;
122        Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false);
123        bitmap.recycle();
124        return newBitmap;
125    }
126
127    public static BitmapRegionDecoder requestCreateBitmapRegionDecoder(
128            JobContext jc, byte[] bytes, int offset, int length,
129            boolean shareable) {
130        if (offset < 0 || length <= 0 || offset + length > bytes.length) {
131            throw new IllegalArgumentException(String.format(
132                    "offset = %s, length = %s, bytes = %s",
133                    offset, length, bytes.length));
134        }
135
136        try {
137            return BitmapRegionDecoder.newInstance(
138                    bytes, offset, length, shareable);
139        } catch (Throwable t)  {
140            Log.w(TAG, t);
141            return null;
142        }
143    }
144
145    public static BitmapRegionDecoder requestCreateBitmapRegionDecoder(
146            JobContext jc, String filePath, boolean shareable) {
147        try {
148            return BitmapRegionDecoder.newInstance(filePath, shareable);
149        } catch (Throwable t)  {
150            Log.w(TAG, t);
151            return null;
152        }
153    }
154
155    public static BitmapRegionDecoder requestCreateBitmapRegionDecoder(
156            JobContext jc, FileDescriptor fd, boolean shareable) {
157        try {
158            return BitmapRegionDecoder.newInstance(fd, shareable);
159        } catch (Throwable t)  {
160            Log.w(TAG, t);
161            return null;
162        }
163    }
164
165    public static BitmapRegionDecoder requestCreateBitmapRegionDecoder(
166            JobContext jc, Uri uri, ContentResolver resolver,
167            boolean shareable) {
168        ParcelFileDescriptor pfd = null;
169        try {
170            pfd = resolver.openFileDescriptor(uri, "r");
171            return BitmapRegionDecoder.newInstance(
172                    pfd.getFileDescriptor(), shareable);
173        } catch (Throwable t) {
174            Log.w(TAG, t);
175            return null;
176        } finally {
177            Utils.closeSilently(pfd);
178        }
179    }
180}
181