1fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford/*
2fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford * Copyright (C) 2015 The Android Open Source Project
3fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford *
4fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford * Licensed under the Apache License, Version 2.0 (the "License");
5fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford * you may not use this file except in compliance with the License.
6fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford * You may obtain a copy of the License at
7fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford *
8fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford *      http://www.apache.org/licenses/LICENSE-2.0
9fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford *
10fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford * Unless required by applicable law or agreed to in writing, software
11fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford * distributed under the License is distributed on an "AS IS" BASIS,
12fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford * See the License for the specific language governing permissions and
14fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford * limitations under the License.
15fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford */
16fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
17fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordpackage com.android.example.rscamera;
18fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
19fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordimport java.io.FileNotFoundException;
20fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordimport java.io.IOException;
21fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordimport java.io.OutputStream;
22fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
23fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordimport android.content.ContentResolver;
24fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordimport android.content.ContentUris;
25fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordimport android.content.ContentValues;
26fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordimport android.graphics.Bitmap;
27fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordimport android.graphics.Matrix;
28fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordimport android.net.Uri;
29fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordimport android.provider.MediaStore;
30fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordimport android.provider.MediaStore.Images;
31fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
32fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford/**
33fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford * Utility class to save images into android image database
34fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford */
35fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hofordpublic class MediaStoreSaver {
36fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford    public static interface StreamWriter {
37fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        void write(OutputStream imageOut) throws IOException;
38fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford    }
39fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
40fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford    public static final String insertImage(ContentResolver contentResolver,
41fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                                           Bitmap image,
42fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                                           String title,
43fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                                           String description) {
44fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        final Bitmap source = image;
45fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        StreamWriter streamWriter = new StreamWriter() {
46fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            public void write(OutputStream imageOut) {
47fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut);
48fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            }
49fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        };
50fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        return insertImage(contentResolver, streamWriter, title, description);
51fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford    }
52fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
53fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
54fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford    public static final String insertImage(ContentResolver cr,
55fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                                           StreamWriter source,
56fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                                           String title,
57fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                                           String description) {
58fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
59fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        ContentValues values = new ContentValues();
60fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        values.put(Images.Media.TITLE, title);
61fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        values.put(Images.Media.DISPLAY_NAME, title);
62fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        values.put(Images.Media.DESCRIPTION, description);
63fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        values.put(Images.Media.MIME_TYPE, "image/jpeg");
64fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        // Add the date meta data to ensure the image is added at the front of the gallery
65fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        values.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
66fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis());
67fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
68fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        Uri url = null;
69fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        String stringUrl = null;    /* value to be returned */
70fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
71fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        try {
72fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            url = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
73fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
74fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            if (source != null) {
75fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                OutputStream imageOut = cr.openOutputStream(url);
76fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                try {
77fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                    source.write(imageOut);
78fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                } finally {
79fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                    imageOut.close();
80fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                }
81fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
82fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                long id = ContentUris.parseId(url);
83fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                // Wait until MINI_KIND thumbnail is generated.
84fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                Bitmap miniThumb = Images.Thumbnails.getThumbnail(cr, id, Images.Thumbnails.MINI_KIND, null);
85fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                // This is for backward compatibility.
86fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                storeThumbnail(cr, miniThumb, id, 50F, 50F, Images.Thumbnails.MICRO_KIND);
87fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            } else {
88fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                cr.delete(url, null, null);
89fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                url = null;
90fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            }
91fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        } catch (Exception e) {
92fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            if (url != null) {
93fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                cr.delete(url, null, null);
94fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                url = null;
95fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            }
96fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        }
97fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
98fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        if (url != null) {
99fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            stringUrl = url.toString();
100fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        }
101fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
102fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        return stringUrl;
103fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford    }
104fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
105fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford    /**
106fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford     * A copy of the Android internals StoreThumbnail method, it used with the insertImage to
107fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford     * populate the android.provider.MediaStore.Images.Media#insertImage with all the correct
108fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford     * meta data. The StoreThumbnail method is private so it must be duplicated here.
109fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford     *
110fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford     * @see android.provider.MediaStore.Images.Media (StoreThumbnail private method)
111fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford     */
112fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford    private static final Bitmap storeThumbnail(
113fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            ContentResolver cr,
114fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            Bitmap source,
115fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            long id,
116fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            float width,
117fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            float height,
118fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            int kind) {
119fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
120fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        // create the matrix to scale it
121fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        Matrix matrix = new Matrix();
122fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
123fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        float scaleX = width / source.getWidth();
124fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        float scaleY = height / source.getHeight();
125fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
126fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        matrix.setScale(scaleX, scaleY);
127fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
128fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        Bitmap thumb = Bitmap.createBitmap(source, 0, 0,
129fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                source.getWidth(),
130fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                source.getHeight(), matrix,
131fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford                true
132fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        );
133fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
134fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        ContentValues values = new ContentValues(4);
135fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        values.put(Images.Thumbnails.KIND, kind);
136fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        values.put(Images.Thumbnails.IMAGE_ID, (int) id);
137fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        values.put(Images.Thumbnails.HEIGHT, thumb.getHeight());
138fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        values.put(Images.Thumbnails.WIDTH, thumb.getWidth());
139fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
140fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        Uri url = cr.insert(Images.Thumbnails.EXTERNAL_CONTENT_URI, values);
141fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
142fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        try {
143fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            OutputStream thumbOut = cr.openOutputStream(url);
144fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut);
145fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            thumbOut.close();
146fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            return thumb;
147fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        } catch (FileNotFoundException ex) {
148fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            return null;
149fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        } catch (IOException ex) {
150fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford            return null;
151fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford        }
152fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford    }
153fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
154fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford
155fbb9dd1843197a0d2f7fcda29abbe9d170682a5dJohn Hoford}
156