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

我有代码来裁剪图像,像这样:

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); } } } 

从我读过的代码intent.putExtra("outputX", 300); intent.putExtra("outputY", 300); intent.putExtra("outputX", 300); intent.putExtra("outputY", 300); 是用来设置裁剪结果的分辨率,但为什么我不能得到高于300×300的结果图像分辨率? 当我设置intent.putExtra("outputX", 800); intent.putExtra("outputY", 800); intent.putExtra("outputX", 800); intent.putExtra("outputY", 800); 作物function没有结果或崩溃,这种情况的任何想法?

日志猫说“!!!失败的BINDER TRANSACTION!!

Solutions Collecting From Web of "如何设置输出图像使用com.android.camera.action.CROP"

该意图不是公开的Android API的一部分,并不保证在所有设备上工作。 它在早期版本的android 1.x和2.x中使用,但不再使用,不推荐使用。 这可能是为什么它崩溃或工作不正常。

使用诸如Bitmap.createBitmap(..)Bitmap.createScaledBitmap(..)来创build原始图像的resize或裁剪后的版本。 这些是Android API的一部分,并保证工作。

在这里和这里查看官方文档

要裁剪位图,可以使用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); 

如果您需要向用户显示select器。 那么你可以做这样的事情:

 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 ); } } } 

代码从这里

这个问题遍布整个计算器。 而且我很高兴,因为我最近不得不自己把这个问题弄清楚。 我会尽我所能标记一些重复的,但我更喜欢这一个,因为它解决了有限的图像大小的问题。

简答

简短的答案是不使用返回数据选项。 阅读更多有关该选项,以及如何检索图像,然后在这里: http : //www.androidworks.com/crop_large_photos_with_android 。 本文做了一个很好的工作,列出了Intent的(已知)configuration选项以及如何使用它们。

选项2:如果将返回数据设置为“false”,则不会从onActivityResult Intent内嵌回来接收到位图,而是需要将MediaStore.EXTRA_OUTPUT设置为Uri(仅限Filescheme)要存储位图。 这有一些限制,首先你需要有一个临时文件系统的位置,以提供文件scheme的URI,而不是一个巨大的问题(除了一些设备没有SD卡)。

  /** 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; } } 

以下代码示例: http : //www.androidworks.com/crop_large_photos_with_android

更多信息

漫长的答案是根本不使用这个意图。 继续阅读,找出原因。

非官方的API

问题的核心是非官方的意图。 不属于公共API的非官方的。 目前它适用于大多数设备,但大多数是不够的。 此外,Google可以随时更改此意图,而不会让您知道。 打破所有使用它的应用程序。 很像日历API曾经是非官方的。 实际上这个作物意图已经改变了一次。 所以避免使用这个意图。 有替代品。 随意忽略这个build议。

只是为了certificate“作品的一些设备声明”按照这个链接,并享受沮丧的Android开发人员讨论什么应该被视为核心的Androidfunction的一部分(而不是): https : //code.google.com/p/android /问题/细节?ID = 1480

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

关于大小限制

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

现在,如果您删除“返回数据”选项,您将能够再次运行它。 有关如何获得结果的更多信息,请参阅我已经引用此链接的简短答案: http : //www.androidworks.com/crop_large_photos_with_android

解决scheme

所以很多问题。 问题需要解决scheme。 直到Google为此提供一个公共API的唯一体面的解决scheme是提供您自己的作物意图。 只要把你的手放在github上的这个适当的作物库上: https : //github.com/lvillani/android-cropimage

该项目缺乏一些文件,但由于它是非官方的Android作物意图的摘录,您可以使用上面列出的例子开始。 只要确保不要使用返回数据选项。 啊,并检查出CropImageIntentBuilder类。 这应该让你轻松创build一个剪裁的意图。 不要忘记将此Activity添加到清单以及写入外部数据存储的权限。

 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); } 

使用这个库也打开了更多定制的大门。 有用的知识是resize的核心位图function: 如何在Android中裁剪parsing的图像?

就是这样。 请享用!