Tomar la imagen de la cámara personalizada se estira cuando guardar en ImageView

Estoy utilizando este código para guardar la imagen en Imageview, pero la imagen se estira cuando dsave en imageview. Previsualización de la cámara es prefecto y haga clic en la imagen de la derecha, pero cuando se establece que la imagen en imageview la imagen es stetched.

public void onPicTaken(byte[] data) { if (data != null) { int screenWidth = getResources().getDisplayMetrics().widthPixels; int screenHeight = getResources().getDisplayMetrics().heightPixels; Bitmap bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { // Notice that width and height are reversed Bitmap scaled = Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true); int w = scaled.getWidth(); int h = scaled.getHeight(); // Setting post rotate to 90 Matrix mtx = new Matrix(); mtx.postRotate(90); // Rotating Bitmap bm = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, true); }else{// LANDSCAPE MODE //No need to reverse width and height Bitmap scaled = Bitmap.createScaledBitmap(bm, screenWidth,screenHeight , true); bm=scaled; } ivCaptureImagePreview.setImageBitmap(bm); ivCaptureImagePreview.setVisibility(View.VISIBLE); } } 

Utilice la siguiente clase para crear mapas de bits escalados

 public class ScalingUtilities { /** * Utility function for decoding an image resource. The decoded bitmap will * be optimized for further scaling to the requested destination dimensions * and scaling logic. * * @param res The resources object containing the image data * @param resId The resource id of the image data * @param dstWidth Width of destination area * @param dstHeight Height of destination area * @param scalingLogic Logic to use to avoid image stretching * @return Decoded bitmap */ public static Bitmap decodeResource(Resources res, int resId, int dstWidth, int dstHeight, ScalingLogic scalingLogic) { Options options = new Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); options.inJustDecodeBounds = false; options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth, dstHeight, scalingLogic); Bitmap unscaledBitmap = BitmapFactory.decodeResource(res, resId, options); return unscaledBitmap; } /** * Utility function for creating a scaled version of an existing bitmap * * @param unscaledBitmap Bitmap to scale * @param dstWidth Wanted width of destination bitmap * @param dstHeight Wanted height of destination bitmap * @param scalingLogic Logic to use to avoid image stretching * @return New scaled bitmap object */ public static Bitmap createScaledBitmap(Bitmap unscaledBitmap, int dstWidth, int dstHeight, ScalingLogic scalingLogic) { Rect srcRect = calculateSrcRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(), dstWidth, dstHeight, scalingLogic); Rect dstRect = calculateDstRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(), dstWidth, dstHeight, scalingLogic); Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(), dstRect.height(), Config.ARGB_8888); Canvas canvas = new Canvas(scaledBitmap); canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(Paint.FILTER_BITMAP_FLAG)); return scaledBitmap; } /** * ScalingLogic defines how scaling should be carried out if source and * destination image has different aspect ratio. * * CROP: Scales the image the minimum amount while making sure that at least * one of the two dimensions fit inside the requested destination area. * Parts of the source image will be cropped to realize this. * * FIT: Scales the image the minimum amount while making sure both * dimensions fit inside the requested destination area. The resulting * destination dimensions might be adjusted to a smaller size than * requested. */ public static enum ScalingLogic { CROP, FIT } /** * Calculate optimal down-sampling factor given the dimensions of a source * image, the dimensions of a destination area and a scaling logic. * * @param srcWidth Width of source image * @param srcHeight Height of source image * @param dstWidth Width of destination area * @param dstHeight Height of destination area * @param scalingLogic Logic to use to avoid image stretching * @return Optimal down scaling sample size for decoding */ public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight, ScalingLogic scalingLogic) { if (scalingLogic == ScalingLogic.FIT) { final float srcAspect = (float)srcWidth / (float)srcHeight; final float dstAspect = (float)dstWidth / (float)dstHeight; if (srcAspect > dstAspect) { return srcWidth / dstWidth; } else { return srcHeight / dstHeight; } } else { final float srcAspect = (float)srcWidth / (float)srcHeight; final float dstAspect = (float)dstWidth / (float)dstHeight; if (srcAspect > dstAspect) { return srcHeight / dstHeight; } else { return srcWidth / dstWidth; } } } /** * Calculates source rectangle for scaling bitmap * * @param srcWidth Width of source image * @param srcHeight Height of source image * @param dstWidth Width of destination area * @param dstHeight Height of destination area * @param scalingLogic Logic to use to avoid image stretching * @return Optimal source rectangle */ public static Rect calculateSrcRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight, ScalingLogic scalingLogic) { if (scalingLogic == ScalingLogic.CROP) { final float srcAspect = (float)srcWidth / (float)srcHeight; final float dstAspect = (float)dstWidth / (float)dstHeight; if (srcAspect > dstAspect) { final int srcRectWidth = (int)(srcHeight * dstAspect); final int srcRectLeft = (srcWidth - srcRectWidth) / 2; return new Rect(srcRectLeft, 0, srcRectLeft + srcRectWidth, srcHeight); } else { final int srcRectHeight = (int)(srcWidth / dstAspect); final int scrRectTop = (int)(srcHeight - srcRectHeight) / 2; return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight); } } else { return new Rect(0, 0, srcWidth, srcHeight); } } /** * Calculates destination rectangle for scaling bitmap * * @param srcWidth Width of source image * @param srcHeight Height of source image * @param dstWidth Width of destination area * @param dstHeight Height of destination area * @param scalingLogic Logic to use to avoid image stretching * @return Optimal destination rectangle */ public static Rect calculateDstRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight, ScalingLogic scalingLogic) { if (scalingLogic == ScalingLogic.FIT) { final float srcAspect = (float)srcWidth / (float)srcHeight; final float dstAspect = (float)dstWidth / (float)dstHeight; if (srcAspect > dstAspect) { return new Rect(0, 0, dstWidth, (int)(dstWidth / srcAspect)); } else { return new Rect(0, 0, (int)(dstHeight * srcAspect), dstHeight); } } else { return new Rect(0, 0, dstWidth, dstHeight); } } } 

