1

HTC Wildfire S デバイスに大きな問題があります。私のアプリケーションは、画像 uri で 2 番目のアクティビティを開始します。ユーザーは画像を回転させることができ、保存してメイン アクティビティに戻ります。問題は HTC のみで、最初の写真が返され、2 番目の写真は以下のエラーでアプリケーションをクラッシュさせます:

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)

別の投稿でこの問題を回避するにはビットマップをコピーする必要があることを読みましたが、コードでそれを行う方法を理解できませんでした。ご協力いただきありがとうございます。以下に含まれる 2 番目のアクティビティのコード:

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;
        }
    }
}
4

1 に答える 1

2

元のビットマップのコピー機能を使用するだけです。

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

Config- ピクセル表現をサポートするための、2 つまたは 3 つのオプションの値を持つ列挙子。

boolean 引数は、結果のビットマップがそのビットを編集するためのアクセスを許可するかどうかを示します。

于 2013-03-12T19:53:30.153 に答える