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); } }
- Cámara Android 2 api BufferQueue ha sido abandonada
- Cómo burlar una imagen en Android Emulator Camera?
- Inicie la aplicación de cámara nativa con la opción de capturar vídeo o imagen
- onActivityResult siempre obtiene Activity.RESULT_CANCELED cuando toma la imagen en FragmentActivity
- Cámara Android Api 2 Foco manual con toque
- SuperficieCreada () Nunca llamado
- La aplicación Phonegap se cierra después de que la cámara capture la imagen.
- Rotación de la matriz de bytes de JPEG después de onPictureTaken
- Cómo recuperar la vista previa de la cámara de dormir?
- ¿Cómo utilizar el feed de cámara en vivo como un fondo de actividad?
- Tamaño de la imagen de la cámara Android
- Android - crear una cámara virtual o sobrescribir el flujo real de la leva? (/ Dev / msm_camera / frame0, v4l2loopback)?
- La calidad de la imagen es mala usando cámara personalizada
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:
-
La vista previa de la cámara necesita lo mismo que su rotación. Establecer esto por
camera.setDisplayOrientation(result);
-
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);