ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

android – 无法压缩回收的位图

2019-07-17 17:34:59  阅读:76  来源: 互联网

标签:android bitmap


我有一个回收bitmap的问题.我有所有null和代码回收.不确定我做错了什么.

我的代码:

ByteArrayOutputStream stream = new ByteArrayOutputStream();               
bmp = DecodeImage.decodeFile(imgpath, 450, 450, true);
bmp.compress(Bitmap.CompressFormat.JPEG, 100 , stream);     
Image img = Image.getInstance(stream.toByteArray()); 

错误信息:

07-12 15:44:11.924: E/AndroidRuntime(415): FATAL EXCEPTION: Thread-9850
07-12 15:44:11.924: E/AndroidRuntime(415): java.lang.IllegalStateException: Can't compress 
a recycled bitmap
07-12 15:44:11.924: E/AndroidRuntime(415):  at 
android.graphics.Bitmap.checkRecycled(Bitmap.java:272)
07-12 15:44:11.924: E/AndroidRuntime(415):  at 
android.graphics.Bitmap.compress(Bitmap.java:896)
07-12 15:44:11.924: E/AndroidRuntime(415):  at com.multiprvt.PDF$1.run(PDF.java:329)
07-12 15:44:11.924: E/AndroidRuntime(415):  at java.lang.Thread.run(Thread.java:856)

解码为位图降低分辨率的类.

    public class DecodeImage
       {

       //decodes image and scales it to reduce memory consumption
         public static Bitmap decodeFile(File bitmapFile, int requiredWidth, int 
    requiredHeight,     boolean quickAndDirty)
   {
    try
    {
        //Decode image size
        BitmapFactory.Options bitmapSizeOptions = new BitmapFactory.Options();
        bitmapSizeOptions.inJustDecodeBounds = true;
      BitmapFactory.decodeStream(new FileInputStream(bitmapFile), null,  
    bitmapSizeOptions);

        // load image using inSampleSize adapted to required image size
        BitmapFactory.Options bitmapDecodeOptions = new BitmapFactory.Options();
        bitmapDecodeOptions.inTempStorage = new byte[16 * 1024];
     bitmapDecodeOptions.inSampleSize = computeInSampleSize(bitmapSizeOptions, 
    requiredWidth, requiredHeight, false);
        bitmapDecodeOptions.inPurgeable = true;
        bitmapDecodeOptions.inDither = !quickAndDirty;
       bitmapDecodeOptions.inPreferredConfig = quickAndDirty ? Bitmap.Config.RGB_565 : 
     Bitmap.Config.ARGB_8888;

         Bitmap decodedBitmap = BitmapFactory.decodeStream(new 
    FileInputStream(bitmapFile), null, bitmapDecodeOptions);

        // scale bitmap to mathc required size (and keep aspect ratio)

        float srcWidth = (float) bitmapDecodeOptions.outWidth;
        float srcHeight = (float) bitmapDecodeOptions.outHeight;

        float dstWidth = (float) requiredWidth;
        float dstHeight = (float) requiredHeight;

        float srcAspectRatio = srcWidth / srcHeight;
        float dstAspectRatio = dstWidth / dstHeight;

    // recycleDecodedBitmap is used to know if we must recycle intermediary 
   'decodedBitmap'
    // (DO NOT recycle it right away: wait for end of bitmap manipulation process to avoid
    // java.lang.RuntimeException: Canvas: trying to use a recycled bitmap 
   android.graphics.Bitmap@416ee7d8
        // I do not excatly understand why, but this way it's OK

        boolean recycleDecodedBitmap = false;

        Bitmap scaledBitmap = decodedBitmap;
        if (srcAspectRatio < dstAspectRatio)
        {       scaledBitmap = getScaledBitmap(decodedBitmap, (int) dstWidth, (int)  
  (srcHeight * (dstWidth / srcWidth)));
            // will recycle recycleDecodedBitmap
            recycleDecodedBitmap = true;
        }
        else if (srcAspectRatio > dstAspectRatio)
        {
            scaledBitmap = getScaledBitmap(decodedBitmap, (int) (srcWidth * (dstHeight / 
  srcHeight)), (int) dstHeight);
            recycleDecodedBitmap = true;
        }

        // crop image to match required image size

        int scaledBitmapWidth = scaledBitmap.getWidth();
        int scaledBitmapHeight = scaledBitmap.getHeight();

        Bitmap croppedBitmap = scaledBitmap;



        if (recycleDecodedBitmap)
        {
            decodedBitmap.recycle();
        }
        decodedBitmap = null;

        scaledBitmap = null;
        return croppedBitmap;

    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }
    return null;
   }

   /**
    * compute powerOf2 or exact scale to be used as {@link   
   BitmapFactory.Options#inSampleSize} value (for subSampling)
   * 
   * @param requiredWidth
   * @param requiredHeight
   * @param powerOf2
   *            weither we want a power of 2 sclae or not
 * @return
 */
  public static int computeInSampleSize(BitmapFactory.Options options, int dstWidth, int 
  dstHeight, boolean powerOf2)
  {
    int inSampleSize = 1;

    // Raw height and width of image
    final int srcHeight = options.outHeight;
    final int srcWidth = options.outWidth;

    if (powerOf2)
    {
        //Find the correct scale value. It should be the power of 2.

        int tmpWidth = srcWidth, tmpHeight = srcHeight;
        while (true)
        {
            if (tmpWidth / 2 < dstWidth || tmpHeight / 2 < dstHeight)
                break;
            tmpWidth /= 2;
            tmpHeight /= 2;
            inSampleSize *= 2;
        }
    }
    else
    {
        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) srcHeight / (float) dstHeight);
        final int widthRatio = Math.round((float) srcWidth / (float) dstWidth);

        // Choose the smallest ratio as inSampleSize value, this will guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    return inSampleSize;
   }

     public static Bitmap drawableToBitmap(Drawable drawable)
    {
    if (drawable instanceof BitmapDrawable)
    {
        return ((BitmapDrawable) drawable).getBitmap();
    }

    Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), 
     drawable.getIntrinsicHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);

    return bitmap;
   }

    public static Bitmap getScaledBitmap(Bitmap bitmap, int newWidth, int newHeight)
   {
    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;

    // CREATE A MATRIX FOR THE MANIPULATION
    Matrix matrix = new Matrix();
    // RESIZE THE BIT MAP
    matrix.postScale(scaleWidth, scaleHeight);

    // RECREATE THE NEW BITMAP
         Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix,                
    false);
    return resizedBitmap;
   } 

   }

不知道它在哪里获得循环位图

解决方法:

您的源和缩放位图是相同的.在回收源之前检查是否相等.

Bitmap scaled = Bitmap.createScaledBitmap(src, ...):
if (src != scaled) {
    src.recycle();
}
return scaled;

从Bitmap.createScaledBitmap(…)的文档:

尽可能创建从现有位图缩放的新位图.如果指定的宽度和高度与源位图的当前宽度和高度相同,则返回源位图,并且不会创建新的位图.

标签:android,bitmap
来源: https://codeday.me/bug/20190717/1490755.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有