Android 从源码分析Bitmap和BitmapFactory常用API

来源:互联网 发布:鲍尔州立大学 知乎 编辑:程序博客网 时间:2024/06/14 01:36

Bitmap

recycle()

调用nativeRecycle()释放该bitmap分配的native对象,清除对像素数据的引用。不会同步的释放像素数据,只是简单的允许bitmap在没有其他引用时被垃圾回收。此bitmap被标记为dead,意味着调用getPixels()或者setPixels()将会抛出异常,而且不会绘制。此操作不能回退,所以最好在bitmap不会用到时调用。这是一个高级调用,通常不应该调用,因为通常情况下如果此bitmap没有被引用,垃圾回收进程会释放占用的内存空间。

    /**     * Free the native object associated with this bitmap, and clear the     * reference to the pixel data. This will not free the pixel data synchronously;     * it simply allows it to be garbage collected if there are no other references.     * The bitmap is marked as "dead", meaning it will throw an exception if     * getPixels() or setPixels() is called, and will draw nothing. This operation     * cannot be reversed, so it should only be called if you are sure there are no     * further uses for the bitmap. This is an advanced call, and normally need     * not be called, since the normal GC process will free up this memory when     * there are no more references to this bitmap.     */     public void recycle() {        if (!mRecycled && mNativePtr != 0) {            if (nativeRecycle(mNativePtr)) {                // return value indicates whether native pixel object was actually recycled.                // false indicates that it is still in use at the native level and these                // objects should not be collected now. They will be collected later when the                // Bitmap itself is collected.                mBuffer = null;                mNinePatchChunk = null;            }            mRecycled = true;        }    }

isRecycled()

判断位图内存是否已经被回收。

checkRecycled

如果已经被回收,则抛出非法状态异常IllegalStateException。

    /**     * This is called by methods that want to throw an exception if the bitmap     * has already been recycled.     */    private void checkRecycled(String errorMessage) {        if (mRecycled) {            throw new IllegalStateException(errorMessage);        }    }

getWidth() 获取宽度

getHeight() 获取高度

getScaledWidth(Canvas canvas)

获取经指定密度转换后的宽度

/**     * Convenience for calling {@link #getScaledWidth(int)} with the target     * density of the given {@link Canvas}.     */    public int getScaledWidth(Canvas canvas) {        return scaleFromDensity(getWidth(), mDensity, canvas.mDensity);    }    /**     * Convenience for calling {@link #getScaledWidth(int)} with the target     * density of the given {@link DisplayMetrics}.     */    public int getScaledWidth(DisplayMetrics metrics) {        return scaleFromDensity(getWidth(), mDensity, metrics.densityDpi);    }    /**     * @hide     */    static public int scaleFromDensity(int size, int sdensity, int tdensity) {        if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {            return size;        }        // Scale by tdensity / sdensity, rounding up.        return ((size * tdensity) + (sdensity >> 1)) / sdensity;    }

getScaledHeight(Canvas canvas)

获取经制定密度转换后的高度

    /**     * Convenience for calling {@link #getScaledHeight(int)} with the target     * density of the given {@link Canvas}.     */    public int getScaledHeight(Canvas canvas) {        return scaleFromDensity(getHeight(), mDensity, canvas.mDensity);    }    /**     * Convenience for calling {@link #getScaledHeight(int)} with the target     * density of the given {@link DisplayMetrics}.     */    public int getScaledHeight(DisplayMetrics metrics) {        return scaleFromDensity(getHeight(), mDensity, metrics.densityDpi);    }

getRowBytes()

获取native位图行像素的byte数

    /**     * Return the number of bytes between rows in the bitmap's pixels. Note that     * this refers to the pixels as stored natively by the bitmap. If you call     * getPixels() or setPixels(), then the pixels are uniformly treated as     * 32bit values, packed according to the Color class.     *     * <p>As of {@link android.os.Build.VERSION_CODES#KITKAT}, this method     * should not be used to calculate the memory usage of the bitmap. Instead,     * see {@link #getAllocationByteCount()}.     *     * @return number of bytes between rows of the native bitmap pixels.     */    public final int getRowBytes() {        if (mRecycled) {            Log.w(TAG, "Called getRowBytes() on a recycle()'d bitmap! This is undefined behavior!");        }        return nativeRowBytes(mNativePtr);    }

getByteCount()

获取可以存储此bitmap像素的最小字节。返回行像素x高度。

    /**     * Returns the minimum number of bytes that can be used to store this bitmap's pixels.     *     * <p>As of {@link android.os.Build.VERSION_CODES#KITKAT}, the result of this method can     * no longer be used to determine memory usage of a bitmap. See {@link     * #getAllocationByteCount()}.</p>     */    public final int getByteCount() {        // int result permits bitmaps up to 46,340 x 46,340        return getRowBytes() * getHeight();    }

getAllocationByteCount()

获取用来存储bitmap所分配的内存大小。在bitmap的生命周期内此值不会改变。

    /**     * Returns the size of the allocated memory used to store this bitmap's pixels.     *     * <p>This can be larger than the result of {@link #getByteCount()} if a bitmap is reused to     * decode other bitmaps of smaller size, or by manual reconfiguration. See {@link     * #reconfigure(int, int, Config)}, {@link #setWidth(int)}, {@link #setHeight(int)}, {@link     * #setConfig(Bitmap.Config)}, and {@link BitmapFactory.Options#inBitmap     * BitmapFactory.Options.inBitmap}. If a bitmap is not modified in this way, this value will be     * the same as that returned by {@link #getByteCount()}.</p>     *     * <p>This value will not change over the lifetime of a Bitmap.</p>     *     * @see #reconfigure(int, int, Config)     */    public final int getAllocationByteCount() {        if (mBuffer == null) {            // native backed bitmaps don't support reconfiguration,            // so alloc size is always content size            return getByteCount();        }        return mBuffer.length;    }

getConfig()

获取Config枚举:

  • ALPHA_8, 代表8位Alpha位图,每个像素占用1byte内存
  • RGB_565,代表8位RGB位图,每个像素占用2byte内存
  • ARGB_4444 (@deprecated),代表16位ARGB位图,每个像素占用2byte内存
  • ARGB_8888,代表32位ARGB位图,每个像素占用4byte内存
    /**     * If the bitmap's internal config is in one of the public formats, return     * that config, otherwise return null.     */    public final Config getConfig() {        if (mRecycled) {            Log.w(TAG, "Called getConfig() on a recycle()'d bitmap! This is undefined behavior!");        }        return Config.nativeToConfig(nativeConfig(mNativePtr));    }

hasAlpha()

检测bitmap是否支持像素级别透明。

    /** Returns true if the bitmap's config supports per-pixel alpha, and     * if the pixels may contain non-opaque alpha values. For some configs,     * this is always false (e.g. RGB_565), since they do not support per-pixel     * alpha. However, for configs that do, the bitmap may be flagged to be     * known that all of its pixels are opaque. In this case hasAlpha() will     * also return false. If a config such as ARGB_8888 is not so flagged,     * it will return true by default.     */    public final boolean hasAlpha() {        if (mRecycled) {            Log.w(TAG, "Called hasAlpha() on a recycle()'d bitmap! This is undefined behavior!");        }        return nativeHasAlpha(mNativePtr);    }

setHasAlpha(boolean hasAlpha)

设置bitmap是否支持像素级别透明

    /**     * Tell the bitmap if all of the pixels are known to be opaque (false)     * or if some of the pixels may contain non-opaque alpha values (true).     * Note, for some configs (e.g. RGB_565) this call is ignored, since it     * does not support per-pixel alpha values.     *     * This is meant as a drawing hint, as in some cases a bitmap that is known     * to be opaque can take a faster drawing case than one that may have     * non-opaque per-pixel alpha values.     */    public void setHasAlpha(boolean hasAlpha) {        checkRecycled("setHasAlpha called on a recycled bitmap");        nativeSetHasAlpha(mNativePtr, hasAlpha, mRequestPremultiplied);    }

eraseColor(@ColorInt int c)

用颜色值填充bitmap的像素。

    /**     * Fills the bitmap's pixels with the specified {@link Color}.     *     * @throws IllegalStateException if the bitmap is not mutable.     */    public void eraseColor(@ColorInt int c) {        checkRecycled("Can't erase a recycled bitmap");        if (!isMutable()) {            throw new IllegalStateException("cannot erase immutable bitmaps");        }        nativeErase(mNativePtr, c);    }

getPixel(int x, int y)

获取指定位置像素的颜色值。

    /**     * Returns the {@link Color} at the specified location. Throws an exception     * if x or y are out of bounds (negative or >= to the width or height     * respectively). The returned color is a non-premultiplied ARGB value.     *     * @param x    The x coordinate (0...width-1) of the pixel to return     * @param y    The y coordinate (0...height-1) of the pixel to return     * @return     The argb {@link Color} at the specified coordinate     * @throws IllegalArgumentException if x, y exceed the bitmap's bounds     */    @ColorInt    public int getPixel(int x, int y) {        checkRecycled("Can't call getPixel() on a recycled bitmap");        checkPixelAccess(x, y);        return nativeGetPixel(mNativePtr, x, y);    }

setPixel(int x, int y, @ColorInt int color)

设置指定位置像素的颜色值。

    /**     * <p>Write the specified {@link Color} into the bitmap (assuming it is     * mutable) at the x,y coordinate. The color must be a     * non-premultiplied ARGB value.</p>     *     * @param x     The x coordinate of the pixel to replace (0...width-1)     * @param y     The y coordinate of the pixel to replace (0...height-1)     * @param color The ARGB color to write into the bitmap     *     * @throws IllegalStateException if the bitmap is not mutable     * @throws IllegalArgumentException if x, y are outside of the bitmap's     *         bounds.     */    public void setPixel(int x, int y, @ColorInt int color) {        checkRecycled("Can't call setPixel() on a recycled bitmap");        if (!isMutable()) {            throw new IllegalStateException();        }        checkPixelAccess(x, y);        nativeSetPixel(mNativePtr, x, y, color);    }

writeToParcel(Parcel p, int flags)

打包bitmap

    /**     * Write the bitmap and its pixels to the parcel. The bitmap can be     * rebuilt from the parcel by calling CREATOR.createFromParcel().     * @param p    Parcel object to write the bitmap data into     */    public void writeToParcel(Parcel p, int flags) {        checkRecycled("Can't parcel a recycled bitmap");        if (!nativeWriteToParcel(mNativePtr, mIsMutable, mDensity, p)) {            throw new RuntimeException("native writeToParcel failed");        }    }

extractAlpha()

获取原bitmap的alpha通道数据最为新的bitmap。

    /**     * Returns a new bitmap that captures the alpha values of the original.     * This may be drawn with Canvas.drawBitmap(), where the color(s) will be     * taken from the paint that is passed to the draw call.     *     * @return new bitmap containing the alpha channel of the original bitmap.     */    @CheckResult    public Bitmap extractAlpha() {        return extractAlpha(null, null);    }

#

和另外一个bitmap比较二者是否相同。    /**     *  Given another bitmap, return true if it has the same dimensions, config,     *  and pixel data as this bitmap. If any of those differ, return false.     *  If other is null, return false.     */    public boolean sameAs(Bitmap other) {        checkRecycled("Can't call sameAs on a recycled bitmap!");        if (this == other) return true;        if (other == null) return false;        if (other.isRecycled()) {            throw new IllegalArgumentException("Can't compare to a recycled bitmap!");        }        return nativeSameAs(mNativePtr, other.mNativePtr);    }

prepareToDraw()

绘制准备:重建该bitmap相关联的缓存来绘制。在可清除的bitmap中,此方法会尝试确保像素已经被解码。

    /**     * Rebuilds any caches associated with the bitmap that are used for     * drawing it. In the case of purgeable bitmaps, this call will attempt to     * ensure that the pixels have been decoded.     * If this is called on more than one bitmap in sequence, the priority is     * given in LRU order (i.e. the last bitmap called will be given highest     * priority).     *     * For bitmaps with no associated caches, this call is effectively a no-op,     * and therefore is harmless.     */    public void prepareToDraw() {        checkRecycled("Can't prepareToDraw on a recycled bitmap!");        // Kick off an update/upload of the bitmap outside of the normal        // draw path.        nativePrepareToDraw(mNativePtr);    }

CompressFormat

bitmap压缩格式:JPEG,PNG,WEBP(谷歌推出的图片格式,小体积高质量,豆瓣电影的海报使用的此格式)

    /**     * Specifies the known formats a bitmap can be compressed into     */    public enum CompressFormat {        JPEG    (0),        PNG     (1),        WEBP    (2);        CompressFormat(int nativeInt) {            this.nativeInt = nativeInt;        }        final int nativeInt;    }

compress(CompressFormat format, int quality, OutputStream stream)

压缩bitmap。

    /**     * Write a compressed version of the bitmap to the specified outputstream.     * If this returns true, the bitmap can be reconstructed by passing a     * corresponding inputstream to BitmapFactory.decodeStream(). Note: not     * all Formats support all bitmap configs directly, so it is possible that     * the returned bitmap from BitmapFactory could be in a different bitdepth,     * and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque     * pixels).     *     * @param format   The format of the compressed image     * @param quality  Hint to the compressor, 0-100. 0 meaning compress for     *                 small size, 100 meaning compress for max quality. Some     *                 formats, like PNG which is lossless, will ignore the     *                 quality setting     * @param stream   The outputstream to write the compressed data.     * @return true if successfully compressed to the specified stream.     */    public boolean compress(CompressFormat format, int quality, OutputStream stream) {        checkRecycled("Can't compress a recycled bitmap");        // do explicit check before calling the native method        if (stream == null) {            throw new NullPointerException();        }        if (quality < 0 || quality > 100) {            throw new IllegalArgumentException("quality must be 0..100");        }        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "Bitmap.compress");        boolean result = nativeCompress(mNativePtr, format.nativeInt,                quality, stream, new byte[WORKING_COMPRESS_STORAGE]);        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);        return result;    }

BitmapFactory

inMutable

配置bitmap是否可修改

        /**         * If set, decode methods will always return a mutable Bitmap instead of         * an immutable one. This can be used for instance to programmatically apply         * effects to a Bitmap loaded through BitmapFactory.         */        @SuppressWarnings({"UnusedDeclaration"}) // used in native code        public boolean inMutable;

inJustDecodeBounds

如果设置为true,不获取图片,不分配内存,但会返回图片的高度宽度信息。

        /**         * If set to true, the decoder will return null (no bitmap), but         * the out... fields will still be set, allowing the caller to query         * the bitmap without having to allocate the memory for its pixels.         */        public boolean inJustDecodeBounds;

inSampleSize

图片缩放倍数

        /**         * If set to a value > 1, requests the decoder to subsample the original         * image, returning a smaller image to save memory. The sample size is         * the number of pixels in either dimension that correspond to a single         * pixel in the decoded bitmap. For example, inSampleSize == 4 returns         * an image that is 1/4 the width/height of the original, and 1/16 the         * number of pixels. Any value <= 1 is treated the same as 1. Note: the         * decoder uses a final value based on powers of 2, any other value will         * be rounded down to the nearest power of 2.         */        public int inSampleSize;

inDither, @deprecated

抖动解码

        /**         * @deprecated As of {@link android.os.Build.VERSION_CODES#N}, this is         * ignored.         *         * In {@link android.os.Build.VERSION_CODES#M} and below, if dither is         * true, the decoder will attempt to dither the decoded image.         */        public boolean inDither;

inDensity

用于位图的像素压缩比。

        /**         * The pixel density to use for the bitmap.  This will always result         * in the returned bitmap having a density set for it (see         * {@link Bitmap#setDensity(int) Bitmap.setDensity(int)}).  In addition,         * if {@link #inScaled} is set (which it is by default} and this         * density does not match {@link #inTargetDensity}, then the bitmap         * will be scaled to the target density before being returned.         *          * <p>If this is 0,         * {@link BitmapFactory#decodeResource(Resources, int)},          * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},         * and {@link BitmapFactory#decodeResourceStream}         * will fill in the density associated with the resource.  The other         * functions will leave it as-is and no density will be applied.         *         * @see #inTargetDensity         * @see #inScreenDensity         * @see #inScaled         * @see Bitmap#setDensity(int)         * @see android.util.DisplayMetrics#densityDpi         */        public int inDensity;

inTargetDensity

用于目标位图的像素压缩比(要生成的位图)

        /**         * The pixel density of the destination this bitmap will be drawn to.         * This is used in conjunction with {@link #inDensity} and         * {@link #inScaled} to determine if and how to scale the bitmap before         * returning it.         *          * <p>If this is 0,         * {@link BitmapFactory#decodeResource(Resources, int)},          * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},         * and {@link BitmapFactory#decodeResourceStream}         * will fill in the density associated the Resources object's         * DisplayMetrics.  The other         * functions will leave it as-is and no scaling for density will be         * performed.         *          * @see #inDensity         * @see #inScreenDensity         * @see #inScaled         * @see android.util.DisplayMetrics#densityDpi         */        public int inTargetDensity;

inScreenDensity

当前屏幕的像素密度

        /**         * The pixel density of the actual screen that is being used.  This is         * purely for applications running in density compatibility code, where         * {@link #inTargetDensity} is actually the density the application         * sees rather than the real screen density.         *          * <p>By setting this, you         * allow the loading code to avoid scaling a bitmap that is currently         * in the screen density up/down to the compatibility density.  Instead,         * if {@link #inDensity} is the same as {@link #inScreenDensity}, the         * bitmap will be left as-is.  Anything using the resulting bitmap         * must also used {@link Bitmap#getScaledWidth(int)         * Bitmap.getScaledWidth} and {@link Bitmap#getScaledHeight         * Bitmap.getScaledHeight} to account for any different between the         * bitmap's density and the target's density.         *          * <p>This is never set automatically for the caller by         * {@link BitmapFactory} itself.  It must be explicitly set, since the         * caller must deal with the resulting bitmap in a density-aware way.         *          * @see #inDensity         * @see #inTargetDensity         * @see #inScaled         * @see android.util.DisplayMetrics#densityDpi         */        public int inScreenDensity;

inScaled

设置为true时进行图片压缩,从inDensity到inTargetDensity

        /**         * When this flag is set, if {@link #inDensity} and         * {@link #inTargetDensity} are not 0, the         * bitmap will be scaled to match {@link #inTargetDensity} when loaded,         * rather than relying on the graphics system scaling it each time it         * is drawn to a Canvas.         *         * <p>BitmapRegionDecoder ignores this flag, and will not scale output         * based on density. (though {@link #inSampleSize} is supported)</p>         *         * <p>This flag is turned on by default and should be turned off if you need         * a non-scaled version of the bitmap.  Nine-patch bitmaps ignore this         * flag and are always scaled.         *         * <p>If {@link #inPremultiplied} is set to false, and the image has alpha,         * setting this flag to true may result in incorrect colors.         */        public boolean inScaled;

inPurgeable

当存储Pixel的内存空间在系统内存不足时是否可以被回收

        /**         * @deprecated As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this is         * ignored.         *         * In {@link android.os.Build.VERSION_CODES#KITKAT} and below, if this         * is set to true, then the resulting bitmap will allocate its         * pixels such that they can be purged if the system needs to reclaim         * memory. In that instance, when the pixels need to be accessed again         * (e.g. the bitmap is drawn, getPixels() is called), they will be         * automatically re-decoded.         *         * <p>For the re-decode to happen, the bitmap must have access to the         * encoded data, either by sharing a reference to the input         * or by making a copy of it. This distinction is controlled by         * inInputShareable. If this is true, then the bitmap may keep a shallow         * reference to the input. If this is false, then the bitmap will         * explicitly make a copy of the input data, and keep that. Even if         * sharing is allowed, the implementation may still decide to make a         * deep copy of the input data.</p>         *         * <p>While inPurgeable can help avoid big Dalvik heap allocations (from         * API level 11 onward), it sacrifices performance predictability since any         * image that the view system tries to draw may incur a decode delay which         * can lead to dropped frames. Therefore, most apps should avoid using         * inPurgeable to allow for a fast and fluid UI. To minimize Dalvik heap         * allocations use the {@link #inBitmap} flag instead.</p>         *         * <p class="note"><strong>Note:</strong> This flag is ignored when used         * with {@link #decodeResource(Resources, int,         * android.graphics.BitmapFactory.Options)} or {@link #decodeFile(String,         * android.graphics.BitmapFactory.Options)}.</p>         */        @Deprecated        public boolean inPurgeable;

inInputShareable

inPurgeable为true情况下才生效,是否可以共享一个InputStream

        /**         * @deprecated As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this is         * ignored.         *         * In {@link android.os.Build.VERSION_CODES#KITKAT} and below, this         * field works in conjuction with inPurgeable. If inPurgeable is false,         * then this field is ignored. If inPurgeable is true, then this field         * determines whether the bitmap can share a reference to the input         * data (inputstream, array, etc.) or if it must make a deep copy.         */        @Deprecated        public boolean inInputShareable;

inPreferQualityOverSpeed

为true则优先保证Bitmap质量其次是解码速度。

        /**         * @deprecated As of {@link android.os.Build.VERSION_CODES#N}, this is         * ignored.  The output will always be high quality.         *         * In {@link android.os.Build.VERSION_CODES#M} and below, if         * inPreferQualityOverSpeed is set to true, the decoder will try to         * decode the reconstructed image to a higher quality even at the         * expense of the decoding speed. Currently the field only affects JPEG         * decode, in the case of which a more accurate, but slightly slower,         * IDCT method will be used instead.         */        public boolean inPreferQualityOverSpeed;

decodeFile(String pathName, Options opts)

从文件读取图片

    /**     * Decode a file path into a bitmap. If the specified file name is null,     * or cannot be decoded into a bitmap, the function returns null.     *     * @param pathName complete path name for the file to be decoded.     * @param opts null-ok; Options that control downsampling and whether the     *             image should be completely decoded, or just is size returned.     * @return The decoded bitmap, or null if the image data could not be     *         decoded, or, if opts is non-null, if opts requested only the     *         size be returned (in opts.outWidth and opts.outHeight)     */    public static Bitmap decodeFile(String pathName, Options opts) {        Bitmap bm = null;        InputStream stream = null;        try {            stream = new FileInputStream(pathName);            bm = decodeStream(stream, null, opts);        } catch (Exception e) {            /*  do nothing.                If the exception happened on open, bm will be null.            */            Log.e("BitmapFactory", "Unable to decode stream: " + e);        } finally {            if (stream != null) {                try {                    stream.close();                } catch (IOException e) {                    // do nothing here                }            }        }        return bm;    }

decodeResource

从res资源文件读取图片。
加载的图片可能会经过缩放,该缩放目前是放在 java 层做的,效率比较低,而且需要消耗 java 层的内存。因此,如果大量使用该接口加载图片,容易导致OOM错误

    /**     * Synonym for opening the given resource and calling     * {@link #decodeResourceStream}.     *     * @param res   The resources object containing the image data     * @param id The resource id of the image data     * @param opts null-ok; Options that control downsampling and whether the     *             image should be completely decoded, or just is size returned.     * @return The decoded bitmap, or null if the image data could not be     *         decoded, or, if opts is non-null, if opts requested only the     *         size be returned (in opts.outWidth and opts.outHeight)     */    public static Bitmap decodeResource(Resources res, int id, Options opts) {        Bitmap bm = null;        InputStream is = null;         try {            final TypedValue value = new TypedValue();            is = res.openRawResource(id, value);            bm = decodeResourceStream(res, value, is, null, opts);        } catch (Exception e) {            /*  do nothing.                If the exception happened on open, bm will be null.                If it happened on close, bm is still valid.            */        } finally {            try {                if (is != null) is.close();            } catch (IOException e) {                // Ignore            }        }        if (bm == null && opts != null && opts.inBitmap != null) {            throw new IllegalArgumentException("Problem decoding into existing bitmap");        }        return bm;    }

decodeByteArray

从数组读取图片

    /**     * Decode an immutable bitmap from the specified byte array.     *     * @param data byte array of compressed image data     * @param offset offset into imageData for where the decoder should begin     *               parsing.     * @param length the number of bytes, beginning at offset, to parse     * @param opts null-ok; Options that control downsampling and whether the     *             image should be completely decoded, or just is size returned.     * @return The decoded bitmap, or null if the image data could not be     *         decoded, or, if opts is non-null, if opts requested only the     *         size be returned (in opts.outWidth and opts.outHeight)     */    public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {        if ((offset | length) < 0 || data.length < offset + length) {            throw new ArrayIndexOutOfBoundsException();        }        Bitmap bm;        Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap");        try {            bm = nativeDecodeByteArray(data, offset, length, opts);            if (bm == null && opts != null && opts.inBitmap != null) {                throw new IllegalArgumentException("Problem decoding into existing bitmap");            }            setDensityFromOptions(bm, opts);        } finally {            Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);        }        return bm;    }

decodeStream(InputStream is, Rect outPadding, Options opts)

从输入流读取图片。
不会对所加载的图片进行缩放,相比之下占用内存少,效率更高。

    /**     * Decode an input stream into a bitmap. If the input stream is null, or     * cannot be used to decode a bitmap, the function returns null.     * The stream's position will be where ever it was after the encoded data     * was read.     *     * @param is The input stream that holds the raw data to be decoded into a     *           bitmap.     * @param outPadding If not null, return the padding rect for the bitmap if     *                   it exists, otherwise set padding to [-1,-1,-1,-1]. If     *                   no bitmap is returned (null) then padding is     *                   unchanged.     * @param opts null-ok; Options that control downsampling and whether the     *             image should be completely decoded, or just is size returned.     * @return The decoded bitmap, or null if the image data could not be     *         decoded, or, if opts is non-null, if opts requested only the     *         size be returned (in opts.outWidth and opts.outHeight)     *     * <p class="note">Prior to {@link android.os.Build.VERSION_CODES#KITKAT},     * if {@link InputStream#markSupported is.markSupported()} returns true,     * <code>is.mark(1024)</code> would be called. As of     * {@link android.os.Build.VERSION_CODES#KITKAT}, this is no longer the case.</p>     */    public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {        // we don't throw in this case, thus allowing the caller to only check        // the cache, and not force the image to be decoded.        if (is == null) {            return null;        }        Bitmap bm = null;        Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap");        try {            if (is instanceof AssetManager.AssetInputStream) {                final long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();                bm = nativeDecodeAsset(asset, outPadding, opts);            } else {                bm = decodeStreamInternal(is, outPadding, opts);            }            if (bm == null && opts != null && opts.inBitmap != null) {                throw new IllegalArgumentException("Problem decoding into existing bitmap");            }            setDensityFromOptions(bm, opts);        } finally {            Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);        }        return bm;    }
阅读全文
0 0
原创粉丝点击