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