0

I have an Android app that opens the camera, starts preview and streams it on screen. Important note: there is no real SurfaceView associated with the camera. There's only a dummy SurfaceTexture:

m_previewTexture = new SurfaceTexture(58346);
camera.setPreviewTexture(m_previewTexture);

Now, I'm getting the image using the Camera.PreviewCallback. It is irrelevant what I'm doing with it further. So far I'm displaying it on the screen, but I might as well be saving it on the memory card.

Now, the problem. I set preview size to 320x240. I get the image of 320x240 size, all seems fine. But as soon as real life objects come into the frame, I can clearly see that the image is stretched.
My activity's orientation is locked, it doesn't rotate. As I rotate the device relative to a fixed object, I can very clearly see and confirm that the image is stretched. Why could this be and how to avoid stretching?

Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335
  • Can you confirm that 320x240 is in the list of supported preview modes (from `getSupportedPreviewSizes()`)? Which device are you using? – fadden Jan 12 '15 at 17:01
  • @fadden: I confirm that. Was among the first things I checked, and then double-checked. The device is Nexus 7 2013. – Violet Giraffe Jan 13 '15 at 06:00

1 Answers1

2

Does your screen aspect ratio correspond to your preview's frame ratio? Assure correct aspect ratio in onMeasure:

@Override
protected void onMeasure(int widthSpec, int heightSpec) {
    if (this.mAspectRatio == 0) {
        super.onMeasure(widthSpec, heightSpec);
        return;
    }
    int previewWidth = MeasureSpec.getSize(widthSpec);
    int previewHeight = MeasureSpec.getSize(heightSpec);

    int hPadding = getPaddingLeft() + getPaddingRight();
    int vPadding = getPaddingTop() + getPaddingBottom();

    previewWidth -= hPadding;
    previewHeight -= vPadding;

    boolean widthLonger = previewWidth > previewHeight;
    int longSide = (widthLonger ? previewWidth : previewHeight);
    int shortSide = (widthLonger ? previewHeight : previewWidth);
    if (longSide > shortSide * mAspectRatio) {
        longSide = (int) ((double) shortSide * mAspectRatio);
    } else {
        shortSide = (int) ((double) longSide / mAspectRatio);
    }
    if (widthLonger) {
        previewWidth = longSide;
        previewHeight = shortSide;
    } else {
        previewWidth = shortSide;
        previewHeight = longSide;
    }

    // Add the padding of the border.
    previewWidth += hPadding;
    previewHeight += vPadding;

    // Ask children to follow the new preview dimension.
    super.onMeasure(MeasureSpec.makeMeasureSpec(previewWidth, MeasureSpec.EXACTLY),
            MeasureSpec.makeMeasureSpec(previewHeight, MeasureSpec.EXACTLY));
}

from this project

Margarita Litkevych
  • 2,086
  • 20
  • 28
  • Thank you Margarita, but that is not applicable to my app. As I've mentioned, I'm getting the image from the camera by means of `Camera.PreviewCallback` and then I render it on screen using OpenGL in 1:1 scale, meaning that an image pixel is mapped onto a screen pixel - no transformation whatsoever. The image is much smaller than the screen. Alternatively, I could save the image to JPEG, open it in any viewer and confirm that it is stretched. But the physical dimensions of the image are correct - 320x240. – Violet Giraffe Jan 13 '15 at 14:21
  • What picture size is set in Camera.Parameters? Do their (picture-to-be-taken and preview) aspect ratios correspond each other? Even if you do not want to take a picture, you can try to set correct aspect ratio for it. – Margarita Litkevych Jan 13 '15 at 14:47
  • Thanks for the idea, I didn't bother setting the picture size. Will see if that helps. – Violet Giraffe Jan 13 '15 at 14:50