在Android中从图库选择图片时裁剪图片

26

我想在我的应用程序中从图库选择图片后进行裁剪。 比如说,如果我启动图库并选择一张图片,则应该出现裁剪窗口,就像我们从iPhone中选择图片时一样。这在Android中可行吗?

我找到了一个有关在Android中裁剪图像的教程,但似乎不是我想要的方式。

http://www.coderzheaven.com/2011/03/15/crop-an-image-in-android/


请查看此链接:https://dev59.com/gnI95IYBdhLWcg3w8iv1,希望能对您有所帮助。 - Simon Dorociak
看到我的回答,希望这是你要找的。如果你发现问题或者不理解代码,请让我知道。 - K_Anas
我在stackoverflow的帖子(https://stackoverflow.com/a/44089387/1448357)上分享了我的解决方案。 - Gaurav
6个回答

27

在Android中,可以使用com.android.camera.action.CROP来裁剪图像。从相册选择图像URL后,您可以启动裁剪编辑器:

Intent intent = new Intent("com.android.camera.action.CROP");  
intent.setClassName("com.android.camera", "com.android.camera.CropImage");  
File file = new File(filePath);  
Uri uri = Uri.fromFile(file);  
intent.setData(uri);  
intent.putExtra("crop", "true");  
intent.putExtra("aspectX", 1);  
intent.putExtra("aspectY", 1);  
intent.putExtra("outputX", 96);  
intent.putExtra("outputY", 96);  
intent.putExtra("noFaceDetection", true);  
intent.putExtra("return-data", true);                                  
startActivityForResult(intent, REQUEST_CROP_ICON);

当图片选择活动返回时,将选定内容保存在 onActivityResult 中:

Bundle extras = data.getExtras();  
if(extras != null ) {  
    Bitmap photo = extras.getParcelable("data");  
    ByteArrayOutputStream stream = new ByteArrayOutputStream();  
    photo.compress(Bitmap.CompressFormat.JPEG, 75, stream);  
        // The stream to write to a file or directly using the photo
}

并且查看这篇文章,它也可以帮助您在Android中裁剪图像


18
com.android.camera.action.CROP 操作是内部 API 的一部分,因此在所有情况下都无法正常工作。只是想提一下这一点 :) - Alex Lockwood
1
这在许多设备上都不起作用。Android没有CROP Intent:http://commonsware.com/blog/2013/01/23/no-android-does-not-have-crop-intent.html - CommonsWare
3
在我的情况下,data.getExtras() 返回一个 nullBundle,那么我该如何获取目标 Bitmap - SilentKnight
3
在5.0以上的照片应用程序中无法使用(在Nexus设备上,5.0版本之后的系统已经移除了相册应用程序)。 - silent_grave
@AlexLockwood 那么用什么来进行裁剪呢?而且 com.android.camera.action.CROP 在所有设备上都能完美运行,只有在联想设备上无法工作。它会显示一个提示,说明无法编辑小于50x50的图像!应该怎么办? - Dharmishtha
显示剩余5条评论

21

这个教程正是你需要的:

从图库中选择图片:

输入图像描述

在Intent选择操作后裁剪图片

输入图像描述

干杯


这个非常好用,完美的答案,而且使用起来非常简单。 - Divyanshu Negi
@K_Anas,你在这里描述的教程在API>19上无法工作。它显示了一个错误:“无法加载图像”。请在这里帮助我解决问题。 - Usman Khan
1
这不是一个好的解决方案,因为Intent不是Android的一部分,所以它不能在许多设备上工作。 - tobias

17

在选择/拍摄图片后,您已经可以告知相机/图库意图启动裁剪编辑器:

从图库中选择图片:

Intent pickImageIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

