android图片导入防止OOM

来源:互联网 发布:mac键盘按键 编辑:程序博客网 时间:2024/04/29 23:11

类似帖子太多,当然我的也不是我写的,只是这代码比较典型,而且逻辑清晰,可以直接使用。

还是要经常学习别人写的比较优秀的代码,学习别人控制代码的逻辑,控制变量,内存,流程等,如果控制好的话代码就比较稳定。如下:

import android.content.res.Resources;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.graphics.BitmapFactory;import android.graphics.BitmapFactory.Options;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Rect;/** * Class containing static utility methods for bitmap decoding and scaling * */public class ScalingUtilities {    /**     * Utility function for decoding an image resource. The decoded bitmap will     * be optimized for further scaling to the requested destination dimensions     * and scaling logic.     *     * @param res The resources object containing the image data     * @param resId The resource id of the image data     * @param dstWidth Width of destination area     * @param dstHeight Height of destination area     * @param scalingLogic Logic to use to avoid image stretching     * @return Decoded bitmap     */    public static Bitmap decodeResource(Resources res, int resId, int dstWidth, int dstHeight,            ScalingLogic scalingLogic) {        Options options = new Options();        options.inJustDecodeBounds = true;        BitmapFactory.decodeResource(res, resId, options);        options.inJustDecodeBounds = false;        options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,                dstHeight, scalingLogic);        Bitmap unscaledBitmap = BitmapFactory.decodeResource(res, resId, options);        return unscaledBitmap;    }    /**     * Utility function for creating a scaled version of an existing bitmap     *     * @param unscaledBitmap Bitmap to scale     * @param dstWidth Wanted width of destination bitmap     * @param dstHeight Wanted height of destination bitmap     * @param scalingLogic Logic to use to avoid image stretching     * @return New scaled bitmap object     */    public static Bitmap createScaledBitmap(Bitmap unscaledBitmap, int dstWidth, int dstHeight,            ScalingLogic scalingLogic) {        Rect srcRect = calculateSrcRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),                dstWidth, dstHeight, scalingLogic);        Rect dstRect = calculateDstRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),                dstWidth, dstHeight, scalingLogic);        Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(), dstRect.height(),                Config.ARGB_8888);        Canvas canvas = new Canvas(scaledBitmap);        canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(Paint.FILTER_BITMAP_FLAG));        return scaledBitmap;    }    /**     * ScalingLogic defines how scaling should be carried out if source and     * destination image has different aspect ratio.     *     * CROP: Scales the image the minimum amount while making sure that at least     * one of the two dimensions fit inside the requested destination area.     * Parts of the source image will be cropped to realize this.     *     * FIT: Scales the image the minimum amount while making sure both     * dimensions fit inside the requested destination area. The resulting     * destination dimensions might be adjusted to a smaller size than     * requested.     */    public static enum ScalingLogic {        CROP, FIT    }    /**     * Calculate optimal down-sampling factor given the dimensions of a source     * image, the dimensions of a destination area and a scaling logic.     *     * @param srcWidth Width of source image     * @param srcHeight Height of source image     * @param dstWidth Width of destination area     * @param dstHeight Height of destination area     * @param scalingLogic Logic to use to avoid image stretching     * @return Optimal down scaling sample size for decoding     */    public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight,            ScalingLogic scalingLogic) {        if (scalingLogic == ScalingLogic.FIT) {            final float srcAspect = (float)srcWidth / (float)srcHeight;            final float dstAspect = (float)dstWidth / (float)dstHeight;            if (srcAspect > dstAspect) {                return srcWidth / dstWidth;            } else {                return srcHeight / dstHeight;            }        } else {            final float srcAspect = (float)srcWidth / (float)srcHeight;            final float dstAspect = (float)dstWidth / (float)dstHeight;            if (srcAspect > dstAspect) {                return srcHeight / dstHeight;            } else {                return srcWidth / dstWidth;            }        }    }    /**     * Calculates source rectangle for scaling bitmap     *     * @param srcWidth Width of source image     * @param srcHeight Height of source image     * @param dstWidth Width of destination area     * @param dstHeight Height of destination area     * @param scalingLogic Logic to use to avoid image stretching     * @return Optimal source rectangle     */    public static Rect calculateSrcRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,            ScalingLogic scalingLogic) {        if (scalingLogic == ScalingLogic.CROP) {            final float srcAspect = (float)srcWidth / (float)srcHeight;            final float dstAspect = (float)dstWidth / (float)dstHeight;            if (srcAspect > dstAspect) {                final int srcRectWidth = (int)(srcHeight * dstAspect);                final int srcRectLeft = (srcWidth - srcRectWidth) / 2;                return new Rect(srcRectLeft, 0, srcRectLeft + srcRectWidth, srcHeight);            } else {                final int srcRectHeight = (int)(srcWidth / dstAspect);                final int scrRectTop = (int)(srcHeight - srcRectHeight) / 2;                return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight);            }        } else {            return new Rect(0, 0, srcWidth, srcHeight);        }    }    /**     * Calculates destination rectangle for scaling bitmap     *     * @param srcWidth Width of source image     * @param srcHeight Height of source image     * @param dstWidth Width of destination area     * @param dstHeight Height of destination area     * @param scalingLogic Logic to use to avoid image stretching     * @return Optimal destination rectangle     */    public static Rect calculateDstRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,            ScalingLogic scalingLogic) {        if (scalingLogic == ScalingLogic.FIT) {            final float srcAspect = (float)srcWidth / (float)srcHeight;            final float dstAspect = (float)dstWidth / (float)dstHeight;            if (srcAspect > dstAspect) {                return new Rect(0, 0, dstWidth, (int)(dstWidth / srcAspect));            } else {                return new Rect(0, 0, (int)(dstHeight * srcAspect), dstHeight);            }        } else {            return new Rect(0, 0, dstWidth, dstHeight);        }    }}

 ScalingUtilities 主要用来编码图片资源成bitmap ,计算图片尺寸并缩放图片到指定尺寸

