• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.graphics;
18 
19 import android.content.res.AssetManager;
20 import android.content.res.Resources;
21 import android.util.DisplayMetrics;
22 import android.util.Log;
23 import android.util.TypedValue;
24 
25 import java.io.BufferedInputStream;
26 import java.io.FileDescriptor;
27 import java.io.FileInputStream;
28 import java.io.IOException;
29 import java.io.InputStream;
30 
31 /**
32  * Creates Bitmap objects from various sources, including files, streams,
33  * and byte-arrays.
34  */
35 public class BitmapFactory {
36     private static final int DECODE_BUFFER_SIZE = 16 * 1024;
37 
38     public static class Options {
39         /**
40          * Create a default Options object, which if left unchanged will give
41          * the same result from the decoder as if null were passed.
42          */
Options()43         public Options() {
44             inDither = false;
45             inScaled = true;
46         }
47 
48         /**
49          * If set, decode methods that take the Options object will attempt to
50          * reuse this bitmap when loading content. If the decode operation cannot
51          * use this bitmap, the decode method will return <code>null</code> and
52          * will throw an IllegalArgumentException. The
53          * current implementation necessitates that the reused bitmap be of the
54          * same size as the source content and in jpeg or png format (whether as a
55          * resource or as a stream). The {@link android.graphics.Bitmap.Config
56          * configuration} of the reused bitmap will override the setting of
57          * {@link #inPreferredConfig}, if set.
58          *
59          * <p>You should still always use the returned Bitmap of the decode
60          * method and not assume that reusing the bitmap worked, due to the
61          * constraints outlined above and failure situations that can occur.
62          * Checking whether the return value matches the value of the inBitmap
63          * set in the Options structure is a way to see if the bitmap was reused,
64          * but in all cases you should use the returned Bitmap to make sure
65          * that you are using the bitmap that was used as the decode destination.</p>
66          */
67         public Bitmap inBitmap;
68 
69         /**
70          * If set, decode methods will always return a mutable Bitmap instead of
71          * an immutable one. This can be used for instance to programmatically apply
72          * effects to a Bitmap loaded through BitmapFactory.
73          */
74         @SuppressWarnings({"UnusedDeclaration"}) // used in native code
75         public boolean inMutable;
76 
77         /**
78          * If set to true, the decoder will return null (no bitmap), but
79          * the out... fields will still be set, allowing the caller to query
80          * the bitmap without having to allocate the memory for its pixels.
81          */
82         public boolean inJustDecodeBounds;
83 
84         /**
85          * If set to a value > 1, requests the decoder to subsample the original
86          * image, returning a smaller image to save memory. The sample size is
87          * the number of pixels in either dimension that correspond to a single
88          * pixel in the decoded bitmap. For example, inSampleSize == 4 returns
89          * an image that is 1/4 the width/height of the original, and 1/16 the
90          * number of pixels. Any value <= 1 is treated the same as 1. Note: the
91          * decoder will try to fulfill this request, but the resulting bitmap
92          * may have different dimensions that precisely what has been requested.
93          * Also, powers of 2 are often faster/easier for the decoder to honor.
94          */
95         public int inSampleSize;
96 
97         /**
98          * If this is non-null, the decoder will try to decode into this
99          * internal configuration. If it is null, or the request cannot be met,
100          * the decoder will try to pick the best matching config based on the
101          * system's screen depth, and characteristics of the original image such
102          * as if it has per-pixel alpha (requiring a config that also does).
103          *
104          * Image are loaded with the {@link Bitmap.Config#ARGB_8888} config by
105          * default.
106          */
107         public Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888;
108 
109         /**
110          * If dither is true, the decoder will attempt to dither the decoded
111          * image.
112          */
113         public boolean inDither;
114 
115         /**
116          * The pixel density to use for the bitmap.  This will always result
117          * in the returned bitmap having a density set for it (see
118          * {@link Bitmap#setDensity(int) Bitmap.setDensity(int)}).  In addition,
119          * if {@link #inScaled} is set (which it is by default} and this
120          * density does not match {@link #inTargetDensity}, then the bitmap
121          * will be scaled to the target density before being returned.
122          *
123          * <p>If this is 0,
124          * {@link BitmapFactory#decodeResource(Resources, int)},
125          * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},
126          * and {@link BitmapFactory#decodeResourceStream}
127          * will fill in the density associated with the resource.  The other
128          * functions will leave it as-is and no density will be applied.
129          *
130          * @see #inTargetDensity
131          * @see #inScreenDensity
132          * @see #inScaled
133          * @see Bitmap#setDensity(int)
134          * @see android.util.DisplayMetrics#densityDpi
135          */
136         public int inDensity;
137 
138         /**
139          * The pixel density of the destination this bitmap will be drawn to.
140          * This is used in conjunction with {@link #inDensity} and
141          * {@link #inScaled} to determine if and how to scale the bitmap before
142          * returning it.
143          *
144          * <p>If this is 0,
145          * {@link BitmapFactory#decodeResource(Resources, int)},
146          * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},
147          * and {@link BitmapFactory#decodeResourceStream}
148          * will fill in the density associated the Resources object's
149          * DisplayMetrics.  The other
150          * functions will leave it as-is and no scaling for density will be
151          * performed.
152          *
153          * @see #inDensity
154          * @see #inScreenDensity
155          * @see #inScaled
156          * @see android.util.DisplayMetrics#densityDpi
157          */
158         public int inTargetDensity;
159 
160         /**
161          * The pixel density of the actual screen that is being used.  This is
162          * purely for applications running in density compatibility code, where
163          * {@link #inTargetDensity} is actually the density the application
164          * sees rather than the real screen density.
165          *
166          * <p>By setting this, you
167          * allow the loading code to avoid scaling a bitmap that is currently
168          * in the screen density up/down to the compatibility density.  Instead,
169          * if {@link #inDensity} is the same as {@link #inScreenDensity}, the
170          * bitmap will be left as-is.  Anything using the resulting bitmap
171          * must also used {@link Bitmap#getScaledWidth(int)
172          * Bitmap.getScaledWidth} and {@link Bitmap#getScaledHeight
173          * Bitmap.getScaledHeight} to account for any different between the
174          * bitmap's density and the target's density.
175          *
176          * <p>This is never set automatically for the caller by
177          * {@link BitmapFactory} itself.  It must be explicitly set, since the
178          * caller must deal with the resulting bitmap in a density-aware way.
179          *
180          * @see #inDensity
181          * @see #inTargetDensity
182          * @see #inScaled
183          * @see android.util.DisplayMetrics#densityDpi
184          */
185         public int inScreenDensity;
186 
187         /**
188          * When this flag is set, if {@link #inDensity} and
189          * {@link #inTargetDensity} are not 0, the
190          * bitmap will be scaled to match {@link #inTargetDensity} when loaded,
191          * rather than relying on the graphics system scaling it each time it
192          * is drawn to a Canvas.
193          *
194          * <p>This flag is turned on by default and should be turned off if you need
195          * a non-scaled version of the bitmap.  Nine-patch bitmaps ignore this
196          * flag and are always scaled.
197          */
198         public boolean inScaled;
199 
200         /**
201          * If this is set to true, then the resulting bitmap will allocate its
202          * pixels such that they can be purged if the system needs to reclaim
203          * memory. In that instance, when the pixels need to be accessed again
204          * (e.g. the bitmap is drawn, getPixels() is called), they will be
205          * automatically re-decoded.
206          *
207          * For the re-decode to happen, the bitmap must have access to the
208          * encoded data, either by sharing a reference to the input
209          * or by making a copy of it. This distinction is controlled by
210          * inInputShareable. If this is true, then the bitmap may keep a shallow
211          * reference to the input. If this is false, then the bitmap will
212          * explicitly make a copy of the input data, and keep that. Even if
213          * sharing is allowed, the implementation may still decide to make a
214          * deep copy of the input data.
215          */
216         public boolean inPurgeable;
217 
218         /**
219          * This field works in conjuction with inPurgeable. If inPurgeable is
220          * false, then this field is ignored. If inPurgeable is true, then this
221          * field determines whether the bitmap can share a reference to the
222          * input data (inputstream, array, etc.) or if it must make a deep copy.
223          */
224         public boolean inInputShareable;
225 
226         /**
227          * If inPreferQualityOverSpeed is set to true, the decoder will try to
228          * decode the reconstructed image to a higher quality even at the
229          * expense of the decoding speed. Currently the field only affects JPEG
230          * decode, in the case of which a more accurate, but slightly slower,
231          * IDCT method will be used instead.
232          */
233         public boolean inPreferQualityOverSpeed;
234 
235         /**
236          * The resulting width of the bitmap, set independent of the state of
237          * inJustDecodeBounds. However, if there is an error trying to decode,
238          * outWidth will be set to -1.
239          */
240 
241         public int outWidth;
242 
243         /**
244          * The resulting height of the bitmap, set independent of the state of
245          * inJustDecodeBounds. However, if there is an error trying to decode,
246          * outHeight will be set to -1.
247          */
248         public int outHeight;
249 
250         /**
251          * If known, this string is set to the mimetype of the decoded image.
252          * If not know, or there is an error, it is set to null.
253          */
254         public String outMimeType;
255 
256         /**
257          * Temp storage to use for decoding.  Suggest 16K or so.
258          */
259         public byte[] inTempStorage;
260 
requestCancel()261         private native void requestCancel();
262 
263         /**
264          * Flag to indicate that cancel has been called on this object.  This
265          * is useful if there's an intermediary that wants to first decode the
266          * bounds and then decode the image.  In that case the intermediary
267          * can check, inbetween the bounds decode and the image decode, to see
268          * if the operation is canceled.
269          */
270         public boolean mCancel;
271 
272         /**
273          *  This can be called from another thread while this options object is
274          *  inside a decode... call. Calling this will notify the decoder that
275          *  it should cancel its operation. This is not guaranteed to cancel
276          *  the decode, but if it does, the decoder... operation will return
277          *  null, or if inJustDecodeBounds is true, will set outWidth/outHeight
278          *  to -1
279          */
requestCancelDecode()280         public void requestCancelDecode() {
281             mCancel = true;
282             requestCancel();
283         }
284     }
285 
286     /**
287      * Decode a file path into a bitmap. If the specified file name is null,
288      * or cannot be decoded into a bitmap, the function returns null.
289      *
290      * @param pathName complete path name for the file to be decoded.
291      * @param opts null-ok; Options that control downsampling and whether the
292      *             image should be completely decoded, or just is size returned.
293      * @return The decoded bitmap, or null if the image data could not be
294      *         decoded, or, if opts is non-null, if opts requested only the
295      *         size be returned (in opts.outWidth and opts.outHeight)
296      */
decodeFile(String pathName, Options opts)297     public static Bitmap decodeFile(String pathName, Options opts) {
298         Bitmap bm = null;
299         InputStream stream = null;
300         try {
301             stream = new FileInputStream(pathName);
302             bm = decodeStream(stream, null, opts);
303         } catch (Exception e) {
304             /*  do nothing.
305                 If the exception happened on open, bm will be null.
306             */
307             Log.e("BitmapFactory", "Unable to decode stream: " + e);
308         } finally {
309             if (stream != null) {
310                 try {
311                     stream.close();
312                 } catch (IOException e) {
313                     // do nothing here
314                 }
315             }
316         }
317         return bm;
318     }
319 
320     /**
321      * Decode a file path into a bitmap. If the specified file name is null,
322      * or cannot be decoded into a bitmap, the function returns null.
323      *
324      * @param pathName complete path name for the file to be decoded.
325      * @return the resulting decoded bitmap, or null if it could not be decoded.
326      */
decodeFile(String pathName)327     public static Bitmap decodeFile(String pathName) {
328         return decodeFile(pathName, null);
329     }
330 
331     /**
332      * Decode a new Bitmap from an InputStream. This InputStream was obtained from
333      * resources, which we pass to be able to scale the bitmap accordingly.
334      */
decodeResourceStream(Resources res, TypedValue value, InputStream is, Rect pad, Options opts)335     public static Bitmap decodeResourceStream(Resources res, TypedValue value,
336             InputStream is, Rect pad, Options opts) {
337 
338         if (opts == null) {
339             opts = new Options();
340         }
341 
342         if (opts.inDensity == 0 && value != null) {
343             final int density = value.density;
344             if (density == TypedValue.DENSITY_DEFAULT) {
345                 opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
346             } else if (density != TypedValue.DENSITY_NONE) {
347                 opts.inDensity = density;
348             }
349         }
350 
351         if (opts.inTargetDensity == 0 && res != null) {
352             opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
353         }
354 
355         return decodeStream(is, pad, opts);
356     }
357 
358     /**
359      * Synonym for opening the given resource and calling
360      * {@link #decodeResourceStream}.
361      *
362      * @param res   The resources object containing the image data
363      * @param id The resource id of the image data
364      * @param opts null-ok; Options that control downsampling and whether the
365      *             image should be completely decoded, or just is size returned.
366      * @return The decoded bitmap, or null if the image data could not be
367      *         decoded, or, if opts is non-null, if opts requested only the
368      *         size be returned (in opts.outWidth and opts.outHeight)
369      */
decodeResource(Resources res, int id, Options opts)370     public static Bitmap decodeResource(Resources res, int id, Options opts) {
371         Bitmap bm = null;
372         InputStream is = null;
373 
374         try {
375             final TypedValue value = new TypedValue();
376             is = res.openRawResource(id, value);
377 
378             bm = decodeResourceStream(res, value, is, null, opts);
379         } catch (Exception e) {
380             /*  do nothing.
381                 If the exception happened on open, bm will be null.
382                 If it happened on close, bm is still valid.
383             */
384         } finally {
385             try {
386                 if (is != null) is.close();
387             } catch (IOException e) {
388                 // Ignore
389             }
390         }
391 
392         if (bm == null && opts != null && opts.inBitmap != null) {
393             throw new IllegalArgumentException("Problem decoding into existing bitmap");
394         }
395 
396         return bm;
397     }
398 
399     /**
400      * Synonym for {@link #decodeResource(Resources, int, android.graphics.BitmapFactory.Options)}
401      * will null Options.
402      *
403      * @param res The resources object containing the image data
404      * @param id The resource id of the image data
405      * @return The decoded bitmap, or null if the image could not be decode.
406      */
decodeResource(Resources res, int id)407     public static Bitmap decodeResource(Resources res, int id) {
408         return decodeResource(res, id, null);
409     }
410 
411     /**
412      * Decode an immutable bitmap from the specified byte array.
413      *
414      * @param data byte array of compressed image data
415      * @param offset offset into imageData for where the decoder should begin
416      *               parsing.
417      * @param length the number of bytes, beginning at offset, to parse
418      * @param opts null-ok; Options that control downsampling and whether the
419      *             image should be completely decoded, or just is size returned.
420      * @return The decoded bitmap, or null if the image data could not be
421      *         decoded, or, if opts is non-null, if opts requested only the
422      *         size be returned (in opts.outWidth and opts.outHeight)
423      */
decodeByteArray(byte[] data, int offset, int length, Options opts)424     public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {
425         if ((offset | length) < 0 || data.length < offset + length) {
426             throw new ArrayIndexOutOfBoundsException();
427         }
428         Bitmap bm = nativeDecodeByteArray(data, offset, length, opts);
429 
430         if (bm == null && opts != null && opts.inBitmap != null) {
431             throw new IllegalArgumentException("Problem decoding into existing bitmap");
432         }
433         return bm;
434     }
435 
436     /**
437      * Decode an immutable bitmap from the specified byte array.
438      *
439      * @param data byte array of compressed image data
440      * @param offset offset into imageData for where the decoder should begin
441      *               parsing.
442      * @param length the number of bytes, beginning at offset, to parse
443      * @return The decoded bitmap, or null if the image could not be decode.
444      */
decodeByteArray(byte[] data, int offset, int length)445     public static Bitmap decodeByteArray(byte[] data, int offset, int length) {
446         return decodeByteArray(data, offset, length, null);
447     }
448 
449     /**
450      * Decode an input stream into a bitmap. If the input stream is null, or
451      * cannot be used to decode a bitmap, the function returns null.
452      * The stream's position will be where ever it was after the encoded data
453      * was read.
454      *
455      * @param is The input stream that holds the raw data to be decoded into a
456      *           bitmap.
457      * @param outPadding If not null, return the padding rect for the bitmap if
458      *                   it exists, otherwise set padding to [-1,-1,-1,-1]. If
459      *                   no bitmap is returned (null) then padding is
460      *                   unchanged.
461      * @param opts null-ok; Options that control downsampling and whether the
462      *             image should be completely decoded, or just is size returned.
463      * @return The decoded bitmap, or null if the image data could not be
464      *         decoded, or, if opts is non-null, if opts requested only the
465      *         size be returned (in opts.outWidth and opts.outHeight)
466      */
decodeStream(InputStream is, Rect outPadding, Options opts)467     public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
468         // we don't throw in this case, thus allowing the caller to only check
469         // the cache, and not force the image to be decoded.
470         if (is == null) {
471             return null;
472         }
473 
474         // we need mark/reset to work properly
475 
476         if (!is.markSupported()) {
477             is = new BufferedInputStream(is, DECODE_BUFFER_SIZE);
478         }
479 
480         // so we can call reset() if a given codec gives up after reading up to
481         // this many bytes. FIXME: need to find out from the codecs what this
482         // value should be.
483         is.mark(1024);
484 
485         Bitmap bm;
486         boolean finish = true;
487 
488         if (is instanceof AssetManager.AssetInputStream) {
489             final int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
490 
491             if (opts == null || (opts.inScaled && opts.inBitmap == null)) {
492                 float scale = 1.0f;
493                 int targetDensity = 0;
494                 if (opts != null) {
495                     final int density = opts.inDensity;
496                     targetDensity = opts.inTargetDensity;
497                     if (density != 0 && targetDensity != 0) {
498                         scale = targetDensity / (float) density;
499                     }
500                 }
501 
502                 bm = nativeDecodeAsset(asset, outPadding, opts, true, scale);
503                 if (bm != null && targetDensity != 0) bm.setDensity(targetDensity);
504 
505                 finish = false;
506             } else {
507                 bm = nativeDecodeAsset(asset, outPadding, opts);
508             }
509         } else {
510             // pass some temp storage down to the native code. 1024 is made up,
511             // but should be large enough to avoid too many small calls back
512             // into is.read(...) This number is not related to the value passed
513             // to mark(...) above.
514             byte [] tempStorage = null;
515             if (opts != null) tempStorage = opts.inTempStorage;
516             if (tempStorage == null) tempStorage = new byte[16 * 1024];
517 
518             if (opts == null || (opts.inScaled && opts.inBitmap == null)) {
519                 float scale = 1.0f;
520                 int targetDensity = 0;
521                 if (opts != null) {
522                     final int density = opts.inDensity;
523                     targetDensity = opts.inTargetDensity;
524                     if (density != 0 && targetDensity != 0) {
525                         scale = targetDensity / (float) density;
526                     }
527                 }
528 
529                 bm = nativeDecodeStream(is, tempStorage, outPadding, opts, true, scale);
530                 if (bm != null && targetDensity != 0) bm.setDensity(targetDensity);
531 
532                 finish = false;
533             } else {
534                 bm = nativeDecodeStream(is, tempStorage, outPadding, opts);
535             }
536         }
537 
538         if (bm == null && opts != null && opts.inBitmap != null) {
539             throw new IllegalArgumentException("Problem decoding into existing bitmap");
540         }
541 
542         return finish ? finishDecode(bm, outPadding, opts) : bm;
543     }
544 
finishDecode(Bitmap bm, Rect outPadding, Options opts)545     private static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) {
546         if (bm == null || opts == null) {
547             return bm;
548         }
549 
550         final int density = opts.inDensity;
551         if (density == 0) {
552             return bm;
553         }
554 
555         bm.setDensity(density);
556         final int targetDensity = opts.inTargetDensity;
557         if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {
558             return bm;
559         }
560         byte[] np = bm.getNinePatchChunk();
561         int[] lb = bm.getLayoutBounds();
562         final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
563         if (opts.inScaled || isNinePatch) {
564             float scale = targetDensity / (float) density;
565             if (scale != 1.0f) {
566                 final Bitmap oldBitmap = bm;
567                 bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f),
568                         (int) (bm.getHeight() * scale + 0.5f), true);
569                 if (bm != oldBitmap) oldBitmap.recycle();
570 
571                 if (isNinePatch) {
572                     np = nativeScaleNinePatch(np, scale, outPadding);
573                     bm.setNinePatchChunk(np);
574                 }
575                 if (lb != null) {
576                     int[] newLb = new int[lb.length];
577                     for (int i=0; i<lb.length; i++) {
578                         newLb[i] = (int)((lb[i]*scale)+.5f);
579                     }
580                     bm.setLayoutBounds(newLb);
581                 }
582             }
583 
584             bm.setDensity(targetDensity);
585         }
586 
587         return bm;
588     }
589 
590     /**
591      * Decode an input stream into a bitmap. If the input stream is null, or
592      * cannot be used to decode a bitmap, the function returns null.
593      * The stream's position will be where ever it was after the encoded data
594      * was read.
595      *
596      * @param is The input stream that holds the raw data to be decoded into a
597      *           bitmap.
598      * @return The decoded bitmap, or null if the image data could not be decoded.
599      */
decodeStream(InputStream is)600     public static Bitmap decodeStream(InputStream is) {
601         return decodeStream(is, null, null);
602     }
603 
604     /**
605      * Decode a bitmap from the file descriptor. If the bitmap cannot be decoded
606      * return null. The position within the descriptor will not be changed when
607      * this returns, so the descriptor can be used again as-is.
608      *
609      * @param fd The file descriptor containing the bitmap data to decode
610      * @param outPadding If not null, return the padding rect for the bitmap if
611      *                   it exists, otherwise set padding to [-1,-1,-1,-1]. If
612      *                   no bitmap is returned (null) then padding is
613      *                   unchanged.
614      * @param opts null-ok; Options that control downsampling and whether the
615      *             image should be completely decoded, or just is size returned.
616      * @return the decoded bitmap, or null
617      */
decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts)618     public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {
619         if (nativeIsSeekable(fd)) {
620             Bitmap bm = nativeDecodeFileDescriptor(fd, outPadding, opts);
621             if (bm == null && opts != null && opts.inBitmap != null) {
622                 throw new IllegalArgumentException("Problem decoding into existing bitmap");
623             }
624             return finishDecode(bm, outPadding, opts);
625         } else {
626             FileInputStream fis = new FileInputStream(fd);
627             try {
628                 return decodeStream(fis, outPadding, opts);
629             } finally {
630                 try {
631                     fis.close();
632                 } catch (Throwable t) {/* ignore */}
633             }
634         }
635     }
636 
637     /**
638      * Decode a bitmap from the file descriptor. If the bitmap cannot be decoded
639      * return null. The position within the descriptor will not be changed when
640      * this returns, so the descriptor can be used again as is.
641      *
642      * @param fd The file descriptor containing the bitmap data to decode
643      * @return the decoded bitmap, or null
644      */
decodeFileDescriptor(FileDescriptor fd)645     public static Bitmap decodeFileDescriptor(FileDescriptor fd) {
646         return decodeFileDescriptor(fd, null, null);
647     }
648 
nativeDecodeStream(InputStream is, byte[] storage, Rect padding, Options opts)649     private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
650             Rect padding, Options opts);
nativeDecodeStream(InputStream is, byte[] storage, Rect padding, Options opts, boolean applyScale, float scale)651     private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
652             Rect padding, Options opts, boolean applyScale, float scale);
nativeDecodeFileDescriptor(FileDescriptor fd, Rect padding, Options opts)653     private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
654             Rect padding, Options opts);
nativeDecodeAsset(int asset, Rect padding, Options opts)655     private static native Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts);
nativeDecodeAsset(int asset, Rect padding, Options opts, boolean applyScale, float scale)656     private static native Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts,
657             boolean applyScale, float scale);
nativeDecodeByteArray(byte[] data, int offset, int length, Options opts)658     private static native Bitmap nativeDecodeByteArray(byte[] data, int offset,
659             int length, Options opts);
nativeScaleNinePatch(byte[] chunk, float scale, Rect pad)660     private static native byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad);
nativeIsSeekable(FileDescriptor fd)661     private static native boolean nativeIsSeekable(FileDescriptor fd);
662 }
663