2016-02-29 18 views
8

Sto utilizzando questo codice per salvare le immagini in Imageview ma l'immagine viene allungata quando si salva in visualizzazione immagini. L'anteprima della fotocamera è prefetta e fai clic sull'immagine destra, ma quando imposto quell'immagine in imageview l'immagine viene scaricata.L'acquisizione di immagini dalla telecamera personalizzata viene allungata quando si esegue il salvataggio in ImageView

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

} 

risposta

5

Usa seguente classe per la creazione di scala bitmap

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


} 

e utilizzare questa classe nella funzione, come di seguito

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

} 
+0

non può risolvere 'postRotate (90)'. Qualsiasi aiuto? –

+0

@SrujanBarai il suo metodo di matrice lo chiama sull'oggetto matrice Matrix mtx = new Matrix(); mtx.postRotate (90); – Ajinkya

0

Utilizzare questo impedirà immagine da stretching e mantenendo le proporzioni dell'immagine

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

Impostazioni UIImageView

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

mio Applicazione Test per questo problema

.210

per ottenere l'immagine della telecamera, ho utilizzare i seguenti metodi:

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

Per ottenere il risultato dalla fotocamera o immagine Picker, e vederlo in ImageView. Qui 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"); 
    } 
} 

Questo è il modo che ho usato questo nel mio test di applicazione, e funziona non ho problemi di orientamento. Ho eseguito il test in modalità verticale con l'immagine verticale e orizzontale e in modalità orizzontale con l'immagine verticale e orizzontale. E con entrambi i casi in cui ho cambiato l'orientamento dopo aver ottenuto l'immagine.

Se stai utilizzando la fotocamera personalizzato e l'orientamento è sbagliato con il codice di cui sopra, basta aggiungere questo

Ci sono due cose necessarie:

  1. fotocamera anteprima bisogno lo stesso del vostro rotazione . Impostare questo

    camera.setDisplayOrientation(result);

  2. Salva l'immagine catturata come l'anteprima della fotocamera. Fai questo tramite 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);

quindi è possibile utilizzare la funzione, senza la roba orientamento

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

Speranza che aiuta.

+0

convertisce l'orientamento dell'immagine in modalità orizzontale –

+0

@NeerajSharma ha aggiornato il mio codice e funziona perfettamente con la miapplicazione. – Kordi

+0

il tuo codice funziona bene solo in modalità orizzontale non in modalità ritratto bro. –

-1

uso questo putExtra nella chiamata intenti per fotocamera

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

Io uso questa funzione nel mio uno dei progetti si prega di verificare se è utile per voi.

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

È possibile impostare scaleType in xml

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

Nel codice Java puoi ac hieve stesso simili

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

Scaling bitmap con Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true); non manterrà proporzioni perché questo allungare la larghezza e l'altezza della bitmap per abbinare il bersaglio.

Una possibilità sarebbe quella di calcolare l'altezza bersaglio manualmente in modo non si verifica alcun ritaglio:

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

e quindi utilizzare targetHeight anziché screenHeight come argomento altezza in createScaledBitmap().

Inoltre, assicurarsi che l'immagine in cui si carica la bitmap abbia il tipo di scala appropriato (ad esempio FIT_CENTER o CENTER_CROP).

Problemi correlati