【问题标题】:Android Library - android-crop rotates captured imagesAndroid 库 - android-crop 旋转捕获的图像
【发布时间】:2015-06-19 15:50:38
【问题描述】:

我正在使用 Android-Crop https://github.com/jdamcd/android-crop 来对使用相机 onActivityResult 捕获图像的结果进行方形裁剪。问题是,由于某种原因,这个库似乎会不可预测地旋转图像。

以下是创建我正在处理 onActivityResult 的输出的库的 Activity - CropImageActivity

裁剪的结果只是在 ImageView 中使用 Picasso 加载。图像文件临时存储在 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) 中,该文件以 EXTRA_OUTPUT 形式提供,用于捕获图像,然后被裁剪并加载到 ImageVIew 中。

问题在于,对于某些 Android 手机,图像旋转正确,但对于其他手机,则不然。 Nexus 5 还可以,Xperia Z 不行等等...

我正在寻找一种简单的方法来确保正确旋转图像。 提前感谢您的帮助!

【问题讨论】:

  • 是什么让你认为这是这个库的错,而不是你在它们上使用的设备或相机应用程序的错?您是否正在检查 EXIF 标头以查看是否包含方向标头?
  • 当跳过裁剪步骤时,图像的方向正确。
  • 结帐Android-Image-Cropper图书馆。

标签: android


【解决方案1】:

我用过This cropping library,它工作得很好。以下是可行的步骤。

  1. 在您的 build.gradle(app) 文件中添加“compile 'com.isseiaoki:simplecropview:1.1.7'”

  2. 在主类文件中创建一个全局变量,从中调用相机意图,例如 私有静态最终整数 REQUEST_CODE_FOR_IMAGE_CROPPING = 65 ;

    public static final int REQUEST_CODE_FOR_OPENCAMERA = 300;

  3. 打开相机的onButton点击listner写下代码

    // create file 
    File newfile = createFile();
    Uri outputFileUri = Uri.fromFile(newfile);
    String uriString = outputFileUri.toString();
    
    Intent intent = new Intent();
    intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); 
    intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
    context.startActivityForResult(intent, OPENCAMERA);
    
  4. 在 onCreate() 之后写下创建文件的方法。

     private File createFile() {
    String root = Environment.getExternalStorageDirectory().toString();
    myDir = new File(root + File.separator + "YourFolderName");
    if (!myDir.exists())
        myDir.mkdirs();
    
    File newfile = new File(myDir, "IMG_" + System.currentTimeMillis() + ".JPG");
    try {
        newfile.createNewFile();
    } catch (IOException e) {
    }
    return newfile;
    }
    
  5. 获取相机意图的 onActivityResult 数据,如下所示。

    if (requestCode == REQUEST_CODE_FOR_OPENCAMERA) {
    if (resultCode == RESULT_OK) {
            try {
                uriStr = (Uri) data.getExtras().get("data");
    
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uriStr);
    
                if (bitmap != null) {
    
                    Intent gotoCropImage = new Intent(thisActivity, CropMyImageActivity.class);
                    gotoCropImage.setData(uriStr);
                    startActivityForResult(gotoCropImage, REQUEST_CODE_FOR_IMAGE_CROPPING);
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (resultCode == RESULT_CANCELED) {
            // user cancelled Image capture
            DialogManager.showToast(thisActivity, getString(R.string.user_cancelled_image_capture));
        }
    }
    
  1. 创建名为 CropMyImageActivity.java 的新活动并编写以下代码
  import android.content.Intent;
  import android.graphics.Bitmap;
  import android.net.Uri;
  import android.os.Bundle;
  import android.view.View;
  import android.widget.ImageButton;

  import com.isseiaoki.simplecropview.CropImageView;
  import com.isseiaoki.simplecropview.callback.CropCallback;
  import com.isseiaoki.simplecropview.callback.LoadCallback;
  import com.isseiaoki.simplecropview.callback.SaveCallback;
  import com.pioneer.parivaar.activities.BaseActivity;

  public class CropMyImageActivity extends BaseActivity implements View.OnClickListener {

private Uri mSourceUri = null;
private CropImageView mCropView;
private Bitmap.CompressFormat mCompressFormat = Bitmap.CompressFormat.JPEG;
private ImageButton rotateLeft, rotateRight, doneBtn, cancelBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_crop_my_image);

    mCropView = (CropImageView) findViewById(R.id.cropImageView);
    rotateLeft = (ImageButton) findViewById(R.id.buttonRotateLeft);
    rotateRight = (ImageButton) findViewById(R.id.buttonRotateRight);
    doneBtn = (ImageButton) findViewById(R.id.buttonDone);
    cancelBtn = (ImageButton) findViewById(R.id.buttonCancel);

    mSourceUri = getIntent().getData();

    rotateLeft.setOnClickListener(this);
    rotateRight.setOnClickListener(this);
    doneBtn.setOnClickListener(this);
    cancelBtn.setOnClickListener(this);
    // load image
    mCropView.setCropMode(CropImageView.CropMode.SQUARE);
    mCropView.load(mSourceUri)
            .useThumbnail(true)
            .execute(mLoadCallback);


}

private final LoadCallback mLoadCallback = new LoadCallback() {
    @Override public void onSuccess() {
    }

    @Override public void onError(Throwable e) {
    }
};

private final CropCallback mCropCallback = new CropCallback() {
    @Override public void onSuccess(Bitmap cropped) {
        mCropView.save(cropped)
                .compressFormat(mCompressFormat)
                .execute(mSourceUri, mSaveCallback);
    }

    @Override public void onError(Throwable e) {
    }
};
private final SaveCallback mSaveCallback = new SaveCallback() {
    @Override public void onSuccess(Uri outputUri) {
        Intent i = new Intent();
        i.setData(outputUri);
        setResult(RESULT_OK, i);
        finish();
    }

    @Override public void onError(Throwable e) {
    }
};


@Override
public void onClick(View view) {
    switch (view.getId()){
        case R.id.buttonRotateLeft:
            mCropView.rotateImage(CropImageView.RotateDegrees.ROTATE_M90D);
            break;
        case R.id.buttonRotateRight:
            mCropView.rotateImage(CropImageView.RotateDegrees.ROTATE_90D);
            break;
        case R.id.buttonDone:
            mCropView.crop(mSourceUri).execute(mCropCallback);
            break;

        case R.id.buttonCancel:
            setResult(RESULT_CANCELED);
            finish();
            break;
    }
}
}
  1. 创建一个名为 activity_crop_my_image.xml 的 xml 文件,如下所示
  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">


