Question

I have managed to use the answer here to rotate the camera preview to portrait: http://code.google.com/p/zxing/issues/detail?id=178#c46

however the preview itself is stretched/warped - the height appears to be stretching to fill the box (but it could be that the width is too large for the screen and it is being squished to fit)

Is there any way to 'wrap' the content rather than make it stretch to fit the surfaceview?

EDIT: I sorted it by altering the 'findBestPreviewSizeValue' method in the 'CameraConfigurationManager' and reversing the X and Y points (thanks to sean owen for the pointer below!), here is the code:

private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString,
  Point screenResolution) {
int bestX = 0;
int bestY = 0;
int diff = Integer.MAX_VALUE;
for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {

  previewSize = previewSize.trim();
  int dimPosition = previewSize.indexOf('x');
  if (dimPosition < 0) {
    Log.w(TAG, "Bad preview-size: " + previewSize);
    continue;
  }

  int newX;
  int newY;
  try {
    newY = Integer.parseInt(previewSize.substring(0, dimPosition));
    newX = Integer.parseInt(previewSize.substring(dimPosition + 1));
    //original:
    //newX = Integer.parseInt(previewSize.substring(0, dimPosition));
    //newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
  } catch (NumberFormatException nfe) {
    Log.w(TAG, "Bad preview-size: " + previewSize);
    continue;
  }

  int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
  if (newDiff == 0) {
    bestX = newY;
    bestY = newX;
    //original:
    //bestX = newX;
    //bestY = newY;
    break;
  } else if (newDiff < diff) {
    bestX = newY;
    bestY = newX;
    //original:
    //bestX = newX;
    //bestY = newY;
    diff = newDiff;
  }

}

if (bestX > 0 && bestY > 0) {
  return new Point(bestX, bestY);
}
return null;
}
Was it helpful?

Solution

You have to do a fair bit more to get this to work than just set the preview to portrait mode. For example, you need to choose an appropriate preview size now that it's in portrait, not landscape.

Wrapping is surely not desirable? No you can't make it wrap; it will always fling the whole preview image onto the SurfaceView, stretching if needed. I suppose you could reimplement a lot of that code to do something different, but it would be quite hard.

OTHER TIPS

I had the same problem but I could resolved it by inverting the aspect ratio on the CameraConfigurationManager.java file inside the findBestPreviewSizeValue changing this

 float screenAspectRatio = (float) screenResolution.x / (float) screenResolution.y;

to this

 float screenAspectRatio = (float) screenResolution.y / (float) screenResolution.x;

I found the solution here.

http://bighow.net/4660010-Android_zxing___portrait_camera_preview_surfaceview_is_stretched_warped.html

You can get Priview size by this function:

private List mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();

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

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
            final double ASPECT_TOLERANCE = 0.1;
            double targetRatio = (double) h / w;

            if (sizes == null)
                return null;

            Camera.Size optimalSize = null;
            double minDiff = Double.MAX_VALUE;

            int targetHeight = h;

            for (Camera.Size size : sizes) {
                double ratio = (double) size.height / size.width;
                if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                    continue;

                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }

            if (optimalSize == null) {
                minDiff = Double.MAX_VALUE;
                for (Camera.Size size : sizes) {
                    if (Math.abs(size.height - targetHeight) < minDiff) {
                        optimalSize = size;
                        minDiff = Math.abs(size.height - targetHeight);
                    }
                }
            }

            return optimalSize;
        }


            float ratio;
            if (mPreviewSize.height >= mPreviewSize.width)
                ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
            else
                ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;

            after getting ratio set your size in 

            protected void onMeasure(int widthMeasureSpec, int                              heightMeasureSpec) {

            setMeasuredDimension((int) (width * ratio), height);
            }

I managed to get this to work by changing below code inCameraConfigurationManager.java:

float screenAspectRatio = (float) screenResolution.x / (float) screenResolution.y;

To:

float screenAspectRatio = (float) screenResolution.y / (float) screenResolution.x;

AND

float aspectRatio = (float) maybeFlippedWidth / (float) maybeFlippedHeight;

TO:

float aspectRatio = (float) maybeFlippedHeight / (float) maybeFlippedWidth;

I did this alongside this post: Zxing Camera in Portrait mode on Android

Hope this helps others.

The reason of deformation may is that the camera's preview aspect ratio does not match the display's aspect ratio.

Most aspect ratio of cellphone screen is 4:3, such as 2560x1440, 1920x1080 and so on. When you use parameter.setPreviewSize(width,height) to set camera preview dimension, if the value of height : width does not equals your phone screen's aspect ratio,the picture of camera will be deformed to fill thg screen.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top