Y utilizar esta clase en su función como a continuación

 public void onPicTaken(byte[] data) { if (data != null) { int screenWidth = getResources().getDisplayMetrics().widthPixels; int screenHeight = getResources().getDisplayMetrics().heightPixels; Bitmap bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { // Notice that width and height are reversed Bitmap scaled = ScalingUtilities.createScaledBitmap(bm, screenHeight, screenWidth, ScalingLogic.FIT); int w = scaled.getWidth(); int h = scaled.getHeight(); // Setting post rotate to 90 Matrix mtx = new Matrix(); mtx.postRotate(90); // Rotating Bitmap bm = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, true); }else{// LANDSCAPE MODE //No need to reverse width and height Bitmap scaled = ScalingUtilities.createScaledBitmap(bm, screenHeight, screenWidth, ScalingLogic.FIT); bm=scaled; } ivCaptureImagePreview.setImageBitmap(bm); ivCaptureImagePreview.setVisibility(View.VISIBLE); } } 

Configuración de UIImageView

 <ImageView android:id="@id/img" android:layout_width="match_parent" android:layout_height="wrap_content" android:adjustViewBounds="true" android:scaleType="fitCenter" /> 

Mi aplicación de prueba para este problema

Para obtener la imagen de la cámara, utilizo los siguientes métodos:

 private void pickImageIntent() { Intent pickPhoto = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); getCurrentActivity().startActivityForResult(pickPhoto, REQUEST_PICK_IMAGE); } private void takeImageIntent() { try { File outputDir = getCurrentActivity().getExternalCacheDir(); File outputFile = File.createTempFile("prefix", "extension", outputDir); selectedImageUri = Uri.fromFile(outputFile); Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); takePicture.putExtra(MediaStore.EXTRA_OUTPUT, selectedImageUri); getCurrentActivity().startActivityForResult(takePicture, REQUEST_TAKE_IMAGE); } catch (IOException e) { e.printStackTrace(); } } 

Para obtener el resultado de la cámara o el selector de imágenes, y muéstrelo en la imagenVista. Aquí this.myInterfaceImage :

 public void onActivityResult(int requestCode, int resultCode, Intent data) { switch(requestCode) { case REQUEST_PICK_IMAGE: if(resultCode == Activity.RESULT_OK) { selectedImageUri = data.getData(); initImage(selectedImageUri); } break; case REQUEST_TAKE_IMAGE: if(resultCode == Activity.RESULT_OK) { initImage(selectedImageUri); } break; } } protected void initImage(Uri selectedImageUri_) { try { ParcelFileDescriptor parcelFileDescriptor = getContext().getContentResolver().openFileDescriptor(selectedImageUri_, "r"); FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor(); Bitmap source = BitmapFactory.decodeFileDescriptor(fileDescriptor); float ratio = (float)source.getWidth() / (float)source.getHeight(); // here perhaps limit the size of the image int height = Math.min(getContext().getResources().getDisplayMetrics().heightPixels, source.getHeight()); int width = (int)(ratio*height); Bitmap result = Bitmap.createScaledBitmap(source, width, height, false); this.interfaceImage.setImageBitmap(result); if (result != source) { source.recycle(); } } catch (Exception ex) { System.out.println("File not found"); } } 

Así es como lo utilicé en Mi aplicación de prueba y funciona. No tengo problemas de orientación. He probado en el modo vertical con retrato y paisaje, y en modo horizontal con retrato y paisaje. Y con ambos en donde cambié la orientación después de conseguir la imagen.

Si está usando la cámara personalizada y la orientación es incorrecta con el código anterior, simplemente añada esto

Hay dos cosas necesarias:

  1. La vista previa de la cámara necesita lo mismo que su rotación. Establecer esto por

    camera.setDisplayOrientation(result);

  2. Guarde la imagen capturada como previsualización de la cámara. Haga esto a través de Camera.Parameters.

    int mRotation = getCameraDisplayOrientation(); Camera.Parameters parameters = camera.getParameters(); parameters.setRotation(mRotation); //set rotation to save the picture camera.setDisplayOrientation(result); //set the rotation for preview camera camera.setParameters(parameters);

A continuación, puede utilizar su función sin la orientación de cosas

 public void onPicTaken(byte[] data) { if (data != null) { Bitmap bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0); int screenWidth = getResources().getDisplayMetrics().widthPixels; float ratio = (float)bm.getWidth() / (float)bm.getHeight(); int screenHeight = (int)(ratio*screenWidth) Bitmap scaled = Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true); if (scaled != bm) { source.recycle(); } ivCaptureImagePreview.setImageBitmap(scaled); ivCaptureImagePreview.setVisibility(View.VISIBLE); } } 

Espero que ayude.

Utilice esto para evitar que la imagen se estire y mantenga la relación de aspecto de la imagen

 android:scaleType="fitXY" // or desired scale type android:adjustViewBounds="true" 

Utilizo esta función en mi proyecto, por favor compruebe si es útil para usted.

 public static Bitmap Preview(String path) { //SCALE IMAGE int SCALE = 4; try { BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = SCALE; Bitmap bitmap = BitmapFactory.decodeFile(path, o2); OutputStream os = new FileOutputStream(path); bitmap.compress(Bitmap.CompressFormat.PNG, 100, os); os.flush(); os.close(); File file = new File(path); while (file.length() > 800000) { SCALE += 2; o2.inSampleSize = SCALE; bitmap = BitmapFactory.decodeFile(path, o2); os = new FileOutputStream(path); bitmap.compress(Bitmap.CompressFormat.PNG, 100, os); os.flush(); os.close(); file = new File(path); } bitmap = BitmapFactory.decodeFile(path, o2); return bitmap; } catch (Exception e) { e.printStackTrace(); return null; } } 

Puede establecer scaleType en xml

 <ImageView android:id="@+id/iv_imageview" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitCenter" /> 

En código Java puede lograr lo mismo como este

 ImageView mImageView = (ImageView) findViewById(R.id.iv_imageview); mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER); 

Escala de su mapa de bits con Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true); No mantendrá la relación de aspecto porque esto se extenderá el ancho y la altura del mapa de bits para coincidir con el destino.

