如何设置输出图像使用 com.android.camera.action.CROP

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12758425/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 11:40:03  来源:igfitidea点击:

how to set the output image use com.android.camera.action.CROP

androidimageimage-processingcrop

提问by adi.zean

I have code to crop an image, like this :

我有代码来裁剪图像,如下所示:

public void doCrop(){
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setType("image/");
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent,0);
int size = list.size();
if (size == 0 ){
   Toast.makeText(this, "Cant find crop app").show();
   return;
} else{
   intent.setData(selectImageUri);
   intent.putExtra("outputX", 300);
   intent.putExtra("outputY", 300);
   intent.putExtra("aspectX", 1);
   intent.putExtra("aspectY", 1);
   intent.putExtra("scale", true);
   intent.putExtra("return-data", true);
   if (size == 1) {
       Intent i = new Intent(intent);
       ResolveInfo res = list.get(0);
       i.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
       startActivityForResult(i, CROP_RESULT);
   }
}
}

public void onActivityResult (int requestCode, int resultCode, Intent dara){
   if (resultCode == RESULT_OK){
      if (requestCode == CROP_RESULT){
          Bundle extras = data.getExtras();
          if (extras != null){
              bmp = extras.getParcelable("data");
          }
          File f = new File(selectImageUri.getPath());
          if (f.exists()) f.delete();
          Intent inten3 = new Intent(this, tabActivity.class);
          startActivity(inten3);
      }
   }
}

from what i have read, the code intent.putExtra("outputX", 300); intent.putExtra("outputY", 300);is use to set the resolution of crop result, but why i can't get the result image resolution higer than 300x300? when I set the intent.putExtra("outputX", 800); intent.putExtra("outputY", 800);the crop function has no result or crash, any idea for this situation?

从我读过的内容来看,该代码intent.putExtra("outputX", 300); intent.putExtra("outputY", 300);用于设置裁剪结果的分辨率,但为什么我无法获得高于 300x300 的结果图像分辨率?当我设置intent.putExtra("outputX", 800); intent.putExtra("outputY", 800);裁剪功能没有结果或崩溃时,对这种情况有什么想法吗?

the log cat say "! ! ! FAILED BINDER TRANSACTION ! ! !

日志猫说“!!!失败的绑定交易!!!

采纳答案by Anup Cowkur

That Intent is not part of the public Android API and is not guaranteed to work on all devices. It was used in earlier versions of android 1.x and 2.x but it's not used anymore and is not recommended. That is probably why it's crashing all over the palce or working improperly.

该 Intent 不是公共 Android API 的一部分,并且不能保证在所有设备上都可以使用。它在早期版本的 android 1.x 和 2.x 中使用,但不再使用,不推荐使用。这可能就是它在整个地方崩溃或工作不正常的原因。

Use methods such as Bitmap.createBitmap(..)or Bitmap.createScaledBitmap(..)to create a resized or cropped version of your original image. These are part of the Android API and are guaranteed to work.

使用诸如Bitmap.createBitmap(..)或 之类的方法Bitmap.createScaledBitmap(..)来创建原始图像的调整大小或裁剪版本。这些是 Android API 的一部分,保证可以正常工作。

See official docs hereand here

在此处此处查看官方文档

To crop a bitmap, you can use Bitmap.createBitmap(Bitmap, int x, int y, int width, int height). For example, if you need to crop 10 pixels from each side of a bitmap then use this:

要裁剪位图,您可以使用Bitmap.createBitmap(Bitmap, int x, int y, int width, int height). 例如,如果您需要从位图的每一侧裁剪 10 个像素,请使用以下命令:

Bitmap croppedBitmap = Bitmap.createBitmap(originalBitmap, 10, 10, originalBitmap.getWidth() - 20, originalBitmap.getHeight() - 20);

If you need to show the selector to the user. Then you can do something like this:

如果您需要向用户显示选择器。然后你可以做这样的事情:

private static final String TEMP_PHOTO_FILE = "temporary_holder.jpg";  

Intent photoPickerIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
photoPickerIntent.setType("image/*");
photoPickerIntent.putExtra("crop", "true");
photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
photoPickerIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(photoPickerIntent, REQ_CODE_PICK_IMAGE);


    private Uri getTempUri() {
    return Uri.fromFile(getTempFile());
    }

    private File getTempFile() {
    if (isSDCARDMounted()) {

    File f = new File(Environment.getExternalStorageDirectory(),TEMP_PHOTO_FILE);
    try {
    f.createNewFile();
    } catch (IOException e) {

    }
    return f;
    } else {
    return null;
    }
    }

    private boolean isSDCARDMounted(){
    String status = Environment.getExternalStorageState();
    if (status.equals(Environment.MEDIA_MOUNTED))
    return true;
    return false;
    }




