cómo configurar la imagen de salida use com.android.camera.action.CROP

Tengo un código para recortar una imagen, así:

public void doCrop(){ Intent intent = new Intent("com.android.camera.action.CROP"); intent.setType("image/"); List 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); } } } 

por lo que he leído, el código intent.putExtra("outputX", 300); intent.putExtra("outputY", 300); intent.putExtra("outputX", 300); intent.putExtra("outputY", 300); Se usa para establecer la resolución del resultado del cultivo, pero ¿por qué no puedo obtener una resolución de imagen de resultado superior a 300×300? cuando configuro intent.putExtra("outputX", 800); intent.putExtra("outputY", 800); intent.putExtra("outputX", 800); intent.putExtra("outputY", 800); la función de recorte no tiene ningún resultado o falla, ¿alguna idea para esta situación?

el log cat dice “¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡”.

Esa intención no es parte de la API pública de Android y no se garantiza que funcione en todos los dispositivos. Se usó en versiones anteriores de Android 1.xy 2.x pero ya no se usa y no se recomienda. Esa es probablemente la razón por la que se cuelga por todas partes o funciona incorrectamente.

Utilice métodos como Bitmap.createBitmap(..) o Bitmap.createScaledBitmap(..) para crear una versión redimensionada o recortada de su imagen original. Estos son parte de la API de Android y están garantizados para funcionar.

Vea los documentos oficiales aquí y aquí

Para recortar un bitmap, puede usar Bitmap.createBitmap(Bitmap, int x, int y, int width, int height) . Por ejemplo, si necesita recortar 10 píxeles de cada lado de un bitmap, utilice esto:

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

Si necesita mostrar el selector al usuario. Entonces puedes hacer algo como esto:

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

código de aquí

Esta pregunta está en todo stackoverflow. Y me alegro de que sea así porque tuve que resolver esto recientemente. Haré todo lo posible para marcar algunos duplicados a medida que avance, pero prefiero este ya que aborda el problema con el tamaño de imagen limitado.

Respuesta corta

La respuesta corta es no usar la opción de devolución de datos. Lea más sobre esa opción y cómo recuperar la imagen, luego aquí: http://www.androidworks.com/crop_large_photos_with_android . El artículo hace un excelente trabajo al listar las opciones de configuración (conocidas) para el Intent y cómo usarlas.

Opción n. ° 2: si configura los datos de retorno en “falso”, no recibirá un bitmap de la activación de onActivityResult en línea, sino que tendrá que establecer MediaStore.EXTRA_OUTPUT en un Uri (solo esquema de archivo) donde quiere que el Bitmap sea almacenado. Esto tiene algunas restricciones, primero debe tener una ubicación de sistema de archivos temporal para dar el URI del esquema de archivos, no es un gran problema (excepto en algunos dispositivos que no tienen tarjetas 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; } } 

Ejemplo de código de: http://www.androidworks.com/crop_large_photos_with_android

Más información

La respuesta larga es no usar ese bash en absoluto. Continúa leyendo para descubrir por qué.

API no oficial

El núcleo del problema es la intención no oficial. No oficial ya que no forma parte de la API pública. Actualmente funciona para la mayoría de los dispositivos, pero la mayoría simplemente no es suficiente. Además, Google puede cambiar esta intención en cualquier momento sin avisarle. Rompiendo con todas las aplicaciones que lo usan. Al igual que la API de calendario fue una vez no oficial. De hecho, esta intención de cultivo ya ha cambiado una vez. Así que evita usar esta intención. Hay alternativas. Siéntase libre de ignorar este consejo.

Solo para probar la afirmación “funciona para algunos dispositivos”, siga este enlace y disfrute de los frustrados desarrolladores de Android que debaten sobre qué se debe considerar como parte de las funciones básicas de Android (y no lo es): https://code.google.com/p/android / issues / detail? id = 1480

Hora por ejemplo código? Verifique este proyecto github: https://github.com/lorensiuswlt/AndroidImageCrop

Sobre el límite de tamaño

Otro problema que experimenté al explorar esta intención es el límite de tamaño de recorte de la imagen. Esto puede reproducirse fácilmente utilizando el código de ejemplo anterior y un tamaño de imagen de cualquier cosa superior a 300 píxeles. Básicamente de qué se trata esta pregunta original. En el mejor de los casos, tu aplicación fallará. Pero he visto cosas peores que colgar dispositivos que solo se podían restablecer extrayendo la batería.

Ahora, si elimina esa opción ‘devolver datos’, podrá ejecutarla nuevamente. Se encuentra más información sobre cómo llegar al resultado en la breve respuesta donde ya hice referencia a este enlace: http://www.androidworks.com/crop_large_photos_with_android

La solución

Entonces muchos problemas. Los problemas requieren una solución. La única solución decente hasta que Google obtenga una API pública para esto es proporcionar su propio bash de cultivo. Solo ponga sus manos en una biblioteca de cultivos adecuada como esta en github: https://github.com/lvillani/android-cropimage

El proyecto carece de documentación, pero dado que es un extracto del bash de cultivo no oficial de Android, puede utilizar los ejemplos enumerados en la parte superior para comenzar. Solo asegúrate de no usar la opción de devolución de datos. Ah, y mira la clase CropImageIntentBuilder. Eso debería permitirle crear fácilmente una intención para el cultivo. No olvide agregar esta actividad a su manifiesto y los permisos para escribir en el almacenamiento de datos externo.

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

El uso de esta biblioteca también abre las puertas a una mayor personalización. Es bueno saber que el bitmap central se usa funcionalmente para redimensionar: ¿Cómo recortar la imagen analizada en Android?

Y eso es. ¡Disfrutar!