2

the camera preview is showing a distorted image, which is elongated while in portrait mode and flattened while in landscape. I have already resized preview with a million techniques. Then I read somewhere it must be something with resizing the SurfaceView. But so far I have not found anything suitable.

This is my activity.java file:

public class CameraActivity extends Activity { private Camera mCamera; private CameraPreview mPreview; private FrameLayout preview; private static final String TAG = "CameraActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); if (checkCameraHardware(getBaseContext())){ // Create an instance of Camera mCamera = getCameraInstance(); // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera, CameraActivity.this); preview = (FrameLayout) findViewById(R.id.camera_preview); preview.addView(mPreview); } } /** Check if this device has a camera */ private boolean checkCameraHardware(Context context) { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){ Log.d(TAG, "Camera Available"); return true; } else { Log.d(TAG, "No Camera Found"); return false; } } /** A safe way to get an instance of the Camera object. */ public Camera getCameraInstance(){ Camera c = null; try { int i = Camera.getNumberOfCameras(); releaseCamera(); //in case camera is being accessed by any other app. Log.d(TAG, "Number of Cameras "+i +"\n"); c = Camera.open(); // attempt to get a Camera instance Log.d(TAG, "Camera Opened"); } catch (Exception e){ Log.d(TAG, "Camera Can't Be Accessed"); } return c; // returns null if camera is unavailable } @Override protected void onPause() { super.onPause(); releaseCamera(); // release the camera immediately on pause event } private void releaseCamera(){ if (mCamera != null){ //mCamera.setPreviewCallback(null); mPreview.getHolder().removeCallback(mPreview); mCamera.release(); // release the camera for other applications } } 

This is my camera preview class:

@SuppressLint("ViewConstructor") public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private static final String TAG = "CameraPreview"; private SurfaceHolder mHolder; private Camera mCamera; private Size mPreviewSize; @SuppressWarnings("deprecation") public CameraPreview(Context context, Camera camera, Activity activity) { super(context); mCamera = camera; // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, now tell the camera where to draw the preview. try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceDestroyed(SurfaceHolder holder) { // empty. Take care of releasing the Camera preview in your activity. } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.getSurface() == null){ // preview surface does not exist return; } // stop preview before making changes try{ mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here Camera.Parameters parameters = mCamera.getParameters(); List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes(); mPreviewSize = localSizes.get(0); Log.d(TAG, "Width " + mPreviewSize.width); Log.d(TAG, "Height " + mPreviewSize.height); parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height ); requestLayout(); mCamera.setParameters(parameters); //start preview with new settings try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e){ Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) { android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(cameraId, info); int rotation = activity.getWindowManager().getDefaultDisplay() .getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = -90; break; case Surface.ROTATION_180: degrees = 0; break; case Surface.ROTATION_270: degrees = -90; break; } int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (info.orientation - degrees + 360) % 360; } camera.setDisplayOrientation(result); } } 

And this is my activity.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:baselineAligned="false" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".CameraActivity" > <FrameLayout android:id="@+id/camera_preview" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight = "1" /> </LinearLayout> 
1
  • Is this issue was resolved? Commented Apr 4, 2014 at 10:18

3 Answers 3

1

Your SurfaceView (or TextureView) must have the same aspect ratio as your preview images, otherwise you will get the distortion that you describe.

FWIW, you may find it useful to work with my CWAC-Camera library, which offers a CameraFragment that handles a lot of this low-level stuff for you. It's still a work in progress, though.

Sign up to request clarification or add additional context in comments.

2 Comments

My Surface View does have the same aspect ratio.
@user1235240: Not that I can see. CameraPreview chooses a semi-random preview size, then only seems to use that to configure the camera. I fail to see anywhere that you are affecting the aspect ratio of CameraPreview itself using that preview size.
1

You can find the camera preview width & height as soon as the camera instance is created, in onCreate. Then, choose layout_width and layout_height so that they fit into the preview FrameLayout and preserve the aspect ratio of the camera. You can use FrameLayout.addView(View, LayoutParams).

5 Comments

do I specify the layout_width and the layout_height? because I have mentioned in the xml that it has to fill_parent.
Yes, and you would probably prefer to choose them at runtime, not in xml.
I used to the camera parameters to get the width and the height, and set it accordingly, and added them as you mentioned. But it still has no effect. The landscape mode is working fine now since I added cameraorientation: portrait in the Manifest file, but it all stretched when I make the camera vertical.
Maybe, in Portrait mode you should swap width and height?
@Haleema i m also getting same issue can u pls tell me how u resolved your issue?
0

Not sure if anyone still reads this but I had the same problem and this answer fixed it. I copy the code here just in case (I also editted it to match this example):

mCamera.Parameters parameters1 = mCamera.getParameters(); parameters1.setPreviewSize(getWidth(), getHeight()); mCamera.setParameters(parameters1); 

add these lines just before this:

mCamera.startPreview(); 

1 Comment

Unfortunately most devices don't support arbitrary preview sizes.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.