erik
erik

Reputation: 4958

fullScreen Camera Preview without distortion/stretching

I have a cameraPreview class (see below) that is launching fullscreen and landscape... but the image is getting stretched/ and distorted.. is there a way to get this preview to remain fullscreen but not distort?

camLayer:

public class CamLayer extends SurfaceView implements SurfaceHolder.Callback {
       Camera camera;
       SurfaceHolder previewHolder;
       String camID;
       private static final String TAG = "Cam Preview";


       public CamLayer(Context context, String facing)
       {
               super(context);
               camID = facing;
               previewHolder = this.getHolder();
               previewHolder.addCallback(this);
               previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);


       }
       public void surfaceCreated(SurfaceHolder holder) {
           startCamera();
       }

       @Override
       public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
       {
               Parameters params = camera.getParameters();
                   //params.setPreviewSize(width, height);
                   //params.setPictureFormat(PixelFormat.JPEG);
                   camera.setParameters(params);
                   camera.startPreview();


       }

       public void surfaceDestroyed(SurfaceHolder arg0)
       {

            stopCamera();
       }



       public void onResume() {

           startCamera();

       }

       public void onPause() {

           stopCamera();
       }


       public void stopCamera(){
            System.out.println("stopCamera method");
            if (camera != null){
                camera.stopPreview();
                camera.setPreviewCallback(null);
                camera.release();
                camera = null;
                previewHolder.removeCallback(this);
                previewHolder = null;
            }
        }

       private void startCamera(){
           if(camID.equals("front")){
               camera=Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
           }else{
               camera=Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
           }
           try {
                   camera.setPreviewDisplay(previewHolder);

                }
                   catch (Throwable e){ Log.w("TAG,", "failed create surface !?!?"); }
        }

       public void draw(Canvas canvas) {
           super.draw(canvas);
           Paint p = new Paint(Color.RED);
           Log.d(TAG, "draw");
           canvas.drawText("PREVIEW", canvas.getWidth() / 2,
                canvas.getHeight() / 2, p);
        }
}

Upvotes: 8

Views: 6961

Answers (2)

Eddy Talvala
Eddy Talvala

Reputation: 18107

In addition to what Lena Bru says about finding a good preview size, if there isn't an exact aspect ratio match between your CamLayer dimensions and the camera preview size you select, the only option to avoid distortion is to adjust the layout of your CamLayer.

The camera preview is simply stretched to cover the entire view, no matter what the aspect ratios are, so for an undistorted view, you have to configure the View's layout to match the selected preview aspect ratio. See the Android developer site custom components documentation; especially the part about onMeasure.

You'll want to report a width and height that's based on the preview aspect ratio, and you might need to trigger a relayout of your UI when you configure the camera preview size to update the View sizing.

Upvotes: 0

Lena Bru
Lena Bru

Reputation: 13947

You need to run params.getSupportedPreviewSizes();

and from that find the best previewSize for your view

Look at this project: https://github.com/commonsguy/cw-advandroid/blob/master/Camera/Picture/src/com/commonsware/android/picture/PictureDemo.java

  private Camera.Size getBestPreviewSize(int width, int height,
                                         Camera.Parameters parameters) {
    Camera.Size result=null;

    for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
      if (size.width <= width && size.height <= height) {
        if (result == null) {
          result=size;
        }
        else {
          int resultArea=result.width * result.height;
          int newArea=size.width * size.height;

          if (newArea > resultArea) {
            result=size;
          }
        }
      }
    }

    return(result);
  }

Upvotes: 1

Related Questions