开源android-crop裁剪库的bug并修复

作者: laogui | 来源:发表于2016-07-05 18:37 被阅读1417次

    最近项目中使用了开源裁剪库android-cropandroid-crop,使用过程中遇到了三星手机拍照后裁剪的bug,上官方github里看issues发现果真还是有开发者同样遇到这个问题的。bug描述如下:
    用手机拍照(保持竖屏)后进入裁剪界面,裁剪完后的图片是旋转90度的,但是在裁剪预览界面中看的是正常的。

    最好到官方github去clone原始项目,运行其中的example程序体验下。

    先看修复前bug截图:


    1.png 2.png

    修复后截图:


    Paste_Image.png 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方法:

    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则选择图片再保存

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

    CropUtil.rotateImage的代码如下:

    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裁剪前,需要对裁剪的宽和高进行交换处理。

    写在最后

    大家可以在我的github地址android-cropclone我的官方fork版本。
    example中相比原始项目增加了拍照后裁剪的demo。

    相关文章

      网友评论

      • liguiyun:亲刚才试了 还是不可以啊
        laogui:@liguiyun 试试我的demo看符合你需求吗?我的项目是没有问题的哟
      • liguiyun:不知道 能否解决 但是 看着 可有谱!看看能否解决!谢大神了啊

      本文标题:开源android-crop裁剪库的bug并修复

      本文链接:https://www.haomeiwen.com/subject/auzqjttx.html