具体使用如下,可以有两种使用方式:

    /**     * Invoked when pressing button for showing result of the "Fit" decoding     * method     */    protected void fitButtonPressed() {        final long startTime = SystemClock.uptimeMillis();        // Part 1: Decode image        Bitmap unscaledBitmap = ScalingUtilities.decodeResource(getResources(), mSourceId,                mDstWidth, mDstHeight, ScalingLogic.FIT);        // Part 2: Scale image        Bitmap scaledBitmap = ScalingUtilities.createScaledBitmap(unscaledBitmap, mDstWidth,                mDstHeight, ScalingLogic.FIT);        unscaledBitmap.recycle();        // Calculate memory usage and performance statistics        final int memUsageKb = (unscaledBitmap.getRowBytes() * unscaledBitmap.getHeight()) / 1024;        final long stopTime = SystemClock.uptimeMillis();        // Publish results        mResultView.setText("Time taken: " + (stopTime - startTime)                + " ms. Memory used for scaling: " + memUsageKb + " kb.");        mImageView.setImageBitmap(scaledBitmap);    }    /**     * Invoked when pressing button for showing result of the "Crop" decoding     * method     */    protected void cropButtonPressed() {        final long startTime = SystemClock.uptimeMillis();        // Part 1: Decode image        Bitmap unscaledBitmap = ScalingUtilities.decodeResource(getResources(), mSourceId,                mDstWidth, mDstHeight, ScalingLogic.CROP);        // Part 2: Scale image        Bitmap scaledBitmap = ScalingUtilities.createScaledBitmap(unscaledBitmap, mDstWidth,                mDstHeight, ScalingLogic.CROP);        unscaledBitmap.recycle();        // Calculate memory usage and performance statistics        final int memUsageKb = (unscaledBitmap.getRowBytes() * unscaledBitmap.getHeight()) / 1024;        final long stopTime = SystemClock.uptimeMillis();        // Publish results        mResultView.setText("Time taken: " + (stopTime - startTime)                + " ms. Memory used for scaling: " + memUsageKb + " kb.");        mImageView.setImageBitmap(scaledBitmap);    }


这样先计算图片尺寸然后加载的方式可以防止一定程度的OOM,至于如此情形下图片过多过大防止OOM可以考虑在应用内存不足的时候计算剩余内存量,如果过少则停止加载图片资源到内存。


本例代码可以下载使用,已经上传,链接如下:

http://download.csdn.net/detail/bawang_cn/5033276


该文可以参见地址:

http://developer.sonymobile.com/2011/06/27/how-to-scale-images-for-your-android-application/