protected void onActivityResult(int requestCode, int resultCode,
        Intent imageReturnedIntent) {
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent);

    switch (requestCode) {
    case REQ_CODE_PICK_IMAGE:
        if (resultCode == RESULT_OK) {  
          if (imageReturnedIntent!=null){



               File tempFile = getTempFile();

              String filePath= Environment.getExternalStorageDirectory()
            + "/temporary_holder.jpg";
              System.out.println("path "+filePath);


    Bitmap selectedImage =  BitmapFactory.decodeFile(filePath);
    _image = (ImageView) findViewById(R.id.image);
    _image.setImageBitmap(selectedImage );

}
}
}

code from here

来自这里的代码

回答by hcpl

This question is all over stackoverflow. And I'm glad it is since I had to sort this out myself recently. I'll do my best to mark some duplicates as I go but I prefer this one since it addresses the issue with the limited image size.

这个问题遍布stackoverflow。我很高兴这是因为我最近不得不自己解决这个问题。我会尽我所能标记一些重复的内容,但我更喜欢这个,因为它解决了图像大小有限的问题。

Short Answer

简答

The short answer is not to use the return-data option. Read more about that option and how to retrieve the image then here: http://www.androidworks.com/crop_large_photos_with_android. The article does a great job listing the (known) configuration options for the Intent and how to use them.

简短的回答是不要使用返回数据选项。在此处阅读有关该选项以及如何检索图像的更多信息:http: //www.androidworks.com/crop_large_photos_with_android。这篇文章很好地列出了 Intent 的(已知)配置选项以及如何使用它们。

Option #2: If you set return-data to "false", you will not receive a Bitmap back from the onActivityResult Intent in-line, instead you will need to set MediaStore.EXTRA_OUTPUT to a Uri (of File scheme only) where you want the Bitmap to be stored. This has some restrictions, first you need to have a temp filesystem location in order to give the file scheme URI, not a huge problem (except on some devices that don't have sdcards).

选项#2:如果您将 return-data 设置为“false”,您将不会从内联的 onActivityResult Intent 接收到位图,而是需要将 MediaStore.EXTRA_OUTPUT 设置为您所在的 Uri(仅限文件方案)想要存储位图。这有一些限制,首先您需要有一个临时文件系统位置,以便为文件方案提供 URI,这不是一个大问题(在某些没有 sdcard 的设备上除外)。

    /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    thiz = this;
    setContentView(R.layout.main);
    mBtn = (Button) findViewById(R.id.btnLaunch);
    photo = (ImageView) findViewById(R.id.imgPhoto);
    mBtn.setOnClickListener(new OnClickListener(){

        public void onClick(View v) {
            try {
                // Launch picker to choose photo for selected contact
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
                intent.setType("image/*");
                intent.putExtra("crop", "true");
                intent.putExtra("aspectX", aspectX);
                intent.putExtra("aspectY", aspectY);
                intent.putExtra("outputX", outputX);
                intent.putExtra("outputY", outputY);
                intent.putExtra("scale", scale);
                intent.putExtra("return-data", return_data);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
                intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
                intent.putExtra("noFaceDetection",!faceDetection); // lol, negative boolean noFaceDetection
                if (circleCrop) {
                    intent.putExtra("circleCrop", true);
                }

                startActivityForResult(intent, PHOTO_PICKED);
            } catch (ActivityNotFoundException e) {
                Toast.makeText(thiz, R.string.photoPickerNotFoundText, Toast.LENGTH_LONG).show();
            }
        }
    });
}

private Uri getTempUri() {
    return Uri.fromFile(getTempFile());
}

private File getTempFile() {
    if (isSDCARDMounted()) {
        File f = new File(Environment.getExternalStorageDirectory(),TEMP_PHOTO_FILE);
        try {
            f.createNewFile();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            Toast.makeText(thiz, R.string.fileIOIssue, Toast.LENGTH_LONG).show();
        }
        return f;
    } else {
        return null;
    }
}

private boolean isSDCARDMounted(){
    String status = Environment.getExternalStorageState();    
    if (status.equals(Environment.MEDIA_MOUNTED))
        return true;
    return false;
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode) {
        case PHOTO_PICKED:
            if (resultCode == RESULT_OK) {
                if (data == null) {
                    Log.w(TAG, "Null data, but RESULT_OK, from image picker!");
                    Toast.makeText(this, R.string.no_photo_picked,
Toast.LENGTH_SHORT).show();
                    return;
                }

            final Bundle extras = data.getExtras();
            if (extras != null) {
                File tempFile = getTempFile();
                // new logic to get the photo from a URI
                if (data.getAction() != null) {
                    processPhotoUpdate(tempFile);
                }
            }
        }
        break;
    }
}

