문제

I have a weird problem with my Camera-SurfaceHolder.

I want to show the image of the camera in my activity. It all works greatly on my GalaxyS1 (CyanogenMod - Android 4.4) On my S3 (also CyanogenMod - Android 4.4) on the other hand it looks weird.

The landscape image without title bar is okay but when I show the title bar or turn it into portrait mode it looks distorted:

enter image description here

--- EDIT ---

Thank you Alex Cohn for your help. It looks like you are right. The preview for the portraid mode is now working nicely. But still it looks distorted on the landscape view. I checked the preview scale and it looks okay. As far as I can see I set the preview size properly, too. So what is wrong with it?

Here is the current code:

    private static final String TAG = CameraView.class.getSimpleName();

      private SurfaceHolder surfaceHolder;
      private Camera camera;
      private List<Size> mSupportedPreviewSizes;
      private Size mPreviewSize;

      public CameraView(Activity activity) {
        super(activity);
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        camera = Camera.open();
        mSupportedPreviewSizes = camera.getParameters()
                .getSupportedPreviewSizes();
        setCameraDisplayOrientation(activity, 0, camera);
      }

      @Override
      public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        Camera.Parameters parameters = camera.getParameters();
        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        camera.setParameters(parameters);
        camera.startPreview();
      }

      @Override
      public void surfaceCreated(SurfaceHolder holder) {
       try {
         camera.setPreviewDisplay(holder);
       } catch (IOException exception) {
             camera.release();
             camera = null;
       }
      }

     @Override
       public void surfaceDestroyed(SurfaceHolder arg0) {
       camera.stopPreview();
       camera.release();
       camera = null;
     }

   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
    final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
                setMeasuredDimension(width, height);

    if (mSupportedPreviewSizes != null) {
        mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
    }
  }

  private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w,
                int h) {...}

  public static void setCameraDisplayOrientation(Activity activity,
                int cameraId, Camera camera) {...}

--- EDIT ---

I logged the values for the onMeasure and surface Changed. They seem to be ok:

Portrait:

SURFACE CHANGED: Witdh:720 Height:1134

onMeasure: width:720 height:1134

Landscape:

SURFACE CHANGED: Witdh:1280 Height:590

onMeasure: width:1280 height:590

Preview Size: Width: 704 Height:576

I get the following possible preview sizes.

There are 8 elements in the array:

960 x 720, 1280 x 720, 1184 x 666, 960 x 640, 704 x 576, 640 x 480, 352 x 288, 320 x 240

Hopefully anyone can help!

Thanks, Tobias

도움이 되었습니까?

해결책

The source of your problem is the following line:

parameters.setPreviewSize(w, h);

in surfaceChanged() method. You cannot set preview size to arbitrary values in Android. You should only use the pairs of (w, h) as returned by Parameters.getSupportedPreviewSizes(). Otherwise, you hit the appearing to succeed is a valid form of undefined behavior situation. Actually, many devices will simply raise a RuntimeException on camera.setParameters(parameters), but your dev platforms chose to behave differently.

There is no requirement that the preview size be same as the surface used to display it, e.g. using 320x240 preview on a 640x480 surface is OK. But if your preview and surface have different aspect ratios, than the image will look stretched (see http://i.stack.imgur.com/VFwes.jpg). Minor distortions may be tolerable, like using 1280x720 preview on 800x400 pixel sceen, but above certain threshold, you have no choice but to only use part of the screen, leaving margins above and below the preview.

You can find what the developers community came up with: use getOptimalPreviewSize() for given width, hight (this is just one example).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top