<com.isseiaoki.simplecropview.CropImageView
    android:id="@+id/cropImageView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:padding="@dimen/margin25"
    custom:scv_background_color="@color/windowBackground"
    custom:scv_crop_mode="fit_image"
    custom:scv_frame_color="@color/colorAccent"
    custom:scv_frame_stroke_weight="1dp"
    custom:scv_guide_color="@color/colorAccent"
    custom:scv_guide_show_mode="show_always"
    custom:scv_guide_stroke_weight="1dp"
    custom:scv_handle_color="@color/colorAccent"
    custom:scv_handle_show_mode="show_always"
    custom:scv_handle_size="14dp"
    custom:scv_min_frame_size="50dp"
    custom:scv_overlay_color="@color/overlay"
    custom:scv_touch_padding="8dp" />

<View
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:layout_marginLeft="@dimen/margin7"
    android:layout_marginRight="@dimen/margin7"
    android:background="@color/black"
    />


<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@id/cropImageView"
    android:layout_centerHorizontal="true"
    android:orientation="horizontal">

    <ImageButton
        android:id="@+id/buttonCancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:background="?attr/selectableItemBackgroundBorderless"
        android:padding="16dp"
        android:src="@drawable/crop__ic_cancel" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:orientation="horizontal">

        <ImageButton
            android:id="@+id/buttonRotateLeft"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:padding="@dimen/margin5"
            android:src="@drawable/rotate_left" />

        <ImageButton
            android:id="@+id/buttonRotateRight"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:padding="@dimen/margin5"
            android:src="@drawable/rotate_right" />

    </LinearLayout>

    <ImageButton
        android:id="@+id/buttonDone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:background="?attr/selectableItemBackgroundBorderless"
        android:padding="16dp"
        android:src="@drawable/crop__ic_done" />
</RelativeLayout>

  1. REQUEST_CODE_FOR_IMAGE_CROPPING 的 OnActivity 结果写在下面的代码
if (requestCode == REQUEST_CODE_FOR_IMAGE_CROPPING ){
        if (resultCode == RESULT_OK ) {
            mExecutor = Executors.newSingleThreadExecutor();
            Uri myUri = data.getData();
            mExecutor.submit(new LoadScaledImageTask(this, myUri, profileImage, calcImageSize()));
            imageTypedFile = new TypedFile("multipart/form-data", new File(myUri.toString().substring(7)));
        } else if (resultCode == RESULT_CANCELED){
            DialogManager.showToast(BigFarmerActivity.this, getString(R.string.user_cancelled_image_cropping));
        }
    }

【讨论】:

    【解决方案2】:

    经过一番挣扎,我找到了答案。该库正在从 MediaStore 中提取 exif 数据,但我没有将我的临时文件存储在那里。我想到了两种可能的解决方案。首先是在裁剪前读取exif方向,裁剪后设置orientation属性。另一种方法是将文件保存到媒体存储中。

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

    【讨论】:

    • 我需要在哪里写这个?
    • 拍照后@Tara
    【解决方案3】:

    你可以试试这个库https://github.com/Yalantis/uCrop 它可以旋转图像。

    【讨论】:

      猜你喜欢
      • 2015-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-03
      • 2017-09-06
      相关资源
      最近更新 更多