Code example from: http://www.androidworks.com/crop_large_photos_with_android

代码示例来自:http: //www.androidworks.com/crop_large_photos_with_android

More Information

更多信息

The long answer is not to use that intent at all. Continue reading to find out why.

长答案是根本不使用该意图。继续阅读以找出原因。

Unofficial API

非官方 API

The core of the problem is the unofficial intent. Unofficial as in not part of the public API. Currently it works for most devices but most just isn't enough. Also Google can change this intent anytime without letting you know. Breaking along all the apps using it. Much like how the calendar API was once unofficial. In fact this crop intent has already changed once. So avoid using this intent. There are alternatives. Feel free to ignore this advice.

问题的核心是非官方意图。非官方,因为不是公共 API 的一部分。目前它适用于大多数设备,但大多数还不够。此外,Google 可以随时更改此意图,而无需让您知道。打破所有使用它的应用程序。就像日历 API 曾经是非官方的一样。事实上,这种作物意图已经改变过一次。所以避免使用这个意图。有替代方案。请随意忽略此建议。

Just to proof the "works for some devices statement" follow this link and enjoy frustrated Android developers discussing what should be considered part of the core android features (and isn't): https://code.google.com/p/android/issues/detail?id=1480

只是为了证明“适用于某些设备声明”,请点击此链接并享受沮丧的 Android 开发人员讨论什么应该被视为核心 android 功能的一部分(而不是):https: //code.google.com/p/android /issues/detail?id=1480

Time for example code? Check this github project: https://github.com/lorensiuswlt/AndroidImageCrop

示例代码的时间?检查这个 github 项目:https: //github.com/lorensiuswlt/AndroidImageCrop

About Size Limit

关于大小限制

Another issue I experienced while exploring this intent is the image crop size limit. This can easily be reproduced using the above example code and an image size of anything above 300 pixels. Basically what this original question is all about. In the best case your app will crash. But I've seen worse up to hanging devices that could only be reset by removing the battery.

我在探索这个意图时遇到的另一个问题是图像裁剪大小限制。这可以使用上面的示例代码和大于 300 像素的任何图像大小轻松重现。基本上这个原始问题是关于什么的。在最好的情况下,您的应用程序会崩溃。但我见过更糟糕的悬挂设备,只能通过取出电池来重置。

Now if you remove that 'return-data' option you'll be able to run it again. More information on how to get to the result is found in the short answer where I referenced this link already: http://www.androidworks.com/crop_large_photos_with_android

现在,如果您删除该 'return-data' 选项,您将能够再次运行它。有关如何获得结果的更多信息可以在我已经引用此链接的简短回答中找到:http: //www.androidworks.com/crop_large_photos_with_android

The Solution

解决方案

So a lot of problems. Problems require a solution. The only decent solution until Google comes up with a public API for this is to provide your own crop intent. Just get your hands on a proper crop library like this one on github: https://github.com/lvillani/android-cropimage

所以问题很多。问题需要解决方案。在谷歌为此提供公共 API 之前,唯一合适的解决方案是提供您自己的裁剪意图。只需在 github 上获取一个像这样的合适的裁剪库:https: //github.com/lvillani/android-cropimage

The project lacks some documentation but since it's an extract of the unofficial android crop intent you can use the examples listed on top to get started. Just make sure not to use the return-data option. Ah and check out the CropImageIntentBuilder class. That should let you easily create an intent for the cropping. Don't forget to add this Activity to your manifest and the permissions to write to external data storage.

该项目缺乏一些文档,但由于它是非官方 android 裁剪意图的摘录,您可以使用顶部列出的示例开始。只要确保不要使用返回数据选项。啊,看看 CropImageIntentBuilder 类。这应该让您轻松创建裁剪意图。不要忘记将此活动添加到您的清单以及写入外部数据存储的权限。

private void doCrop(File croppedResult){
        CropImageIntentBuilder builder = new CropImageIntentBuilder(600,600, croppedResult);
        // don't forget this, the error handling within the library is just ignoring if you do
        builder.setSourceImage(mImageCaptureUri);
        Intent  intent = builder.getIntent(getApplicationContext());
        // do not use return data for big images
        intent.putExtra("return-data", false);
        // start an activity and then get the result back in onActivtyResult
        startActivityForResult(intent, CROP_FROM_CAMERA);
    }

Using this library also opens the doors to more customisation. Good to know is the core bitmap functionally used for resizing: How to crop the parsed image in android?

使用这个库还为更多的定制打开了大门。很高兴知道在功能上用于调整大小的核心位图:如何在 android 中裁剪解析的图像?

And that's it. Enjoy!

就是这样。享受!