19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.AssetManager;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.DisplayMetrics;
22b8151ecd6ef4faa5c16d0a4c3abb45ec84d1f97aAmith Yamasaniimport android.util.Log;
23eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chenimport android.util.TypedValue;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.BufferedInputStream;
26eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chenimport java.io.FileDescriptor;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
29eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chenimport java.io.InputStream;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
32eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen * Creates Bitmap objects from various sources, including files, streams,
33eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen * and byte-arrays.
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class BitmapFactory {
367b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy    private static final int DECODE_BUFFER_SIZE = 16 * 1024;
377b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static class Options {
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Create a default Options object, which if left unchanged will give
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the same result from the decoder as if null were passed.
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Options() {
44207b3ab604bcbe47fa55f26f358cde60cf8a784dRomain Guy            inDither = false;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            inScaled = true;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
4937f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         * If set, decode methods that take the Options object will attempt to
50decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase         * reuse this bitmap when loading content. If the decode operation cannot
51decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase         * use this bitmap, the decode method will return <code>null</code> and
52decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase         * will throw an IllegalArgumentException. The
5337f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         * current implementation necessitates that the reused bitmap be of the
54decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase         * same size as the source content and in jpeg or png format (whether as a
5537f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         * resource or as a stream). The {@link android.graphics.Bitmap.Config
5637f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         * configuration} of the reused bitmap will override the setting of
5737f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         * {@link #inPreferredConfig}, if set.
5837f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         *
5937f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         * <p>You should still always use the returned Bitmap of the decode
6037f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         * method and not assume that reusing the bitmap worked, due to the
6137f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         * constraints outlined above and failure situations that can occur.
6237f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         * Checking whether the return value matches the value of the inBitmap
6337f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         * set in the Options structure is a way to see if the bitmap was reused,
6437f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         * but in all cases you should use the returned Bitmap to make sure
6537f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         * that you are using the bitmap that was used as the decode destination.</p>
6637f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase         */
6737f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase        public Bitmap inBitmap;
6837f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase
6937f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase        /**
702361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy         * If set, decode methods will always return a mutable Bitmap instead of
712361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy         * an immutable one. This can be used for instance to programmatically apply
722361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy         * effects to a Bitmap loaded through BitmapFactory.
732361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy         */
742361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy        @SuppressWarnings({"UnusedDeclaration"}) // used in native code
752361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy        public boolean inMutable;
762361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy
772361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy        /**
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * If set to true, the decoder will return null (no bitmap), but
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the out... fields will still be set, allowing the caller to query
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the bitmap without having to allocate the memory for its pixels.
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean inJustDecodeBounds;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * If set to a value > 1, requests the decoder to subsample the original
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * image, returning a smaller image to save memory. The sample size is
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the number of pixels in either dimension that correspond to a single
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * pixel in the decoded bitmap. For example, inSampleSize == 4 returns
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * an image that is 1/4 the width/height of the original, and 1/16 the
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * number of pixels. Any value <= 1 is treated the same as 1. Note: the
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * decoder will try to fulfill this request, but the resulting bitmap
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * may have different dimensions that precisely what has been requested.
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Also, powers of 2 are often faster/easier for the decoder to honor.
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int inSampleSize;
96eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * If this is non-null, the decoder will try to decode into this
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * internal configuration. If it is null, or the request cannot be met,
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the decoder will try to pick the best matching config based on the
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * system's screen depth, and characteristics of the original image such
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * as if it has per-pixel alpha (requiring a config that also does).
103207b3ab604bcbe47fa55f26f358cde60cf8a784dRomain Guy         *
104207b3ab604bcbe47fa55f26f358cde60cf8a784dRomain Guy         * Image are loaded with the {@link Bitmap.Config#ARGB_8888} config by
105207b3ab604bcbe47fa55f26f358cde60cf8a784dRomain Guy         * default.
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
107207b3ab604bcbe47fa55f26f358cde60cf8a784dRomain Guy        public Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888;
108eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1107341d7a104b47996445d069a695e155a07184606Dianne Hackborn         * If dither is true, the decoder will attempt to dither the decoded
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * image.
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean inDither;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
11611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * The pixel density to use for the bitmap.  This will always result
11711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * in the returned bitmap having a density set for it (see
1186e1df0e981c8c588e411b8ad6e55554fe4815655Gilles Debunne         * {@link Bitmap#setDensity(int) Bitmap.setDensity(int)}).  In addition,
11911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * if {@link #inScaled} is set (which it is by default} and this
12011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * density does not match {@link #inTargetDensity}, then the bitmap
12111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * will be scaled to the target density before being returned.
12211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         *
12311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * <p>If this is 0,
12411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * {@link BitmapFactory#decodeResource(Resources, int)},
12511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},
12611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * and {@link BitmapFactory#decodeResourceStream}
12711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * will fill in the density associated with the resource.  The other
12811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * functions will leave it as-is and no density will be applied.
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
13011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see #inTargetDensity
13111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see #inScreenDensity
13211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see #inScaled
13311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see Bitmap#setDensity(int)
13411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see android.util.DisplayMetrics#densityDpi
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int inDensity;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
13911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * The pixel density of the destination this bitmap will be drawn to.
14011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * This is used in conjunction with {@link #inDensity} and
14111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * {@link #inScaled} to determine if and how to scale the bitmap before
14211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * returning it.
14311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         *
14411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * <p>If this is 0,
14511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * {@link BitmapFactory#decodeResource(Resources, int)},
14611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},
14711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * and {@link BitmapFactory#decodeResourceStream}
14811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * will fill in the density associated the Resources object's
14911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * DisplayMetrics.  The other
15011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * functions will leave it as-is and no scaling for density will be
15111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * performed.
15211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         *
15311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see #inDensity
15411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see #inScreenDensity
15511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see #inScaled
15611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see android.util.DisplayMetrics#densityDpi
15711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         */
15811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        public int inTargetDensity;
15911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
16011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        /**
16111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * The pixel density of the actual screen that is being used.  This is
16211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * purely for applications running in density compatibility code, where
16311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * {@link #inTargetDensity} is actually the density the application
16411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * sees rather than the real screen density.
16511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         *
16611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * <p>By setting this, you
16711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * allow the loading code to avoid scaling a bitmap that is currently
16811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * in the screen density up/down to the compatibility density.  Instead,
16911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * if {@link #inDensity} is the same as {@link #inScreenDensity}, the
17011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * bitmap will be left as-is.  Anything using the resulting bitmap
17111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * must also used {@link Bitmap#getScaledWidth(int)
17211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * Bitmap.getScaledWidth} and {@link Bitmap#getScaledHeight
17311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * Bitmap.getScaledHeight} to account for any different between the
17411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * bitmap's density and the target's density.
17511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         *
17611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * <p>This is never set automatically for the caller by
17711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * {@link BitmapFactory} itself.  It must be explicitly set, since the
17811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * caller must deal with the resulting bitmap in a density-aware way.
17911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         *
18011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see #inDensity
18111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see #inTargetDensity
18211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see #inScaled
18311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * @see android.util.DisplayMetrics#densityDpi
18411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         */
18511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        public int inScreenDensity;
18611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
18711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        /**
18811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * When this flag is set, if {@link #inDensity} and
18911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * {@link #inTargetDensity} are not 0, the
19011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * bitmap will be scaled to match {@link #inTargetDensity} when loaded,
19111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * rather than relying on the graphics system scaling it each time it
19211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * is drawn to a Canvas.
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
19411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * <p>This flag is turned on by default and should be turned off if you need
19511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * a non-scaled version of the bitmap.  Nine-patch bitmaps ignore this
19611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn         * flag and are always scaled.
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean inScaled;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
201c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * If this is set to true, then the resulting bitmap will allocate its
202c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * pixels such that they can be purged if the system needs to reclaim
203c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * memory. In that instance, when the pixels need to be accessed again
204c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * (e.g. the bitmap is drawn, getPixels() is called), they will be
205c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * automatically re-decoded.
206c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         *
207c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * For the re-decode to happen, the bitmap must have access to the
208c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * encoded data, either by sharing a reference to the input
209c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * or by making a copy of it. This distinction is controlled by
210c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * inInputShareable. If this is true, then the bitmap may keep a shallow
211c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * reference to the input. If this is false, then the bitmap will
212c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * explicitly make a copy of the input data, and keep that. Even if
213c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * sharing is allowed, the implementation may still decide to make a
214c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * deep copy of the input data.
215c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         */
216c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed        public boolean inPurgeable;
217c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed
218c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed        /**
219c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * This field works in conjuction with inPurgeable. If inPurgeable is
220c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * false, then this field is ignored. If inPurgeable is true, then this
221c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * field determines whether the bitmap can share a reference to the
222c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         * input data (inputstream, array, etc.) or if it must make a deep copy.
223c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed         */
224c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed        public boolean inInputShareable;
225c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed
226c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed        /**
227953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen         * If inPreferQualityOverSpeed is set to true, the decoder will try to
228953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen         * decode the reconstructed image to a higher quality even at the
229953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen         * expense of the decoding speed. Currently the field only affects JPEG
230953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen         * decode, in the case of which a more accurate, but slightly slower,
231953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen         * IDCT method will be used instead.
232953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen         */
233953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen        public boolean inPreferQualityOverSpeed;
234953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen
235953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen        /**
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * The resulting width of the bitmap, set independent of the state of
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * inJustDecodeBounds. However, if there is an error trying to decode,
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * outWidth will be set to -1.
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
240953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int outWidth;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * The resulting height of the bitmap, set independent of the state of
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * inJustDecodeBounds. However, if there is an error trying to decode,
24639c512b623eff1d7a7b17f68a42723fbda9bf483Romain Guy         * outHeight will be set to -1.
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int outHeight;
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * If known, this string is set to the mimetype of the decoded image.
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * If not know, or there is an error, it is set to null.
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String outMimeType;
255eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Temp storage to use for decoding.  Suggest 16K or so.
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public byte[] inTempStorage;
260eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private native void requestCancel();
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Flag to indicate that cancel has been called on this object.  This
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * is useful if there's an intermediary that wants to first decode the
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * bounds and then decode the image.  In that case the intermediary
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * can check, inbetween the bounds decode and the image decode, to see
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * if the operation is canceled.
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean mCancel;
271eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  This can be called from another thread while this options object is
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  inside a decode... call. Calling this will notify the decoder that
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  it should cancel its operation. This is not guaranteed to cancel
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  the decode, but if it does, the decoder... operation will return
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  null, or if inJustDecodeBounds is true, will set outWidth/outHeight
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  to -1
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void requestCancelDecode() {
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCancel = true;
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            requestCancel();
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Decode a file path into a bitmap. If the specified file name is null,
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or cannot be decoded into a bitmap, the function returns null.
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param pathName complete path name for the file to be decoded.
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param opts null-ok; Options that control downsampling and whether the
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *             image should be completely decoded, or just is size returned.
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The decoded bitmap, or null if the image data could not be
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         decoded, or, if opts is non-null, if opts requested only the
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         size be returned (in opts.outWidth and opts.outHeight)
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap decodeFile(String pathName, Options opts) {
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bitmap bm = null;
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputStream stream = null;
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stream = new FileInputStream(pathName);
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bm = decodeStream(stream, null, opts);
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*  do nothing.
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                If the exception happened on open, bm will be null.
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            */
307b8151ecd6ef4faa5c16d0a4c3abb45ec84d1f97aAmith Yamasani            Log.e("BitmapFactory", "Unable to decode stream: " + e);
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (stream != null) {
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    stream.close();
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (IOException e) {
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // do nothing here
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return bm;
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Decode a file path into a bitmap. If the specified file name is null,
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or cannot be decoded into a bitmap, the function returns null.
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param pathName complete path name for the file to be decoded.
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the resulting decoded bitmap, or null if it could not be decoded.
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap decodeFile(String pathName) {
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return decodeFile(pathName, null);
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Decode a new Bitmap from an InputStream. This InputStream was obtained from
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * resources, which we pass to be able to scale the bitmap accordingly.
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
33511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    public static Bitmap decodeResourceStream(Resources res, TypedValue value,
33611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            InputStream is, Rect pad, Options opts) {
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (opts == null) {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            opts = new Options();
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
34211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        if (opts.inDensity == 0 && value != null) {
343a53b828635fce8b6b2d3e3377d74d72070056623Dianne Hackborn            final int density = value.density;
34411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            if (density == TypedValue.DENSITY_DEFAULT) {
34511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn                opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
34611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            } else if (density != TypedValue.DENSITY_NONE) {
34711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn                opts.inDensity = density;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
35011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
35111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        if (opts.inTargetDensity == 0 && res != null) {
35211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
35311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        }
35411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
35511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        return decodeStream(is, pad, opts);
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
35911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Synonym for opening the given resource and calling
36011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * {@link #decodeResourceStream}.
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param res   The resources object containing the image data
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param id The resource id of the image data
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param opts null-ok; Options that control downsampling and whether the
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *             image should be completely decoded, or just is size returned.
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The decoded bitmap, or null if the image data could not be
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         decoded, or, if opts is non-null, if opts requested only the
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         size be returned (in opts.outWidth and opts.outHeight)
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap decodeResource(Resources res, int id, Options opts) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bitmap bm = null;
372650a3eb7d621dc8e81573142a4498bbd07bcde27Romain Guy        InputStream is = null;
373650a3eb7d621dc8e81573142a4498bbd07bcde27Romain Guy
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final TypedValue value = new TypedValue();
376650a3eb7d621dc8e81573142a4498bbd07bcde27Romain Guy            is = res.openRawResource(id, value);
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
37811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            bm = decodeResourceStream(res, value, is, null, opts);
379650a3eb7d621dc8e81573142a4498bbd07bcde27Romain Guy        } catch (Exception e) {
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*  do nothing.
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                If the exception happened on open, bm will be null.
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                If it happened on close, bm is still valid.
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            */
384650a3eb7d621dc8e81573142a4498bbd07bcde27Romain Guy        } finally {
385650a3eb7d621dc8e81573142a4498bbd07bcde27Romain Guy            try {
386650a3eb7d621dc8e81573142a4498bbd07bcde27Romain Guy                if (is != null) is.close();
387650a3eb7d621dc8e81573142a4498bbd07bcde27Romain Guy            } catch (IOException e) {
388650a3eb7d621dc8e81573142a4498bbd07bcde27Romain Guy                // Ignore
389650a3eb7d621dc8e81573142a4498bbd07bcde27Romain Guy            }
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
391650a3eb7d621dc8e81573142a4498bbd07bcde27Romain Guy
392decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase        if (bm == null && opts != null && opts.inBitmap != null) {
393decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase            throw new IllegalArgumentException("Problem decoding into existing bitmap");
394decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase        }
395decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return bm;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
398eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
40011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Synonym for {@link #decodeResource(Resources, int, android.graphics.BitmapFactory.Options)}
40111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * will null Options.
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param res The resources object containing the image data
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param id The resource id of the image data
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The decoded bitmap, or null if the image could not be decode.
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap decodeResource(Resources res, int id) {
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return decodeResource(res, id, null);
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Decode an immutable bitmap from the specified byte array.
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param data byte array of compressed image data
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param offset offset into imageData for where the decoder should begin
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               parsing.
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param length the number of bytes, beginning at offset, to parse
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param opts null-ok; Options that control downsampling and whether the
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *             image should be completely decoded, or just is size returned.
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The decoded bitmap, or null if the image data could not be
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         decoded, or, if opts is non-null, if opts requested only the
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         size be returned (in opts.outWidth and opts.outHeight)
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((offset | length) < 0 || data.length < offset + length) {
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new ArrayIndexOutOfBoundsException();
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
428decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase        Bitmap bm = nativeDecodeByteArray(data, offset, length, opts);
429ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani
430decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase        if (bm == null && opts != null && opts.inBitmap != null) {
431decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase            throw new IllegalArgumentException("Problem decoding into existing bitmap");
432decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase        }
433decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase        return bm;
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
435eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Decode an immutable bitmap from the specified byte array.
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param data byte array of compressed image data
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param offset offset into imageData for where the decoder should begin
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               parsing.
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param length the number of bytes, beginning at offset, to parse
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The decoded bitmap, or null if the image could not be decode.
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap decodeByteArray(byte[] data, int offset, int length) {
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return decodeByteArray(data, offset, length, null);
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
448eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Decode an input stream into a bitmap. If the input stream is null, or
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cannot be used to decode a bitmap, the function returns null.
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The stream's position will be where ever it was after the encoded data
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * was read.
454eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen     *
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param is The input stream that holds the raw data to be decoded into a
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *           bitmap.
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param outPadding If not null, return the padding rect for the bitmap if
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                   it exists, otherwise set padding to [-1,-1,-1,-1]. If
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                   no bitmap is returned (null) then padding is
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                   unchanged.
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param opts null-ok; Options that control downsampling and whether the
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *             image should be completely decoded, or just is size returned.
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The decoded bitmap, or null if the image data could not be
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         decoded, or, if opts is non-null, if opts requested only the
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         size be returned (in opts.outWidth and opts.outHeight)
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // we don't throw in this case, thus allowing the caller to only check
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the cache, and not force the image to be decoded.
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (is == null) {
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
473eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // we need mark/reset to work properly
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!is.markSupported()) {
4777b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            is = new BufferedInputStream(is, DECODE_BUFFER_SIZE);
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // so we can call reset() if a given codec gives up after reading up to
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // this many bytes. FIXME: need to find out from the codecs what this
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // value should be.
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        is.mark(1024);
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4857b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        Bitmap bm;
4867b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        boolean finish = true;
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (is instanceof AssetManager.AssetInputStream) {
4897b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            final int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
4907b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
4917b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            if (opts == null || (opts.inScaled && opts.inBitmap == null)) {
4927b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                float scale = 1.0f;
4937b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                int targetDensity = 0;
4947b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                if (opts != null) {
4957b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                    final int density = opts.inDensity;
4967b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                    targetDensity = opts.inTargetDensity;
4977b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                    if (density != 0 && targetDensity != 0) {
4987b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                        scale = targetDensity / (float) density;
4997b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                    }
5007b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                }
5017b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
5027b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                bm = nativeDecodeAsset(asset, outPadding, opts, true, scale);
5037b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                if (bm != null && targetDensity != 0) bm.setDensity(targetDensity);
5047b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
5057b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                finish = false;
5067b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            } else {
5077b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                bm = nativeDecodeAsset(asset, outPadding, opts);
5087b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            }
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // pass some temp storage down to the native code. 1024 is made up,
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // but should be large enough to avoid too many small calls back
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // into is.read(...) This number is not related to the value passed
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // to mark(...) above.
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            byte [] tempStorage = null;
515207b3ab604bcbe47fa55f26f358cde60cf8a784dRomain Guy            if (opts != null) tempStorage = opts.inTempStorage;
516207b3ab604bcbe47fa55f26f358cde60cf8a784dRomain Guy            if (tempStorage == null) tempStorage = new byte[16 * 1024];
5177b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
5187b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            if (opts == null || (opts.inScaled && opts.inBitmap == null)) {
5197b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                float scale = 1.0f;
5207b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                int targetDensity = 0;
5217b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                if (opts != null) {
5227b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                    final int density = opts.inDensity;
5237b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                    targetDensity = opts.inTargetDensity;
5247b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                    if (density != 0 && targetDensity != 0) {
5257b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                        scale = targetDensity / (float) density;
5267b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                    }
5277b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                }
5287b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
5297b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                bm = nativeDecodeStream(is, tempStorage, outPadding, opts, true, scale);
5307b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                if (bm != null && targetDensity != 0) bm.setDensity(targetDensity);
5317b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
5327b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                finish = false;
5337b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            } else {
5347b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                bm = nativeDecodeStream(is, tempStorage, outPadding, opts);
5357b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            }
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5377b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
538decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase        if (bm == null && opts != null && opts.inBitmap != null) {
539decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase            throw new IllegalArgumentException("Problem decoding into existing bitmap");
540decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase        }
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5427b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        return finish ? finishDecode(bm, outPadding, opts) : bm;
5437341d7a104b47996445d069a695e155a07184606Dianne Hackborn    }
5447341d7a104b47996445d069a695e155a07184606Dianne Hackborn
5457341d7a104b47996445d069a695e155a07184606Dianne Hackborn    private static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) {
54611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        if (bm == null || opts == null) {
54711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            return bm;
54811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        }
54911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
55011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        final int density = opts.inDensity;
55111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        if (density == 0) {
55211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            return bm;
55311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        }
55411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
55511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        bm.setDensity(density);
55611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        final int targetDensity = opts.inTargetDensity;
557207b3ab604bcbe47fa55f26f358cde60cf8a784dRomain Guy        if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {
55811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            return bm;
55911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        }
56011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        byte[] np = bm.getNinePatchChunk();
56176344241719384f160ee623554f66987d0fcae41Dianne Hackborn        int[] lb = bm.getLayoutBounds();
56211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
56311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        if (opts.inScaled || isNinePatch) {
5644e525a6e5ac7499f79f306e0a418f6f6b72c765dRomain Guy            float scale = targetDensity / (float) density;
5654e525a6e5ac7499f79f306e0a418f6f6b72c765dRomain Guy            if (scale != 1.0f) {
5664e525a6e5ac7499f79f306e0a418f6f6b72c765dRomain Guy                final Bitmap oldBitmap = bm;
5674e525a6e5ac7499f79f306e0a418f6f6b72c765dRomain Guy                bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f),
5684e525a6e5ac7499f79f306e0a418f6f6b72c765dRomain Guy                        (int) (bm.getHeight() * scale + 0.5f), true);
5694e525a6e5ac7499f79f306e0a418f6f6b72c765dRomain Guy                if (bm != oldBitmap) oldBitmap.recycle();
57011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
5717b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                if (isNinePatch) {
5727b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                    np = nativeScaleNinePatch(np, scale, outPadding);
5737b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                    bm.setNinePatchChunk(np);
5747b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                }
57576344241719384f160ee623554f66987d0fcae41Dianne Hackborn                if (lb != null) {
57676344241719384f160ee623554f66987d0fcae41Dianne Hackborn                    int[] newLb = new int[lb.length];
57776344241719384f160ee623554f66987d0fcae41Dianne Hackborn                    for (int i=0; i<lb.length; i++) {
57876344241719384f160ee623554f66987d0fcae41Dianne Hackborn                        newLb[i] = (int)((lb[i]*scale)+.5f);
57976344241719384f160ee623554f66987d0fcae41Dianne Hackborn                    }
58076344241719384f160ee623554f66987d0fcae41Dianne Hackborn                    bm.setLayoutBounds(newLb);
58176344241719384f160ee623554f66987d0fcae41Dianne Hackborn                }
58211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            }
5837b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
58411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            bm.setDensity(targetDensity);
58511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        }
5862361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return bm;
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5897341d7a104b47996445d069a695e155a07184606Dianne Hackborn
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Decode an input stream into a bitmap. If the input stream is null, or
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cannot be used to decode a bitmap, the function returns null.
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The stream's position will be where ever it was after the encoded data
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * was read.
595eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen     *
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param is The input stream that holds the raw data to be decoded into a
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *           bitmap.
59803f0292744094ec107ffce71301c394503a31dedGilles Debunne     * @return The decoded bitmap, or null if the image data could not be decoded.
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap decodeStream(InputStream is) {
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return decodeStream(is, null, null);
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Decode a bitmap from the file descriptor. If the bitmap cannot be decoded
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * return null. The position within the descriptor will not be changed when
6077341d7a104b47996445d069a695e155a07184606Dianne Hackborn     * this returns, so the descriptor can be used again as-is.
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param fd The file descriptor containing the bitmap data to decode
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param outPadding If not null, return the padding rect for the bitmap if
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                   it exists, otherwise set padding to [-1,-1,-1,-1]. If
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                   no bitmap is returned (null) then padding is
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                   unchanged.
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param opts null-ok; Options that control downsampling and whether the
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *             image should be completely decoded, or just is size returned.
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the decoded bitmap, or null
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {
619a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin        if (nativeIsSeekable(fd)) {
620a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin            Bitmap bm = nativeDecodeFileDescriptor(fd, outPadding, opts);
621a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin            if (bm == null && opts != null && opts.inBitmap != null) {
622a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin                throw new IllegalArgumentException("Problem decoding into existing bitmap");
623a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin            }
624a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin            return finishDecode(bm, outPadding, opts);
625a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin        } else {
626a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin            FileInputStream fis = new FileInputStream(fd);
627a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin            try {
628a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin                return decodeStream(fis, outPadding, opts);
629a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin            } finally {
630a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin                try {
631a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin                    fis.close();
632a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin                } catch (Throwable t) {/* ignore */}
633a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin            }
634decc8cd41eca3770c8f5ee13d81b9cd5f0c25ccdChet Haase        }
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
636eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Decode a bitmap from the file descriptor. If the bitmap cannot be decoded
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * return null. The position within the descriptor will not be changed when
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this returns, so the descriptor can be used again as is.
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param fd The file descriptor containing the bitmap data to decode
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the decoded bitmap, or null
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap decodeFileDescriptor(FileDescriptor fd) {
646984b5df3830fe26a45bee39c7e8dd86714c99ed0Marco Nelissen        return decodeFileDescriptor(fd, null, null);
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
648eb949674fd3b83b706f795fc6b16ab1c66250c93Wei-Ta Chen
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Rect padding, Options opts);
6517b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy    private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
6527b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            Rect padding, Options opts, boolean applyScale, float scale);
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Rect padding, Options opts);
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts);
6567b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy    private static native Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts,
6577b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            boolean applyScale, float scale);
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native Bitmap nativeDecodeByteArray(byte[] data, int offset,
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int length, Options opts);
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad);
661a9d0d47076ecf2d1739bb3534abc9deead8ebebdOwen Lin    private static native boolean nativeIsSeekable(FileDescriptor fd);
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
663