1/*
2 * Copyright (C) 2015 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.example.rscamera;
18
19import java.io.FileNotFoundException;
20import java.io.IOException;
21import java.io.OutputStream;
22
23import android.content.ContentResolver;
24import android.content.ContentUris;
25import android.content.ContentValues;
26import android.graphics.Bitmap;
27import android.graphics.Matrix;
28import android.net.Uri;
29import android.provider.MediaStore;
30import android.provider.MediaStore.Images;
31
32/**
33 * Utility class to save images into android image database
34 */
35public class MediaStoreSaver {
36    public static interface StreamWriter {
37        void write(OutputStream imageOut) throws IOException;
38    }
39
40    public static final String insertImage(ContentResolver contentResolver,
41                                           Bitmap image,
42                                           String title,
43                                           String description) {
44        final Bitmap source = image;
45        StreamWriter streamWriter = new StreamWriter() {
46            public void write(OutputStream imageOut) {
47                source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut);
48            }
49        };
50        return insertImage(contentResolver, streamWriter, title, description);
51    }
52
53
54    public static final String insertImage(ContentResolver cr,
55                                           StreamWriter source,
56                                           String title,
57                                           String description) {
58
59        ContentValues values = new ContentValues();
60        values.put(Images.Media.TITLE, title);
61        values.put(Images.Media.DISPLAY_NAME, title);
62        values.put(Images.Media.DESCRIPTION, description);
63        values.put(Images.Media.MIME_TYPE, "image/jpeg");
64        // Add the date meta data to ensure the image is added at the front of the gallery
65        values.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
66        values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis());
67
68        Uri url = null;
69        String stringUrl = null;    /* value to be returned */
70
71        try {
72            url = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
73
74            if (source != null) {
75                OutputStream imageOut = cr.openOutputStream(url);
76                try {
77                    source.write(imageOut);
78                } finally {
79                    imageOut.close();
80                }
81
82                long id = ContentUris.parseId(url);
83                // Wait until MINI_KIND thumbnail is generated.
84                Bitmap miniThumb = Images.Thumbnails.getThumbnail(cr, id, Images.Thumbnails.MINI_KIND, null);
85                // This is for backward compatibility.
86                storeThumbnail(cr, miniThumb, id, 50F, 50F, Images.Thumbnails.MICRO_KIND);
87            } else {
88                cr.delete(url, null, null);
89                url = null;
90            }
91        } catch (Exception e) {
92            if (url != null) {
93                cr.delete(url, null, null);
94                url = null;
95            }
96        }
97
98        if (url != null) {
99            stringUrl = url.toString();
100        }
101
102        return stringUrl;
103    }
104
105    /**
106     * A copy of the Android internals StoreThumbnail method, it used with the insertImage to
107     * populate the android.provider.MediaStore.Images.Media#insertImage with all the correct
108     * meta data. The StoreThumbnail method is private so it must be duplicated here.
109     *
110     * @see android.provider.MediaStore.Images.Media (StoreThumbnail private method)
111     */
112    private static final Bitmap storeThumbnail(
113            ContentResolver cr,
114            Bitmap source,
115            long id,
116            float width,
117            float height,
118            int kind) {
119
120        // create the matrix to scale it
121        Matrix matrix = new Matrix();
122
123        float scaleX = width / source.getWidth();
124        float scaleY = height / source.getHeight();
125
126        matrix.setScale(scaleX, scaleY);
127
128        Bitmap thumb = Bitmap.createBitmap(source, 0, 0,
129                source.getWidth(),
130                source.getHeight(), matrix,
131                true
132        );
133
134        ContentValues values = new ContentValues(4);
135        values.put(Images.Thumbnails.KIND, kind);
136        values.put(Images.Thumbnails.IMAGE_ID, (int) id);
137        values.put(Images.Thumbnails.HEIGHT, thumb.getHeight());
138        values.put(Images.Thumbnails.WIDTH, thumb.getWidth());
139
140        Uri url = cr.insert(Images.Thumbnails.EXTERNAL_CONTENT_URI, values);
141
142        try {
143            OutputStream thumbOut = cr.openOutputStream(url);
144            thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut);
145            thumbOut.close();
146            return thumb;
147        } catch (FileNotFoundException ex) {
148            return null;
149        } catch (IOException ex) {
150            return null;
151        }
152    }
153
154
155}
156