16a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang/*
26a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang * Copyright (C) 2010 The Android Open Source Project
36a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang *
46a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang * Licensed under the Apache License, Version 2.0 (the "License");
56a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang * you may not use this file except in compliance with the License.
66a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang * You may obtain a copy of the License at
76a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang *
86a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang *      http://www.apache.org/licenses/LICENSE-2.0
96a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang *
106a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang * Unless required by applicable law or agreed to in writing, software
116a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang * distributed under the License is distributed on an "AS IS" BASIS,
126a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang * See the License for the specific language governing permissions and
146a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang * limitations under the License.
156a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang */
166a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
176a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangpackage com.android.gallery3d.photoeditor;
186a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
196a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.content.Context;
206a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.database.Cursor;
216a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.graphics.Bitmap;
226a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.graphics.Bitmap.CompressFormat;
236a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.graphics.BitmapFactory;
246a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.graphics.Canvas;
256a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.graphics.Matrix;
266a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.graphics.Paint;
276a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.graphics.Rect;
286a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.graphics.RectF;
296a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.net.Uri;
306a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.provider.MediaStore.Images.ImageColumns;
316a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport android.util.Log;
326a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
336a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport java.io.Closeable;
346a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport java.io.File;
356a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport java.io.FileNotFoundException;
366a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport java.io.FileOutputStream;
376a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport java.io.IOException;
386a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport java.io.InputStream;
396a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangimport java.io.OutputStream;
406a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
416a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang/**
426a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang * Utils for bitmap operations.
436a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang */
446a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huangpublic class BitmapUtils {
456a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
466a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    private static final String TAG = "BitmapUtils";
476a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    private static final int DEFAULT_COMPRESS_QUALITY = 90;
486a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    private static final int INDEX_ORIENTATION = 0;
496a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
506a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    private static final String[] IMAGE_PROJECTION = new String[] {
516a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        ImageColumns.ORIENTATION
526a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    };
536a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
546a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    private final Context context;
556a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
566a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    public BitmapUtils(Context context) {
576a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        this.context = context;
586a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    }
596a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
606a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    /**
616a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang     * Creates a mutable bitmap from subset of source bitmap, transformed by the optional matrix.
626a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang     */
63f66bd12b33e0d590e192a3551e9affc55eef9a48Yuli Huang    private static Bitmap createBitmap(
646a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            Bitmap source, int x, int y, int width, int height, Matrix m) {
656a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        // Re-implement Bitmap createBitmap() to always return a mutable bitmap.
666a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        Canvas canvas = new Canvas();
676a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
686a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        Bitmap bitmap;
696a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        Paint paint;
706a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        if ((m == null) || m.isIdentity()) {
716a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            bitmap = Bitmap.createBitmap(width, height, source.getConfig());
726a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            paint = null;
736a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        } else {
746a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            RectF rect = new RectF(0, 0, width, height);
756a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            m.mapRect(rect);
766a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            bitmap = Bitmap.createBitmap(
776a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                    Math.round(rect.width()), Math.round(rect.height()), source.getConfig());
786a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
796a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            canvas.translate(-rect.left, -rect.top);
806a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            canvas.concat(m);
816a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
826a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            paint = new Paint(Paint.FILTER_BITMAP_FLAG);
836a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            if (!m.rectStaysRect()) {
846a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                paint.setAntiAlias(true);
856a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            }
866a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        }
876a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        bitmap.setDensity(source.getDensity());
886a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        canvas.setBitmap(bitmap);
896a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
906a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        Rect srcBounds = new Rect(x, y, x + width, y + height);
916a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        RectF dstBounds = new RectF(0, 0, width, height);
926a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        canvas.drawBitmap(source, srcBounds, dstBounds, paint);
936a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        return bitmap;
946a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    }
956a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
966a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    private void closeStream(Closeable stream) {
976a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        if (stream != null) {
986a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            try {
996a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                stream.close();
1006a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            } catch (IOException e) {
1016a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                e.printStackTrace();
1026a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            }
1036a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        }
1046a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    }
1056a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
1066a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    private Rect getBitmapBounds(Uri uri) {
1076a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        Rect bounds = new Rect();
1086a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        InputStream is = null;
1096a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
1106a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        try {
1116a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            is = context.getContentResolver().openInputStream(uri);
1126a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            BitmapFactory.Options options = new BitmapFactory.Options();
1136a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            options.inJustDecodeBounds = true;
1146a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            BitmapFactory.decodeStream(is, null, options);
1156a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
1166a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            bounds.right = options.outWidth;
1176a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            bounds.bottom = options.outHeight;
1186a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        } catch (FileNotFoundException e) {
1196a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            e.printStackTrace();
1206a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        } finally {
1216a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            closeStream(is);
1226a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        }
1236a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
1246a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        return bounds;
1256a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    }
1266a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
1276a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    private int getOrientation(Uri uri) {
1286a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        int orientation = 0;
129fef5b9860f0a88fc673af2187938956ebd0ade75Yuli Huang        Cursor cursor = null;
1306a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        try {
131fef5b9860f0a88fc673af2187938956ebd0ade75Yuli Huang            cursor = context.getContentResolver().query(uri, IMAGE_PROJECTION, null, null, null);
1326a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            if ((cursor != null) && cursor.moveToNext()) {
1336a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                orientation = cursor.getInt(INDEX_ORIENTATION);
1346a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            }
135fef5b9860f0a88fc673af2187938956ebd0ade75Yuli Huang        } catch (Exception e) {
136fef5b9860f0a88fc673af2187938956ebd0ade75Yuli Huang            // Ignore error for no orientation column; just use the default orientation value 0.
1376a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        } finally {
1386a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            if (cursor != null) {
1396a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                cursor.close();
1406a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            }
1416a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        }
1426a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        return orientation;
1436a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    }
1446a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
1456a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    /**
1466a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang     * Decodes bitmap (maybe immutable) that keeps aspect-ratio and spans most within the bounds.
1476a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang     */
1486a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    private Bitmap decodeBitmap(Uri uri, int width, int height) {
1496a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        InputStream is = null;
1506a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        Bitmap bitmap = null;
1516a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
1526a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        try {
1536a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            // TODO: Take max pixels allowed into account for calculation to avoid possible OOM.
1546a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            Rect bounds = getBitmapBounds(uri);
1556a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            int sampleSize = Math.max(bounds.width() / width, bounds.height() / height);
1566a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            sampleSize = Math.min(sampleSize,
1576a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                    Math.max(bounds.width() / height, bounds.height() / width));
1586a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
1596a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            BitmapFactory.Options options = new BitmapFactory.Options();
1606a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            options.inSampleSize = Math.max(sampleSize, 1);
1616a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
1626a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
1636a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            is = context.getContentResolver().openInputStream(uri);
1646a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            bitmap = BitmapFactory.decodeStream(is, null, options);
1656a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        } catch (FileNotFoundException e) {
1666a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            Log.e(TAG, "FileNotFoundException: " + uri);
1676a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        } finally {
1686a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            closeStream(is);
1696a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        }
1706a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
171f66bd12b33e0d590e192a3551e9affc55eef9a48Yuli Huang        // Ensure bitmap in 8888 format, good for editing as well as GL compatible.
172f66bd12b33e0d590e192a3551e9affc55eef9a48Yuli Huang        if ((bitmap != null) && (bitmap.getConfig() != Bitmap.Config.ARGB_8888)) {
173f66bd12b33e0d590e192a3551e9affc55eef9a48Yuli Huang            Bitmap copy = bitmap.copy(Bitmap.Config.ARGB_8888, true);
174f66bd12b33e0d590e192a3551e9affc55eef9a48Yuli Huang            bitmap.recycle();
175f66bd12b33e0d590e192a3551e9affc55eef9a48Yuli Huang            bitmap = copy;
176f66bd12b33e0d590e192a3551e9affc55eef9a48Yuli Huang        }
177f66bd12b33e0d590e192a3551e9affc55eef9a48Yuli Huang
1786a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        if (bitmap != null) {
179f66bd12b33e0d590e192a3551e9affc55eef9a48Yuli Huang            // Scale down the sampled bitmap if it's still larger than the desired dimension.
1806a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            float scale = Math.min((float) width / bitmap.getWidth(),
1816a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                    (float) height / bitmap.getHeight());
1826a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            scale = Math.max(scale, Math.min((float) height / bitmap.getWidth(),
1836a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                    (float) width / bitmap.getHeight()));
1846a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            if (scale < 1) {
1856a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                Matrix m = new Matrix();
1866a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                m.setScale(scale, scale);
1876a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                Bitmap transformed = createBitmap(
1886a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                        bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m);
1896a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                bitmap.recycle();
1906a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                return transformed;
1916a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            }
1926a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        }
1936a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        return bitmap;
1946a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    }
1956a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
1966a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    /**
1976a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang     * Gets decoded bitmap that keeps orientation as well.
1986a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang     */
1996a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    public Bitmap getBitmap(Uri uri, int width, int height) {
2006a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        Bitmap bitmap = decodeBitmap(uri, width, height);
2016a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
2026a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        // Rotate the decoded bitmap according to its orientation if it's necessary.
2036a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        if (bitmap != null) {
2046a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            int orientation = getOrientation(uri);
2056a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            if (orientation != 0) {
2066a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                Matrix m = new Matrix();
2076a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                m.setRotate(orientation);
2086a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                Bitmap transformed = createBitmap(
2096a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                        bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m);
2106a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                bitmap.recycle();
2116a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                return transformed;
2126a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            }
2136a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        }
2146a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        return bitmap;
2156a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    }
2166a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
2176a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    /**
2186a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang     * Saves the bitmap by given directory, filename, and format; if the directory is given null,
2196a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang     * then saves it under the cache directory.
2206a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang     */
2216a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    public File saveBitmap(
2226a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            Bitmap bitmap, String directory, String filename, CompressFormat format) {
2236a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
2246a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        if (directory == null) {
2256a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            directory = context.getCacheDir().getAbsolutePath();
2266a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        } else {
2276a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            // Check if the given directory exists or try to create it.
2286a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            File file = new File(directory);
2296a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            if (!file.isDirectory() && !file.mkdirs()) {
2306a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang                return null;
2316a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            }
2326a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        }
2336a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
2346a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        File file = null;
2356a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        OutputStream os = null;
2366a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang
2376a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        try {
2386a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            filename = (format == CompressFormat.PNG) ? filename + ".png" : filename + ".jpg";
2396a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            file = new File(directory, filename);
2406a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            os = new FileOutputStream(file);
2416a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            bitmap.compress(format, DEFAULT_COMPRESS_QUALITY, os);
2426a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        } catch (FileNotFoundException e) {
2436a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            e.printStackTrace();
2446a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        } finally {
2456a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang            closeStream(os);
2466a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        }
2476a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang        return file;
2486a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang    }
2496a12ad70df5da5052a8381e2cdda79e6a314cee9Yuli Huang}
250