android_eng
android_eng

Reputation: 1370

onPreviewCallback frames are smaller than actual frames

I am trying to display the frames received from onPreviewCallback on an imageview. Firstly the orientation of the frames are not the same as live preview and secondly it seems to be smaller than the actual live preview here is my code. The preview size is 1024 x 768:

cameraConfigUtil.cameraInstance.setOneShotPreviewCallback(new Camera.PreviewCallback() {
                        @Override
                        public void onPreviewFrame(byte[] originalData, Camera camera) {
                            Mat srcMat = new Mat(camera.getParameters().getPreviewSize().height, camera.getParameters().getPreviewSize().width, CvType.CV_8UC1);
                            srcMat.put(0, 0, originalData);
                            Bitmap bitmap = Bitmap.createBitmap(camera.getParameters().getPreviewSize().width, camera.getParameters().getPreviewSize().height, Bitmap.Config.ARGB_8888);
                            Utils.matToBitmap(srcMat, bitmap);
                            cameraPreviewImage.setVisibility(View.VISIBLE);
                            cameraPreviewImage.setImageBitmap(bitmap);
                        }
                    });

Setting all camera parameters:

 if (!isCameraParametersSet) {
            MIN_FRAME_WIDTH = 1024;
            MIN_FRAME_HEIGHT = 768;
            if (android.os.Build.VERSION.SDK_INT >= 14) {
                setFocus(cameraParameters, false);
            } else {
                setFocus(cameraParameters, true);
            }
            WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            Display display = manager.getDefaultDisplay();
            Point theScreenResolution = new Point();
            theScreenResolution.set(display.getHeight(), display.getWidth());
            SizePair picturePreviewSizePair = selectSizePair(cameraInstance, MIN_FRAME_WIDTH, MIN_FRAME_HEIGHT);
            cameraParameters.setPreviewSize(picturePreviewSizePair.mPreview.getWidth(), picturePreviewSizePair.mPreview.getHeight());
            cameraParameters.setPictureSize(picturePreviewSizePair.mPicture.getWidth(), picturePreviewSizePair.mPicture.getHeight());
            getTargetPictureSize();
            if (cameraParameters.getSupportedPictureFormats().contains(ImageFormat.JPEG)) {
                cameraParameters.setPictureFormat(ImageFormat.JPEG);
            }
            cameraParameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
            isCameraParametersSet = true;
        }
        return cameraParameters;

Here is my resolution code:

private static SizePair selectSizePair(Camera camera, int desiredWidth, int desiredHeight) {
    List<SizePair> validPreviewSizes = generateValidPreviewSizeList(camera);
    SizePair selectedPair = null;
    int minDiff = Integer.MAX_VALUE;
    for (SizePair sizePair : validPreviewSizes) {
        Size size = sizePair.previewSize();
        int diff = Math.abs(size.getWidth() - desiredWidth) +
                Math.abs(size.getHeight() - desiredHeight);
        if (diff < minDiff) {
            selectedPair = sizePair;
            minDiff = diff;
        }
    }

    return selectedPair;
}


private static List<SizePair> generateValidPreviewSizeList(Camera camera) {
    Camera.Parameters parameters = camera.getParameters();
    List<android.hardware.Camera.Size> supportedPreviewSizes =
            parameters.getSupportedPreviewSizes();
    List<android.hardware.Camera.Size> supportedPictureSizes =
            parameters.getSupportedPictureSizes();
    List<SizePair> validPreviewSizes = new ArrayList<>();
    for (android.hardware.Camera.Size previewSize : supportedPreviewSizes) {
        float previewAspectRatio = (float) previewSize.width / (float) previewSize.height;
        for (android.hardware.Camera.Size pictureSize : supportedPictureSizes) {
            float pictureAspectRatio = (float) pictureSize.width / (float) pictureSize.height;
            if (Math.abs(previewAspectRatio - pictureAspectRatio) < ASPECT_RATIO_TOLERANCE) {
                validPreviewSizes.add(new SizePair(previewSize, pictureSize));
                break;
            }
        }
    }

enter image description here

Upvotes: 0

Views: 210

Answers (2)

Eddy Talvala
Eddy Talvala

Reputation: 18137

How can you tell if the two are a different resolution?

The standard UI elements to display camera preview (SurfaceView, TextureView) will both scale up/down whatever they receive to fit the View bounds; so for example if a SurfaceView covers 1600x1200 pixels, and it's provided camera preview frames that are 640x480, it'll scale up the frames to fill the 1600x1200 view.

However, the ImageView you're using to display the preview callbacks doesn't necessarily do the same - it will upsample, but you do need to ensure its layout matches that of the SurfaceView. Here it looks like it's much smaller.

On the rotation - that is documented in setDisplayOrientation. Only the preview output is rotated; you have to rotate anything from preview callbacks by hand. Since you're already loading things into a OpenCV matrix, applying a 90-degree rotation should be easy enough. The amount of rotation you need is the same as what you pass into setDisplayOrientation.

Upvotes: 1

Vyacheslav
Vyacheslav

Reputation: 27221

This code works for me:

Camera.Parameters cameraParam = mCamera.getParameters();
List<Size> sizes = cameraParam.getSupportedPreviewSizes();
            Camera.Size previewSize = cameraParam.getPreviewSize();
            previewFormat = cameraParam.getPreviewFormat();
            int[] sizesForCamera = new int[]{sizes.get(0).width,sizes.get(0).height};
            cameraParam.setPreviewSize(sizesForCamera[0], sizesForCamera[1]);
            mCamera.setParameters(cameraParam);

I have not found setPreviewSize method in your code:)

BUT PLEASE USE CAMERA2 API

https://developer.android.com/reference/android/hardware/camera2/package-summary.html https://github.com/googlesamples/android-Camera2Basic

Upvotes: 0

Related Questions