Util.java revision 937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37
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
17package com.android.camera;
18
19import android.graphics.Bitmap;
20import android.graphics.BitmapFactory;
21import android.graphics.Matrix;
22import android.media.MediaMetadataRetriever;
23import android.os.ParcelFileDescriptor;
24import android.util.Log;
25
26
27import java.io.ByteArrayOutputStream;
28import java.io.Closeable;
29
30/**
31 * Collection of utility functions used in this package.
32 */
33public class Util {
34    private static final boolean VERBOSE = false;
35    private static final String TAG = "db.Util";
36
37    private Util() {
38    }
39
40    // Rotates the bitmap by the specified degree.
41    // If a new bitmap is created, the original bitmap is recycled.
42    public static Bitmap rotate(Bitmap b, int degrees) {
43        if (degrees != 0 && b != null) {
44            Matrix m = new Matrix();
45            m.setRotate(degrees,
46                    (float) b.getWidth() / 2, (float) b.getHeight() / 2);
47            try {
48                Bitmap b2 = Bitmap.createBitmap(
49                        b, 0, 0, b.getWidth(), b.getHeight(), m, true);
50                if (b != b2) {
51                    b.recycle();
52                    b = b2;
53                }
54            } catch (OutOfMemoryError ex) {
55                // We have no memory to rotate. Return the original bitmap.
56            }
57        }
58        return b;
59    }
60
61    /*
62     * Compute the sample size as a function of the image size and the target.
63     * Scale the image down so that both the width and height are just above the
64     * target. If this means that one of the dimension goes from above the
65     * target to below the target (e.g. given a width of 480 and an image width
66     * of 600 but sample size of 2 -- i.e. new width 300 -- bump the sample size
67     * down by 1.
68     */
69    public static int computeSampleSize(
70            BitmapFactory.Options options, int target) {
71        int w = options.outWidth;
72        int h = options.outHeight;
73
74        int candidateW = w / target;
75        int candidateH = h / target;
76        int candidate = Math.max(candidateW, candidateH);
77
78        if (candidate == 0) return 1;
79
80        if (candidate > 1) {
81            if ((w > target) && (w / candidate) < target) candidate -= 1;
82        }
83
84        if (candidate > 1) {
85            if ((h > target) && (h / candidate) < target) candidate -= 1;
86        }
87
88        if (VERBOSE) {
89            Log.v(TAG, "for w/h " + w + "/" + h + " returning " + candidate
90                    + "(" + (w / candidate) + " / " + (h / candidate));
91        }
92
93        return candidate;
94    }
95
96    /**
97     * Creates a centered bitmap of the desired size. Recycles the input.
98     * @param source
99     */
100    public static Bitmap extractMiniThumb(
101            Bitmap source, int width, int height) {
102        return Util.extractMiniThumb(source, width, height, true);
103    }
104
105    public static Bitmap extractMiniThumb(
106            Bitmap source, int width, int height, boolean recycle) {
107        if (source == null) {
108            return null;
109        }
110
111        float scale;
112        if (source.getWidth() < source.getHeight()) {
113            scale = width / (float) source.getWidth();
114        } else {
115            scale = height / (float) source.getHeight();
116        }
117        Matrix matrix = new Matrix();
118        matrix.setScale(scale, scale);
119        Bitmap miniThumbnail = ImageLoader.transform(matrix, source,
120                width, height, false);
121
122        if (recycle && miniThumbnail != source) {
123            source.recycle();
124        }
125        return miniThumbnail;
126    }
127
128    /**
129     * Creates a byte[] for a given bitmap of the desired size. Recycles the
130     * input bitmap.
131     */
132    public static byte[] miniThumbData(Bitmap source) {
133        if (source == null) return null;
134
135        Bitmap miniThumbnail = extractMiniThumb(
136                source, ImageManager.MINI_THUMB_TARGET_SIZE,
137                ImageManager.MINI_THUMB_TARGET_SIZE);
138
139        ByteArrayOutputStream miniOutStream = new ByteArrayOutputStream();
140        miniThumbnail.compress(Bitmap.CompressFormat.JPEG, 75, miniOutStream);
141        miniThumbnail.recycle();
142
143        try {
144            miniOutStream.close();
145            byte [] data = miniOutStream.toByteArray();
146            return data;
147        } catch (java.io.IOException ex) {
148            Log.e(TAG, "got exception ex " + ex);
149        }
150        return null;
151    }
152
153    /**
154     * @return true if the mimetype is a video mimetype.
155     */
156    public static boolean isVideoMimeType(String mimeType) {
157        return mimeType.startsWith("video/");
158    }
159
160    /**
161     * Create a video thumbnail for a video. May return null if the video is
162     * corrupt.
163     *
164     * @param filePath
165     */
166    public static Bitmap createVideoThumbnail(String filePath) {
167        Bitmap bitmap = null;
168        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
169        try {
170            retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
171            retriever.setDataSource(filePath);
172            bitmap = retriever.captureFrame();
173        } catch (IllegalArgumentException ex) {
174            // Assume this is a corrupt video file
175        } catch (RuntimeException ex) {
176            // Assume this is a corrupt video file.
177        } finally {
178            try {
179                retriever.release();
180            } catch (RuntimeException ex) {
181                // Ignore failures while cleaning up.
182            }
183        }
184        return bitmap;
185    }
186
187    public static int indexOf(String [] array, String s) {
188        for (int i = 0; i < array.length; i++) {
189            if (array[i].equals(s)) {
190                return i;
191            }
192        }
193        return -1;
194    }
195
196    public static void closeSiliently(Closeable c) {
197        if (c == null) return;
198        try {
199            c.close();
200        } catch (Throwable t) {
201            // do nothing
202        }
203    }
204
205    public static void closeSiliently(ParcelFileDescriptor c) {
206        if (c == null) return;
207        try {
208            c.close();
209        } catch (Throwable t) {
210            // do nothing
211        }
212    }
213
214}
215