6

基本的に、Androidアプリで(画像から)ビットマップを回転させようとしています。これをやりたい理由は、カメラから(インテントを介して)撮影した写真は、垂直方向にキャプチャした場合でも水平方向に表示され、向きは画像のメタデータとして保持されるためです。間違っている場合は訂正してください。ただし、問題は、適度に優れたカメラを搭載した電話で撮影した場合、画像を読み込んだときに大量のメモリを消費することです。OutOfMemoryErrorが発生するリスクなしに、画像を回転して保存する方法が見つかりませんでした。 。以下のコードは次のとおりです。

  1. 画像を読み込む
  2. 回転させる必要があるかどうかを確認します
  3. ImageViewに表示するために縮小されたバージョンをロードします
  4. 必要に応じて小さな画像を回転します
  5. 別のスレッドで; 画像を読み込んで回転させて保存するので、将来的には必要ありません

アプリケーションが画像を解像度に保つことは重要ですが、エンコーディングのトリックは大歓迎です。私は数日間インターネットを検索しましたが、すでに実装したもの以上のものを見つけることができませんでした。ここにこのテーマに関する別のスレッドがありますが、解決策はないようです。あなたが助けることができることを願っています。

    public Bitmap getBitmap(final Context c) {
    if (bitmap != null)
        return bitmap;

    final int rotate = necessaryRotation(c, file);
    // if(rotate != 0) rotateImageFile(c, rotate);

    try {
        // Get scaled version
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(file, options);
        options.inSampleSize = calcInSampleSize(options, 1024, 1024);
        options.inJustDecodeBounds = false;
        bitmap = BitmapFactory.decodeFile(file, options);

        // rotate?
        bitmap = rotateImage(c,bitmap,rotate);

        System.out.println("Bitmap loaded from file: size="
                + bitmap.getWidth() + "," + bitmap.getHeight());

        System.gc();
    } catch (Exception e) {
        System.err.println("Unable to load image file: "
                + this.getFilename());
    }

    // if rotation is needed, do it in worker thread for next time
    if(rotate != 0){
        Thread t = new Thread(new Runnable(){

            public void run() {
                // load entire image
                try{
                    File imageFile = new File(getFilename());
                    Bitmap huge = Media.getBitmap(c.getContentResolver(),
                    Uri.fromFile(imageFile));

                    huge = rotateImage(c,huge,rotate);

                    // save bitmap properly
                    FileOutputStream out = new FileOutputStream(imageFile);
                    huge.compress(Bitmap.CompressFormat.PNG, 100, out);

                    out.flush();
                    out.close();
                    huge.recycle();
                    huge = null;
                    out = null;
                    System.gc();

                }catch(IOException e){
                    e.printStackTrace();
                }
            }

        });
        t.start();
    }

    return bitmap;
}

private Bitmap rotateImage(Context c, Bitmap bitmap, int rotate) {
    if (rotate != 0) {
        // rotate
        Matrix m = new Matrix();
        m.postRotate(rotate);
        Bitmap rotImage = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), m, true);
        bitmap.recycle();

        System.out.println("Image (id=" + getId()
                + ") rotated successfully");

        System.gc();

        return rotImage;
    }
    return bitmap;
}

private int necessaryRotation(Context c, String imageFile) {
    int rotate = 0;
    ExifInterface exif;
    try {
        exif = new ExifInterface(imageFile);
        int orientation = exif.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);

        switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_270:
            rotate = 270;
            break;
        case ExifInterface.ORIENTATION_ROTATE_180:
            rotate = 180;
            break;
        case ExifInterface.ORIENTATION_ROTATE_90:
            rotate = 90;
            break;
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return rotate;
}

private int calcInSampleSize(BitmapFactory.Options options, int reqWidth,
        int reqHeight) {
    int height = options.outHeight;
    int width = options.outWidth;
    int inSampleSize = 1;
    while (height > reqHeight || width > reqWidth) {
        height /= 2;
        width /= 2;
        inSampleSize *= 2;
    }

    return inSampleSize;
}

知っておく必要のあることや、メモリ使用量を減らすために使用できる可能性のある最適化がある場合は、次のように書いてください:)ありがとう

4

1 に答える 1

0

このスニペットを試してください:

private Bitmap rotateImage(Context c, Bitmap bitmap, int rotate) {
    ....

    // reduce byte per pixel
    bitmap = bitmap.copy(Bitmap.Config.RGB_565, false);

    Bitmap.createBitmap(bitmap,...
}
于 2012-09-11T15:24:09.550 に答える