"无法压缩回收的位图"单个设备上的异常

时间:2012-07-23 11:30:52

标签: android exception bitmap imageview

我有一个巨大的问题HTC Wildfire S设备。我的应用程序使用图像uri启动第二个活动,用户可以旋转图像然后将其保存并返回到主活动。问题出在HTC上,只会返回第一张照片,第二张照片会使应用程序崩溃并出现以下错误:

java.lang.IllegalStateException: Can't compress a recycled bitmap at android.graphics.Bitmap.checkRecycled(Bitmap.java:372) at android.graphics.Bitmap.compress(Bitmap.java:799) at zapytaj.hot.or.not.ImageRotator.end(ImageRotator.java:151) at zapytaj.hot.or.not.ImageRotator$RotatorClass.onClick(ImageRotator.java:80) at android.view.View.performClick(View.java:2532) at android.view.View$PerformClick.run(View.java:9293) at android.os.Handler.handleCallback(Handler.java:587) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:150) at android.app.ActivityThread.main(ActivityThread.java:4277) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:507) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) at dalvik.system.NativeStart.main(Native Method)

我已经读过我应该.copy位图以避免在另一篇文章中出现此问题,但无法弄明白,如何在我的代码上执行此操作。谢谢你的帮助。第二项活动的代码如下:

package com.example.app;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Base64;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;

public class ImageRotator extends Activity {
    private static final String TAG = "Rotator";
    private Uri file;
    private String suffix = "";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.picture);

        Bundle b = getIntent().getExtras();

        file = getIntent().getData();
        suffix = b.getString("suffix");

        Bitmap bm = this.getBitmap();


        ImageView box = (ImageView) findViewById(R.id.imageView1);
        box.setImageBitmap(bm);

        ImageButton v1 = (ImageButton) findViewById(R.id.rotateLeft);
        ImageButton v2 = (ImageButton) findViewById(R.id.rotateRight);
        ImageButton v3 = (ImageButton) findViewById(R.id.save);
        v1.setOnClickListener(new RotatorClass());
        v2.setOnClickListener(new RotatorClass());
        v3.setOnClickListener(new RotatorClass());
    }


    class RotatorClass implements ImageButton.OnClickListener
    {
        public void onClick(View v) {
            final int id = v.getId();

            int change = 0;

            switch(id) {
                case R.id.rotateLeft:
                    change = -90;
                    break;
                case R.id.rotateRight:
                    change = 90;
                    break;
                case R.id.save:
                    end(true);
                    return;
            }

            Log.d(TAG, "change: "+change);

            ImageRotator.this.rotate(change);
        }
    }


    @Override
    public void onBackPressed() {   
        final AlertDialog alertDialog = new AlertDialog.Builder(this).create();
        alertDialog.setTitle("Podane zdjęcie nie zostanie dodane. Kontynuować?");
        alertDialog.setButton("Tak", new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int which) {
                  end(false);
              }
        });

        alertDialog.setButton2("Nie", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                alertDialog.cancel();
            }
        });

        alertDialog.setCancelable(false);
        alertDialog.show();
    }

    public void rotate(int change) {
        // TODO Auto-generated method stub

        ImageView imageView = (ImageView) findViewById(R.id.imageView1);

        BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
        BitmapFactory.Options options = new BitmapFactory.Options();
        Bitmap bm = drawable.getBitmap();
        Matrix matrix = new Matrix();
        matrix.postRotate(change);

        Bitmap bm2 = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
        bm = null;

        imageView.setImageBitmap(bm2);      
    }

    public String getRealPathFromURI(Uri contentUri) {
        String[] proj = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(contentUri, proj, null, null, null);
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }

    public void end(boolean save) {

        Intent in = new Intent();

        if(save == true) {

            File file2 = new File(getRealPathFromURI(file));

            try {
                FileOutputStream fos = new FileOutputStream(file2);
                ImageView imageView = (ImageView) findViewById(R.id.imageView1);
                BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
                Bitmap bm = drawable.getBitmap();

                ByteArrayOutputStream baos = new ByteArrayOutputStream();  
                bm.compress(Bitmap.CompressFormat.JPEG, 30, baos);
                byte[] b = baos.toByteArray(); 

                String base = Base64.encodeToString(b, Base64.NO_WRAP);

                bm.compress(Bitmap.CompressFormat.PNG, 90, fos);
                fos.flush();
                fos.close();

                bm.recycle();
                bm = null;

                in.setData(file);

                in.putExtra("base", base);
                System.gc();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        setResult(4,in);
        finish();
    }


    private Bitmap getBitmap() {

        Uri uri = this.file;
        InputStream in = null;

        ContentResolver mContentResolver = getContentResolver();

        try {
            final int IMAGE_MAX_SIZE = 300000;
            in = mContentResolver.openInputStream(uri);

            // Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(in, null, o);
            in.close();

            int scale = 1;
            while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) > IMAGE_MAX_SIZE) {
                scale++;
            }
            Log.d(TAG, "scale = " + scale + ", orig-width: " + o.outWidth       + ", orig-height: " + o.outHeight);

            Bitmap b = null;
            in = mContentResolver.openInputStream(uri);
            if (scale > 1) {
                scale--;
                // scale to max possible inSampleSize that still yields an image
                // larger than target
                o = new BitmapFactory.Options();
                o.inSampleSize = scale;
                b = BitmapFactory.decodeStream(in, null, o);

                // resize to desired dimensions
                int height = b.getHeight();
                int width = b.getWidth();
                Log.d(TAG, "1th scale operation dimenions - width: " + width    + ", height: " + height);

                double y = Math.sqrt(IMAGE_MAX_SIZE
                        / (((double) width) / height));
                double x = (y / height) * width;

                Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x,     (int) y, true);
                b.recycle();
                b = null;

                b = scaledBitmap;
            } else {
                b = BitmapFactory.decodeStream(in);
            }
            in.close();
            return b;
        } catch (IOException e) {
            Log.e(TAG, e.getMessage(),e);
            return null;
        }
    }
}

1 个答案:

答案 0 :(得分:2)

只需使用原始位图的复制功能即可。

Bitmap bm = drawable.getBitmap().copy(Bitmap.Config.ARGB_8888, false);

Config - 一个具有两个或三个可选值的枚举器,用于支持pixcel表示。

boolean参数指出结果位图是否允许访问来编辑它的位。