18

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;
}
AndroidNoob
  • 2,771
  • 2
  • 40
  • 53

5 Answers5

6

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.

Sean Owen
  • 66,182
  • 23
  • 141
  • 173
  • 1
    Thanks for the quick answer :) could you elaborate on the appropriate preview size? The code changes I implemented from the link in the question appear to be working fine i used appear to be working, they scan qr/bar codes no problem, it is literally just that my preview appears to be stretched/squished slightly – AndroidNoob Jul 17 '12 at 10:53
  • 1
    After you mentioned setting the appropriate preview size I took a look at the 'findBestPreviewSizeValue' method and basically swapped the X and Y values for the points and that has sorted it :) I'll update the question above with the code, thanks again for the pointer! – AndroidNoob Jul 17 '12 at 11:08
2

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

inqui
  • 21
  • 3
  • That link is exactly the same as the question I put above, and in fact links to this question when you click "view complete thread with replies" – AndroidNoob Aug 27 '14 at 12:20
1

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);
            }
Jitendra
  • 3,608
  • 2
  • 17
  • 19
0

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.

Community
  • 1
  • 1
EpicJoker
  • 349
  • 2
  • 15
0

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.

sanmianti
  • 175
  • 2
  • 8