pickImageIntent.setType("image/*");
pickImageIntent.putExtra("crop", "true");
pickImageIntent.putExtra("outputX", 200);
pickImageIntent.putExtra("outputY", 200);
pickImageIntent.putExtra("aspectX", 1);
pickImageIntent.putExtra("aspectY", 1);
pickImageIntent.putExtra("scale", true);
pickImageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriWhereToStore);
pickImageIntent.putExtra("outputFormat",

Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(pickImageIntent, RESULT_LOAD_IMAGE);

拍照:

Intent takePicIntent = new Intent("android.media.action.IMAGE_CAPTURE");

takePicIntent .putExtra("crop", "true");
takePicIntent .putExtra("outputX", 200);
takePicIntent .putExtra("outputY", 200);
takePicIntent .putExtra("aspectX", 1);
takePicIntent .putExtra("aspectY", 1);
takePicIntent .putExtra("scale", true);
takePicIntent .putExtra(MediaStore.EXTRA_OUTPUT, uriWhereToStore);
takePicIntent .putExtra("outputFormat",

Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(takePicIntent , RESULT_LOAD_IMAGE);

3
那么如何编写与您的代码相对应的onActivityResult()函数? - SilentKnight
1
@AliParsa 在 onActivityResult() 中如何获取裁剪后的图像? - Ajay Sivan
1
仅适用于ACTION_PICK,不适用于IMAGE_CAPTURE。 - Vishal
这个解决方案只适用于ACTION_PICK,而不适用于IMAGE_CAPTURE,那么针对IMAGE_CAPTURE应该怎么做呢? - hetsgandhi

15

虽然是内部 API 的一部分,但 com.android.camera.action.CROP 似乎在大多数 Android 设备上都得到了良好的支持。以下内容可能会帮助你入门:

final Intent intent = new Intent("com.android.camera.action.CROP");
intent.setData(uriOfImageToCrop);
intent.putExtra("outputX", 400);
intent.putExtra("outputY", 400);
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("scale", true);
intent.putExtra("noFaceDetection", true);
intent.putExtra("output", Uri.fromFile(someOutputFile));
startActivityForResult(intent, SOME_RANDOM_REQUEST_CODE);

然后在您的ActivityonActivityResult()方法中处理您需要完成的操作,您的输出文件应该是裁剪后的图像。

然而,由于这个Intent动作是内部API的一部分,我强烈建议如果某台设备不支持Intent,请您有一些备用行为。一些制造商提供自己的相册应用程序,因此无法知道用户的设备是否会识别Intent请记得这一点!! :)


我正在寻找的是 intent.putExtra("output", Uri.fromFile(someOutputFile));。 - Amir Qayyum Khan
你能告诉我如何在logcat中打印裁剪后的(outputX,outputY ...)值吗? - Aditya Hari Kishan

0
没有人会告诉你需要哪个额外的东西,除非你尝试过:
   val intent = Intent(Intent.ACTION_PICK)
   intent.apply {
       type = "image/*"
       putExtra("crop", "true") // NOTE: should be string
       putExtra("outputX", 300) // This is needed, editor can't close without these two
       putExtra("outputY", 300) // This is needed

       putExtra("scale", true)
       putExtra("aspectX", 1)
       putExtra("aspectY", 1)
       putExtra("return-data", true)
   }
   startActivityForResult(intent, YOUR_INT_CODE)

它对我不起作用。你在onActivityResult()里有什么特别的东西吗? - ShadeToD
putExtra("return-data", true) 是做什么用的? - HB.

0

我用以下方式解决了这个问题

private void pickUserImage() { 

if (doHavePermission()) { 
    Intent photoPickerIntent = new Intent(Intent.ACTION_PICK,
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    photoPickerIntent.setType("image/*");
    photoPickerIntent.putExtra("crop", "true");
    photoPickerIntent.putExtra("scale", true);
    photoPickerIntent.putExtra("outputX", 256);
    photoPickerIntent.putExtra("outputY", 256);
    photoPickerIntent.putExtra("aspectX", 1);
    photoPickerIntent.putExtra("aspectY", 1);
    photoPickerIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
    photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
    startActivityForResult(photoPickerIntent, PICK_FROM_GALLERY);
    } 
}

在 StackOverflow 帖子中找到我的完整解决方案这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接