Una opción sería calcular la altura objetivo manualmente para que no se produzca ningún cultivo:

 double aspectRatio = (double) source.getHeight() / (double) source.getWidth(); int targetHeight = (int) (screenWidth * aspectRatio); 

Y luego use targetHeight lugar de screenHeight como argumento height en createScaledBitmap ().

Además, asegúrese de que la vista de imagen en la que cargue su mapa de bits tenga el tipo de escala apropiado (por ejemplo, FIT_CENTER o CENTER_CROP).

Utilizar este putExtra en su intención de llamar a la cámara

 intent.putExtra("outputX", 80); intent.putExtra("outputY", 80); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 20); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, Utility.REQUEST_FOR_CAMERA); 
  • Permisos de cámara en Appcelerator
  • Android 1.6 Rotación de la cámara?
  • Ya sea Foto o Live Face Cómo comprobar con la cámara Android
  • Cómo cambiar la cámara de la parte delantera a la parte posterior y posterior a la parte delantera en el botón haga clic en android
  • La cámara de Android tiene una imagen de múltiples bugs para algunos usuarios
  • Apache cordova aplicación de reinicio de la cámara en la galaxia S5
  • Android: cómo capturar la imagen sin mostrar la vista previa
  • Captura de imagen sin permiso con Android 6.0
  • Luz de flash no detectada
  • Uso de la cámara de teléfonos, después de capturar la actividad de la imagen no volver a la actividad particular
  • Android: Editar la intención de la imagen
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.