2016-01-06 3 views
7

Ma question est très simple:Comment obtenir un appareil photo Android2 avec un ratio de 1: 1 comme Instagram?

Comment obtenir une android.hardware.Camera2 Android avec 1: 1 et sans déformation comme Instagram?

J'ai testé avec le projet GoogeSamples android-Camera2Basic. Mais quand je change l'aperçu avec un ratio de 1: 1 l'image est déformée. Est-ce que quelqu'un a une idée à ce sujet?

enter image description here

+1

« Mais quand je change l'aperçu avec un rapport de 1: 1 image est déformée » - nous ne pouvons pas vous aider à déboguer votre code, sauf si vous fournissez votre code, dans le cadre d'une [minimale, complète et vérifiable exemple] (http://stackoverflow.com/help/mcve). En général, la réponse est d'avoir le "SurfaceView" ou "TextureView" avoir le même rapport d'aspect que l'image de la caméra, mais ensuite utiliser des marges négatives ou des trucs équivalents pour montrer seulement un sous-ensemble de ce qui vient du caméra. – CommonsWare

+0

Merci @CommonsWare. Utilisez des marges négatives pour corriger mon problème. Je poste mon code en réponse. –

+0

@ lopez.mikhael comment avez-vous changé le rapport d'aspect? jetez un oeil http://stackoverflow.com/questions/41221284/how-to-change-aspect-ratio-of-camera2-preview –

Répondre

2

Merci @CommonsWare. J'ai suivi votre conseil en utilisant une marge négative (haut et bas) et cela fonctionne.

Pour ce faire, je viens de mettre à jour AutoFitTextureView le projet GoogeSamples android-Camera2Basic cette façon:

public class AutoFitTextureView extends TextureView { 

    //... 
    private boolean mWithMargin = false; 

    //... 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     super.onMeasure(widthMeasureSpec, widthMeasureSpec); 
     int width = MeasureSpec.getSize(widthMeasureSpec); 
     int height = MeasureSpec.getSize(heightMeasureSpec); 
     int margin = (height - width)/2; 

     if(!mWithMargin) { 
      mWithMargin = true; 
      ViewGroup.MarginLayoutParams margins = ViewGroup.MarginLayoutParams.class.cast(getLayoutParams()); 
      margins.topMargin = -margin; 
      margins.bottomMargin = -margin; 
      margins.leftMargin = 0; 
      margins.rightMargin = 0; 
      setLayoutParams(margins); 
     } 

     if (0 == mRatioWidth || 0 == mRatioHeight) { 
      setMeasuredDimension(width, height); 
     } else { 
      if (width < height) { 
       setMeasuredDimension(width, width * mRatioHeight/mRatioWidth); 
      } else { 
       setMeasuredDimension(height * mRatioWidth/mRatioHeight, height); 
      } 
     } 
    } 
} 

enter image description here

+2

Salut! J'ai le même problème. J'ajoute votre implémentation de AutoFitTextureView, mais ça ne marche toujours pas. pouvez-vous s'il vous plaît fournir un peu plus de code de votre application pour faire un aperçu de la caméra et des photos de façon carrée? merci! –

+0

quand je fais cela, je reçois une barre noire en bas de l'aperçu .. des idées? – Dave

0

Créer une vue personnalisée texture comme ceci:

public class AutoFitTextureView extends TextureView { 

    private int mCameraWidth = 0; 
    private int mCameraHeight = 0; 
    private boolean mSquarePreview = false; 

    public AutoFitTextureView(Context context) { 
     this(context, null); 
    } 

    public AutoFitTextureView(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    public void setAspectRatio(int width, int height, boolean squarePreview) { 
     if (width < 0 || height < 0) { 
      throw new IllegalArgumentException("Size cannot be negative."); 
     } 
     mCameraWidth = width; 
     mCameraHeight = height; 
     mSquarePreview = squarePreview; 
     requestLayout(); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     int width = MeasureSpec.getSize(widthMeasureSpec); 
     int height = MeasureSpec.getSize(heightMeasureSpec); 
     if (0 == mCameraWidth || 0 == mCameraHeight) { 
      setMeasuredDimension(width, height); 
     } else { 
      /** 
      * Vertical orientation 
      */ 
      if (width < height) { 
       if (mSquarePreview) { 
        setTransform(squareTransform(width, height)); 
        setMeasuredDimension(width, width); 
       } else { 
        setMeasuredDimension(width, width * mCameraHeight/mCameraWidth); 
       } 
      } 
      /** 
      * Horizontal orientation 
      */ 
      else { 
       if (mSquarePreview) { 
        setTransform(squareTransform(width, height)); 
        setMeasuredDimension(height, height); 
       } else { 
        setMeasuredDimension(height * mCameraWidth/mCameraHeight, height); 
       } 
      } 
     } 
    } 

    private Matrix setupTransform(int sw, int sh, int dw, int dh) { 
     Matrix matrix = new Matrix(); 
     RectF src = new RectF(0, 0, sw, sh); 
     RectF dst = new RectF(0, 0, dw, dh); 
     RectF screen = new RectF(0, 0, dw, dh); 

     matrix.postRotate(-90, screen.centerX(), screen.centerY()); 
     matrix.mapRect(dst); 

     matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER); 
     matrix.mapRect(src); 

     matrix.setRectToRect(screen, src, Matrix.ScaleToFit.FILL); 
     matrix.postRotate(-90, screen.centerX(), screen.centerY()); 

     return matrix; 
    } 

    private Matrix squareTransform(int viewWidth, int viewHeight) { 
     Matrix matrix = new Matrix(); 

     if (viewWidth < viewHeight) { 
      MyLogger.log(AutoFitTextureView.class, "Horizontal"); 
      matrix.setScale(1, (float) mCameraHeight/(float) mCameraWidth, viewWidth/2, viewHeight/2); 
     } else { 
      MyLogger.log(AutoFitTextureView.class, "Vertical"); 
      matrix.setScale((float) mCameraHeight/(float) mCameraWidth, 1, viewWidth/2, viewHeight/2); 
     } 

     return matrix; 
    } 
} 

Et appelez setAspectRatio pour votre vue de texture dans l'activité/fragment.

if (mVideoSize.width > mVideoSize.height) { 
    mTextureView.setAspectRatio(mVideoSize.height, mVideoSize.width, true); 
} else { 
    mTextureView.setAspectRatio(mVideoSize.width, mVideoSize.height, true); 
} 
mCamera.setPreviewTexture(mTextureView.getSurfaceTexture()); 
mCamera.startPreview(); 
+1

Salut Mikhael! J'essaie de mettre en œuvre votre solution mais ne fonctionne pas. Pourriez-vous poster ou m'envoyer une implémentation complète s'il vous plaît? Ce sera fantastique! – anthony