1841a502864d307341945eae62569b92cada93e75Sunny Goyalpackage com.android.wallpaperpicker.common;
2841a502864d307341945eae62569b92cada93e75Sunny Goyal
3841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.content.Context;
4841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.content.res.Resources;
5841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.graphics.Bitmap;
6841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.graphics.BitmapFactory;
7841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.graphics.BitmapRegionDecoder;
8841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.graphics.Canvas;
9841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.graphics.Matrix;
10841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.graphics.Paint;
11841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.graphics.Point;
12841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.graphics.Rect;
13841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.graphics.RectF;
14841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.net.Uri;
15841a502864d307341945eae62569b92cada93e75Sunny Goyalimport android.util.Log;
16841a502864d307341945eae62569b92cada93e75Sunny Goyal
17841a502864d307341945eae62569b92cada93e75Sunny Goyalimport com.android.gallery3d.common.ExifOrientation;
18841a502864d307341945eae62569b92cada93e75Sunny Goyalimport com.android.gallery3d.common.Utils;
19841a502864d307341945eae62569b92cada93e75Sunny Goyal
20841a502864d307341945eae62569b92cada93e75Sunny Goyalimport java.io.BufferedInputStream;
21841a502864d307341945eae62569b92cada93e75Sunny Goyalimport java.io.ByteArrayInputStream;
22841a502864d307341945eae62569b92cada93e75Sunny Goyalimport java.io.IOException;
23841a502864d307341945eae62569b92cada93e75Sunny Goyalimport java.io.InputStream;
24841a502864d307341945eae62569b92cada93e75Sunny Goyal
25841a502864d307341945eae62569b92cada93e75Sunny Goyal/**
26841a502864d307341945eae62569b92cada93e75Sunny Goyal * An abstraction over input stream creation. Also contains some utility methods
27841a502864d307341945eae62569b92cada93e75Sunny Goyal * for various bitmap operations.
28841a502864d307341945eae62569b92cada93e75Sunny Goyal */
29841a502864d307341945eae62569b92cada93e75Sunny Goyalpublic abstract class InputStreamProvider {
30841a502864d307341945eae62569b92cada93e75Sunny Goyal
31841a502864d307341945eae62569b92cada93e75Sunny Goyal    private static final String TAG = "InputStreamProvider";
32841a502864d307341945eae62569b92cada93e75Sunny Goyal
33841a502864d307341945eae62569b92cada93e75Sunny Goyal    /**
34841a502864d307341945eae62569b92cada93e75Sunny Goyal     * Tries to create a new stream or returns null on failure.
35841a502864d307341945eae62569b92cada93e75Sunny Goyal     */
36841a502864d307341945eae62569b92cada93e75Sunny Goyal    public InputStream newStream() {
37841a502864d307341945eae62569b92cada93e75Sunny Goyal        try {
38841a502864d307341945eae62569b92cada93e75Sunny Goyal            return newStreamNotNull();
39841a502864d307341945eae62569b92cada93e75Sunny Goyal        } catch (IOException e) {
40841a502864d307341945eae62569b92cada93e75Sunny Goyal            return null;
41841a502864d307341945eae62569b92cada93e75Sunny Goyal        }
42841a502864d307341945eae62569b92cada93e75Sunny Goyal    }
43841a502864d307341945eae62569b92cada93e75Sunny Goyal
44841a502864d307341945eae62569b92cada93e75Sunny Goyal    /**
45841a502864d307341945eae62569b92cada93e75Sunny Goyal     * Tries to create a new stream or throws an exception on failure.
46841a502864d307341945eae62569b92cada93e75Sunny Goyal     */
47841a502864d307341945eae62569b92cada93e75Sunny Goyal    public abstract InputStream newStreamNotNull() throws IOException;
48841a502864d307341945eae62569b92cada93e75Sunny Goyal
49841a502864d307341945eae62569b92cada93e75Sunny Goyal    /**
50841a502864d307341945eae62569b92cada93e75Sunny Goyal     * Returns the size of the image, if the stream represents an image.
51841a502864d307341945eae62569b92cada93e75Sunny Goyal     */
52841a502864d307341945eae62569b92cada93e75Sunny Goyal    public Point getImageBounds() {
53841a502864d307341945eae62569b92cada93e75Sunny Goyal        InputStream is = newStream();
54841a502864d307341945eae62569b92cada93e75Sunny Goyal        if (is != null) {
55841a502864d307341945eae62569b92cada93e75Sunny Goyal            BitmapFactory.Options options = new BitmapFactory.Options();
56841a502864d307341945eae62569b92cada93e75Sunny Goyal            options.inJustDecodeBounds = true;
57841a502864d307341945eae62569b92cada93e75Sunny Goyal            BitmapFactory.decodeStream(is, null, options);
58841a502864d307341945eae62569b92cada93e75Sunny Goyal            Utils.closeSilently(is);
59841a502864d307341945eae62569b92cada93e75Sunny Goyal            if (options.outWidth != 0 && options.outHeight != 0) {
60841a502864d307341945eae62569b92cada93e75Sunny Goyal                return new Point(options.outWidth, options.outHeight);
61841a502864d307341945eae62569b92cada93e75Sunny Goyal            }
62841a502864d307341945eae62569b92cada93e75Sunny Goyal        }
63841a502864d307341945eae62569b92cada93e75Sunny Goyal        return null;
64841a502864d307341945eae62569b92cada93e75Sunny Goyal    }
65841a502864d307341945eae62569b92cada93e75Sunny Goyal
66841a502864d307341945eae62569b92cada93e75Sunny Goyal    public Bitmap readCroppedBitmap(RectF cropBounds, int outWidth, int outHeight, int rotation) {
67841a502864d307341945eae62569b92cada93e75Sunny Goyal        // Find crop bounds (scaled to original image size)
68841a502864d307341945eae62569b92cada93e75Sunny Goyal        Rect roundedTrueCrop = new Rect();
69841a502864d307341945eae62569b92cada93e75Sunny Goyal        Matrix rotateMatrix = new Matrix();
70841a502864d307341945eae62569b92cada93e75Sunny Goyal        Point bounds = getImageBounds();
71841a502864d307341945eae62569b92cada93e75Sunny Goyal        if (bounds == null) {
72841a502864d307341945eae62569b92cada93e75Sunny Goyal            Log.w(TAG, "cannot get bounds for image");
73841a502864d307341945eae62569b92cada93e75Sunny Goyal            return null;
74841a502864d307341945eae62569b92cada93e75Sunny Goyal        }
75841a502864d307341945eae62569b92cada93e75Sunny Goyal
76841a502864d307341945eae62569b92cada93e75Sunny Goyal        if (rotation > 0) {
77841a502864d307341945eae62569b92cada93e75Sunny Goyal            rotateMatrix.setRotate(rotation);
78841a502864d307341945eae62569b92cada93e75Sunny Goyal
79841a502864d307341945eae62569b92cada93e75Sunny Goyal            Matrix inverseRotateMatrix = new Matrix();
80841a502864d307341945eae62569b92cada93e75Sunny Goyal            inverseRotateMatrix.setRotate(-rotation);
81841a502864d307341945eae62569b92cada93e75Sunny Goyal
82841a502864d307341945eae62569b92cada93e75Sunny Goyal            cropBounds.roundOut(roundedTrueCrop);
83841a502864d307341945eae62569b92cada93e75Sunny Goyal            cropBounds.set(roundedTrueCrop);
84841a502864d307341945eae62569b92cada93e75Sunny Goyal
85841a502864d307341945eae62569b92cada93e75Sunny Goyal            float[] rotatedBounds = new float[] { bounds.x, bounds.y };
86841a502864d307341945eae62569b92cada93e75Sunny Goyal            rotateMatrix.mapPoints(rotatedBounds);
87841a502864d307341945eae62569b92cada93e75Sunny Goyal            rotatedBounds[0] = Math.abs(rotatedBounds[0]);
88841a502864d307341945eae62569b92cada93e75Sunny Goyal            rotatedBounds[1] = Math.abs(rotatedBounds[1]);
89841a502864d307341945eae62569b92cada93e75Sunny Goyal
90841a502864d307341945eae62569b92cada93e75Sunny Goyal            cropBounds.offset(-rotatedBounds[0]/2, -rotatedBounds[1]/2);
91841a502864d307341945eae62569b92cada93e75Sunny Goyal            inverseRotateMatrix.mapRect(cropBounds);
92841a502864d307341945eae62569b92cada93e75Sunny Goyal            cropBounds.offset(bounds.x/2, bounds.y/2);
93841a502864d307341945eae62569b92cada93e75Sunny Goyal        }
94841a502864d307341945eae62569b92cada93e75Sunny Goyal
95841a502864d307341945eae62569b92cada93e75Sunny Goyal        cropBounds.roundOut(roundedTrueCrop);
96841a502864d307341945eae62569b92cada93e75Sunny Goyal        if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) {
97841a502864d307341945eae62569b92cada93e75Sunny Goyal            Log.w(TAG, "crop has bad values for full size image");
98841a502864d307341945eae62569b92cada93e75Sunny Goyal            return null;
99841a502864d307341945eae62569b92cada93e75Sunny Goyal        }
100841a502864d307341945eae62569b92cada93e75Sunny Goyal
101841a502864d307341945eae62569b92cada93e75Sunny Goyal        // See how much we're reducing the size of the image
102841a502864d307341945eae62569b92cada93e75Sunny Goyal        int scaleDownSampleSize = Math.max(1, Math.min(roundedTrueCrop.width() / outWidth,
103841a502864d307341945eae62569b92cada93e75Sunny Goyal                roundedTrueCrop.height() / outHeight));
104841a502864d307341945eae62569b92cada93e75Sunny Goyal        // Attempt to open a region decoder
105841a502864d307341945eae62569b92cada93e75Sunny Goyal        InputStream is = null;
106841a502864d307341945eae62569b92cada93e75Sunny Goyal        BitmapRegionDecoder decoder = null;
107841a502864d307341945eae62569b92cada93e75Sunny Goyal        try {
108841a502864d307341945eae62569b92cada93e75Sunny Goyal            is = newStreamNotNull();
109841a502864d307341945eae62569b92cada93e75Sunny Goyal            decoder = BitmapRegionDecoder.newInstance(is, false);
110841a502864d307341945eae62569b92cada93e75Sunny Goyal        } catch (IOException e) {
111841a502864d307341945eae62569b92cada93e75Sunny Goyal            Log.w(TAG, "cannot open region decoder", e);
112841a502864d307341945eae62569b92cada93e75Sunny Goyal        } finally {
113841a502864d307341945eae62569b92cada93e75Sunny Goyal            Utils.closeSilently(is);
114841a502864d307341945eae62569b92cada93e75Sunny Goyal            is = null;
115841a502864d307341945eae62569b92cada93e75Sunny Goyal        }
116841a502864d307341945eae62569b92cada93e75Sunny Goyal
117841a502864d307341945eae62569b92cada93e75Sunny Goyal        Bitmap crop = null;
118841a502864d307341945eae62569b92cada93e75Sunny Goyal        if (decoder != null) {
119841a502864d307341945eae62569b92cada93e75Sunny Goyal            // Do region decoding to get crop bitmap
120841a502864d307341945eae62569b92cada93e75Sunny Goyal            BitmapFactory.Options options = new BitmapFactory.Options();
121841a502864d307341945eae62569b92cada93e75Sunny Goyal            if (scaleDownSampleSize > 1) {
122841a502864d307341945eae62569b92cada93e75Sunny Goyal                options.inSampleSize = scaleDownSampleSize;
123841a502864d307341945eae62569b92cada93e75Sunny Goyal            }
124841a502864d307341945eae62569b92cada93e75Sunny Goyal            crop = decoder.decodeRegion(roundedTrueCrop, options);
125841a502864d307341945eae62569b92cada93e75Sunny Goyal            decoder.recycle();
126841a502864d307341945eae62569b92cada93e75Sunny Goyal        }
127841a502864d307341945eae62569b92cada93e75Sunny Goyal
128841a502864d307341945eae62569b92cada93e75Sunny Goyal        if (crop == null) {
129841a502864d307341945eae62569b92cada93e75Sunny Goyal            // BitmapRegionDecoder has failed, try to crop in-memory
130841a502864d307341945eae62569b92cada93e75Sunny Goyal            is = newStream();
131841a502864d307341945eae62569b92cada93e75Sunny Goyal            Bitmap fullSize = null;
132841a502864d307341945eae62569b92cada93e75Sunny Goyal            if (is != null) {
133841a502864d307341945eae62569b92cada93e75Sunny Goyal                BitmapFactory.Options options = new BitmapFactory.Options();
134841a502864d307341945eae62569b92cada93e75Sunny Goyal                if (scaleDownSampleSize > 1) {
135841a502864d307341945eae62569b92cada93e75Sunny Goyal                    options.inSampleSize = scaleDownSampleSize;
136841a502864d307341945eae62569b92cada93e75Sunny Goyal                }
137841a502864d307341945eae62569b92cada93e75Sunny Goyal                fullSize = BitmapFactory.decodeStream(is, null, options);
138841a502864d307341945eae62569b92cada93e75Sunny Goyal                Utils.closeSilently(is);
139841a502864d307341945eae62569b92cada93e75Sunny Goyal            }
140841a502864d307341945eae62569b92cada93e75Sunny Goyal            if (fullSize != null) {
141841a502864d307341945eae62569b92cada93e75Sunny Goyal                // Find out the true sample size that was used by the decoder
142841a502864d307341945eae62569b92cada93e75Sunny Goyal                scaleDownSampleSize = bounds.x / fullSize.getWidth();
143841a502864d307341945eae62569b92cada93e75Sunny Goyal                cropBounds.left /= scaleDownSampleSize;
144841a502864d307341945eae62569b92cada93e75Sunny Goyal                cropBounds.top /= scaleDownSampleSize;
145841a502864d307341945eae62569b92cada93e75Sunny Goyal                cropBounds.bottom /= scaleDownSampleSize;
146841a502864d307341945eae62569b92cada93e75Sunny Goyal                cropBounds.right /= scaleDownSampleSize;
147841a502864d307341945eae62569b92cada93e75Sunny Goyal                cropBounds.roundOut(roundedTrueCrop);
148841a502864d307341945eae62569b92cada93e75Sunny Goyal
149841a502864d307341945eae62569b92cada93e75Sunny Goyal                // Adjust values to account for issues related to rounding
150841a502864d307341945eae62569b92cada93e75Sunny Goyal                if (roundedTrueCrop.width() > fullSize.getWidth()) {
151841a502864d307341945eae62569b92cada93e75Sunny Goyal                    // Adjust the width
152841a502864d307341945eae62569b92cada93e75Sunny Goyal                    roundedTrueCrop.right = roundedTrueCrop.left + fullSize.getWidth();
153841a502864d307341945eae62569b92cada93e75Sunny Goyal                }
154841a502864d307341945eae62569b92cada93e75Sunny Goyal                if (roundedTrueCrop.right > fullSize.getWidth()) {
155841a502864d307341945eae62569b92cada93e75Sunny Goyal                    // Adjust the left and right values.
156841a502864d307341945eae62569b92cada93e75Sunny Goyal                    roundedTrueCrop.offset(-(roundedTrueCrop.right - fullSize.getWidth()), 0);
157841a502864d307341945eae62569b92cada93e75Sunny Goyal                }
158841a502864d307341945eae62569b92cada93e75Sunny Goyal                if (roundedTrueCrop.height() > fullSize.getHeight()) {
159841a502864d307341945eae62569b92cada93e75Sunny Goyal                    // Adjust the height
160841a502864d307341945eae62569b92cada93e75Sunny Goyal                    roundedTrueCrop.bottom = roundedTrueCrop.top + fullSize.getHeight();
161841a502864d307341945eae62569b92cada93e75Sunny Goyal                }
162841a502864d307341945eae62569b92cada93e75Sunny Goyal                if (roundedTrueCrop.bottom > fullSize.getHeight()) {
163841a502864d307341945eae62569b92cada93e75Sunny Goyal                    // Adjust the top and bottom values.
164841a502864d307341945eae62569b92cada93e75Sunny Goyal                    roundedTrueCrop.offset(0, -(roundedTrueCrop.bottom - fullSize.getHeight()));
165841a502864d307341945eae62569b92cada93e75Sunny Goyal                }
166841a502864d307341945eae62569b92cada93e75Sunny Goyal
167841a502864d307341945eae62569b92cada93e75Sunny Goyal                crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left,
168841a502864d307341945eae62569b92cada93e75Sunny Goyal                        roundedTrueCrop.top, roundedTrueCrop.width(),
169841a502864d307341945eae62569b92cada93e75Sunny Goyal                        roundedTrueCrop.height());
170841a502864d307341945eae62569b92cada93e75Sunny Goyal            }
171841a502864d307341945eae62569b92cada93e75Sunny Goyal        }
172841a502864d307341945eae62569b92cada93e75Sunny Goyal
173841a502864d307341945eae62569b92cada93e75Sunny Goyal        if (crop == null) {
174841a502864d307341945eae62569b92cada93e75Sunny Goyal            return null;
175841a502864d307341945eae62569b92cada93e75Sunny Goyal        }
176841a502864d307341945eae62569b92cada93e75Sunny Goyal        if (outWidth > 0 && outHeight > 0 || rotation > 0) {
177841a502864d307341945eae62569b92cada93e75Sunny Goyal            float[] dimsAfter = new float[] { crop.getWidth(), crop.getHeight() };
178841a502864d307341945eae62569b92cada93e75Sunny Goyal            rotateMatrix.mapPoints(dimsAfter);
179841a502864d307341945eae62569b92cada93e75Sunny Goyal            dimsAfter[0] = Math.abs(dimsAfter[0]);
180841a502864d307341945eae62569b92cada93e75Sunny Goyal            dimsAfter[1] = Math.abs(dimsAfter[1]);
181841a502864d307341945eae62569b92cada93e75Sunny Goyal
182841a502864d307341945eae62569b92cada93e75Sunny Goyal            if (!(outWidth > 0 && outHeight > 0)) {
183841a502864d307341945eae62569b92cada93e75Sunny Goyal                outWidth = Math.round(dimsAfter[0]);
184841a502864d307341945eae62569b92cada93e75Sunny Goyal                outHeight = Math.round(dimsAfter[1]);
185841a502864d307341945eae62569b92cada93e75Sunny Goyal            }
186841a502864d307341945eae62569b92cada93e75Sunny Goyal
187841a502864d307341945eae62569b92cada93e75Sunny Goyal            RectF cropRect = new RectF(0, 0, dimsAfter[0], dimsAfter[1]);
188841a502864d307341945eae62569b92cada93e75Sunny Goyal            RectF returnRect = new RectF(0, 0, outWidth, outHeight);
189841a502864d307341945eae62569b92cada93e75Sunny Goyal
190841a502864d307341945eae62569b92cada93e75Sunny Goyal            Matrix m = new Matrix();
191841a502864d307341945eae62569b92cada93e75Sunny Goyal            if (rotation == 0) {
192841a502864d307341945eae62569b92cada93e75Sunny Goyal                m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
193841a502864d307341945eae62569b92cada93e75Sunny Goyal            } else {
194841a502864d307341945eae62569b92cada93e75Sunny Goyal                Matrix m1 = new Matrix();
195841a502864d307341945eae62569b92cada93e75Sunny Goyal                m1.setTranslate(-crop.getWidth() / 2f, -crop.getHeight() / 2f);
196841a502864d307341945eae62569b92cada93e75Sunny Goyal                Matrix m2 = new Matrix();
197841a502864d307341945eae62569b92cada93e75Sunny Goyal                m2.setRotate(rotation);
198841a502864d307341945eae62569b92cada93e75Sunny Goyal                Matrix m3 = new Matrix();
199841a502864d307341945eae62569b92cada93e75Sunny Goyal                m3.setTranslate(dimsAfter[0] / 2f, dimsAfter[1] / 2f);
200841a502864d307341945eae62569b92cada93e75Sunny Goyal                Matrix m4 = new Matrix();
201841a502864d307341945eae62569b92cada93e75Sunny Goyal                m4.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
202841a502864d307341945eae62569b92cada93e75Sunny Goyal
203841a502864d307341945eae62569b92cada93e75Sunny Goyal                Matrix c1 = new Matrix();
204841a502864d307341945eae62569b92cada93e75Sunny Goyal                c1.setConcat(m2, m1);
205841a502864d307341945eae62569b92cada93e75Sunny Goyal                Matrix c2 = new Matrix();
206841a502864d307341945eae62569b92cada93e75Sunny Goyal                c2.setConcat(m4, m3);
207841a502864d307341945eae62569b92cada93e75Sunny Goyal                m.setConcat(c2, c1);
208841a502864d307341945eae62569b92cada93e75Sunny Goyal            }
209841a502864d307341945eae62569b92cada93e75Sunny Goyal
210841a502864d307341945eae62569b92cada93e75Sunny Goyal            Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(),
211841a502864d307341945eae62569b92cada93e75Sunny Goyal                    (int) returnRect.height(), Bitmap.Config.ARGB_8888);
212841a502864d307341945eae62569b92cada93e75Sunny Goyal            if (tmp != null) {
213841a502864d307341945eae62569b92cada93e75Sunny Goyal                Canvas c = new Canvas(tmp);
214841a502864d307341945eae62569b92cada93e75Sunny Goyal                Paint p = new Paint();
215841a502864d307341945eae62569b92cada93e75Sunny Goyal                p.setFilterBitmap(true);
216841a502864d307341945eae62569b92cada93e75Sunny Goyal                c.drawBitmap(crop, m, p);
217841a502864d307341945eae62569b92cada93e75Sunny Goyal                crop = tmp;
218841a502864d307341945eae62569b92cada93e75Sunny Goyal            }
219841a502864d307341945eae62569b92cada93e75Sunny Goyal        }
220841a502864d307341945eae62569b92cada93e75Sunny Goyal        return crop;
221841a502864d307341945eae62569b92cada93e75Sunny Goyal    }
222841a502864d307341945eae62569b92cada93e75Sunny Goyal
223841a502864d307341945eae62569b92cada93e75Sunny Goyal    public int getRotationFromExif(Context context) {
224841a502864d307341945eae62569b92cada93e75Sunny Goyal        InputStream is = null;
225841a502864d307341945eae62569b92cada93e75Sunny Goyal        try {
226841a502864d307341945eae62569b92cada93e75Sunny Goyal            is = newStreamNotNull();
227841a502864d307341945eae62569b92cada93e75Sunny Goyal            return ExifOrientation.readRotation(new BufferedInputStream(is), context);
228841a502864d307341945eae62569b92cada93e75Sunny Goyal        } catch (IOException | NullPointerException e) {
229841a502864d307341945eae62569b92cada93e75Sunny Goyal            Log.w(TAG, "Getting exif data failed", e);
230841a502864d307341945eae62569b92cada93e75Sunny Goyal        } finally {
231841a502864d307341945eae62569b92cada93e75Sunny Goyal            Utils.closeSilently(is);
232841a502864d307341945eae62569b92cada93e75Sunny Goyal        }
233841a502864d307341945eae62569b92cada93e75Sunny Goyal        return 0;
234841a502864d307341945eae62569b92cada93e75Sunny Goyal    }
235841a502864d307341945eae62569b92cada93e75Sunny Goyal
236841a502864d307341945eae62569b92cada93e75Sunny Goyal    public static InputStreamProvider fromUri(final Context context, final Uri uri) {
237841a502864d307341945eae62569b92cada93e75Sunny Goyal        return new InputStreamProvider() {
238841a502864d307341945eae62569b92cada93e75Sunny Goyal            @Override
239841a502864d307341945eae62569b92cada93e75Sunny Goyal            public InputStream newStreamNotNull() throws IOException {
240841a502864d307341945eae62569b92cada93e75Sunny Goyal                return new BufferedInputStream(context.getContentResolver().openInputStream(uri));
241841a502864d307341945eae62569b92cada93e75Sunny Goyal            }
242841a502864d307341945eae62569b92cada93e75Sunny Goyal        };
243841a502864d307341945eae62569b92cada93e75Sunny Goyal    }
244841a502864d307341945eae62569b92cada93e75Sunny Goyal
245841a502864d307341945eae62569b92cada93e75Sunny Goyal    public static InputStreamProvider fromResource(final Resources resources, final int resId) {
246841a502864d307341945eae62569b92cada93e75Sunny Goyal        return new InputStreamProvider() {
247841a502864d307341945eae62569b92cada93e75Sunny Goyal            @Override
248841a502864d307341945eae62569b92cada93e75Sunny Goyal            public InputStream newStreamNotNull() {
249841a502864d307341945eae62569b92cada93e75Sunny Goyal                return new BufferedInputStream(resources.openRawResource(resId));
250841a502864d307341945eae62569b92cada93e75Sunny Goyal            }
251841a502864d307341945eae62569b92cada93e75Sunny Goyal        };
252841a502864d307341945eae62569b92cada93e75Sunny Goyal    }
253841a502864d307341945eae62569b92cada93e75Sunny Goyal
254841a502864d307341945eae62569b92cada93e75Sunny Goyal    public static InputStreamProvider fromBytes(final byte[] bytes) {
255841a502864d307341945eae62569b92cada93e75Sunny Goyal        return new InputStreamProvider() {
256841a502864d307341945eae62569b92cada93e75Sunny Goyal            @Override
257841a502864d307341945eae62569b92cada93e75Sunny Goyal            public InputStream newStreamNotNull() {
258841a502864d307341945eae62569b92cada93e75Sunny Goyal                return new BufferedInputStream(new ByteArrayInputStream(bytes));
259841a502864d307341945eae62569b92cada93e75Sunny Goyal            }
260841a502864d307341945eae62569b92cada93e75Sunny Goyal        };
261841a502864d307341945eae62569b92cada93e75Sunny Goyal    }
262841a502864d307341945eae62569b92cada93e75Sunny Goyal
263841a502864d307341945eae62569b92cada93e75Sunny Goyal}
264