OSDN Git Service

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