開源android-crop裁剪庫的bug並修復

最近項目中使用了開源裁剪庫android-crop,使用過程當中遇到了三星手機拍照後裁剪的bug,上官方github裏看issues發現果然仍是有開發者一樣遇到這個問題的。bug描述以下:
用手機拍照(保持豎屏)後進入裁剪界面,裁剪完後的圖片是旋轉90度的,可是在裁剪預覽界面中看的是正常的。java

最好到官方github去clone原始項目,運行其中的example程序體驗下。android

先看修復前bug截圖:
1.pnggit

2.png
修復後截圖:
Paste_Image.pnggithub

Paste_Image.png

修復過程

  1. CropImageActivity.java修改前的saveOutput方法:
private void saveOutput(Bitmap croppedImage) {
    if (saveUri != null) {
        OutputStream outputStream = null;
        try {
            outputStream = getContentResolver().openOutputStream(saveUri);
            if (outputStream != null) {
                croppedImage.compress(saveAsPng ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG,
                        90,     // note: quality is ignored when using PNG
                        outputStream);
            }
        } catch (IOException e) {
            setResultException(e);
            Log.e("Cannot open file: " + saveUri, e);
        } finally {
            CropUtil.closeSilently(outputStream);
        }

        CropUtil.copyExifRotation(
                CropUtil.getFromMediaUri(this, getContentResolver(), sourceUri),
                CropUtil.getFromMediaUri(this, getContentResolver(), saveUri)
        );

        setResultUri(saveUri);
    }

    final Bitmap b = croppedImage;
    handler.post(new Runnable() {
        public void run() {
            imageView.clear();
            b.recycle();
        }
    });

    finish();
}

修改後的saveOutput方法:post

private void saveOutput(Bitmap croppedImage) {
    if (saveUri != null) {
        OutputStream outputStream = null;

        Bitmap destBitmap = croppedImage;
        if(exifRotation != 0){
            destBitmap = CropUtil.rotateImage(croppedImage, exifRotation);
        }
        FileInputStream inputStream = null;
        try {
            //save bitmap to file
            outputStream = getContentResolver().openOutputStream(saveUri);
            if (outputStream != null) {
                destBitmap.compress(saveAsPng ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG,
                        90,     // note: quality is ignored when using PNG
                        outputStream);
            }
            destBitmap.recycle();
        } catch (OutOfMemoryError error) {
        } catch (IOException e){
            setResultException(e);
            Log.e("Cannot open file: " + saveUri, e);
        }finally {
            CropUtil.closeSilently(inputStream);
            CropUtil.closeSilently(outputStream);
        }

        CropUtil.copyExifRotation(
                CropUtil.getFromMediaUri(this, getContentResolver(), sourceUri),
                CropUtil.getFromMediaUri(this, getContentResolver(), saveUri)
        );

        setResultUri(saveUri);
    }

    final Bitmap b = croppedImage;
    handler.post(new Runnable() {
        public void run() {
            imageView.clear();
            b.recycle();
        }
    });

    finish();
}

其實只是加入了旋轉角度的斷定,若是角度不爲0則旋轉圖片再保存ui

if(exifRotation != 0){
    destBitmap = CropUtil.rotateImage(croppedImage, exifRotation);
}

CropUtil.rotateImage的代碼以下:this

public static Bitmap rotateImage(Bitmap img, int rotate) {
    Matrix matrix = new Matrix();
    matrix.postRotate(rotate);
    int width = img.getWidth();
    int height = img.getHeight();
    img = Bitmap.createBitmap(img, 0, 0, width, height, matrix, false);
    return img;
}
  1. 在CropImageActivity.java的onSaveClicked方法中的croppedImage = decodeRegionCrop(r, outWidth, outHeight);前加入以下代碼:
if(exifRotation != 0 && exifRotation % 90 == 0){
    int tmp = outWidth;
    outWidth = outHeight;
    outHeight = tmp;
}

若是有旋轉角度,則在decodeRegionCrop裁剪前,須要對裁剪的寬和高進行交換處理。code

寫在最後

你們能夠在個人github地址android-cropclone個人官方fork版本。
example中相比原始項目增長了拍照後裁剪的demo。orm

相關文章
相關標籤/搜索