将相机预览缩放到已保存图片时出现问题。正确的做法是什么?

时间:2016-03-22 11:01:59

标签: java android android-layout camera

我正在尝试使用相机应用来测量相机预览的特定区域中的像素颜色。为此,用户在摄像机预览上具有网格,该网格指示将要测量哪个特定区域。由于我想要有很好的分辨率,我不想直接从带有预览的surfaceView进行测量,但是我想在拍完照片后对照片进行测量,那么我必须对布局进行一些调整。和图片大小,位置和规则3,以便从预览尺寸到实际图片尺寸。

我使用的相机活动如下所示:

Android Camera Preview Stretched

略微修改,以确保预览和最终图片的比例相同。

我添加了一小段代码,用于保存图片的片段,该片段应该在网格下面作为位图。这就是我的问题,我不知道我在这里做错了什么,因为保存的图片与相机预览中网格下的图片不对应。 (它或多或少地向右和向右移动。)

1)请您指出我这是否是正确的做法,而在否定的情况下,您会使用哪种近似值?

Illustrative example

2)为了为surfaceView camera_view(持有相机预览的那个)设置合适的尺寸,我想检索最佳预览尺寸的大小和比例,这是通过CameraPreview类在Camera.Size getOptimalPreviewSize上计算。要做到这一点,需要启动摄像头,据我所知,当onCreate方法已经发生时会发生这种情况。

在哪里可以放入camera_view.setLayoutParams(new FrameLayout.LayoutParams(x,y)),以便在检索到OptimalPreviewSize后调用它?

非常感谢你!

MainActivity.onCreate

     protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        verticalSeekBar = (VerticalSeekBar)            findViewById(R.id.vertical_Seekbar);
        verticalSeekBar.setOnSeekBarChangeListener(zoomSeekBarListener);

        shotButton = (Button) findViewById(R.id.shotButton);
        shotButton.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (myCameraView.safeToTakePicture)
                    myCamera.takePicture(null, null, jpegCallback);
                myCameraView.safeToTakePicture = false;
                return false;
            }
        });

        try {
            myCamera = Camera.open();
        } catch (Exception e) {
            Log.d("ERROR", "Failed to get camera: " + e.getMessage());
        }

        if (myCamera != null) {
            myCameraView = new CameraView(this, myCamera);//create a SurfaceView to show camera data
            camera_view = (FrameLayout) findViewById(R.id.camera_view);
            camera_view.addView(myCameraView);//add the SurfaceView to the layout

        } 
    }

MainActivity.PictureCallback

调整大小计算在这里完成,所以这可能是我看不到的错误......

     Camera.PictureCallback jpegCallback = new Camera.PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {

            Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

            int viewH = camera_view.getHeight();
            int viewW = camera_view.getWidth();

            ImageView grid = (ImageView) findViewById(R.id.grid);

        int x = grid.getRight();  //As image is rotated 90º, the right side of the grid will be the top side after Bitmap generation
        int y = grid.getTop();

        int relation = bitmap.getWidth()/ camera_view.getLayoutParams().height; //Relation between width of bitmap and height of surfaceview tells the relation between sizes of surfaceView and bitmap

        int scaled_x = relation * y;  //Theoretical position of the grid in the bitmap
        int scaled_y = relation * x;

        int scaledWidth = grid.getWidth() * relation;

        Matrix matrix = new Matrix();
        matrix.postRotate(90);

        Bitmap resizedbitmap = Bitmap.createBitmap(bitmap, scaled_x, scaled_y, scaledWidth, scaledWidth, matrix, true);


            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            resizedbitmap.compress(Bitmap.CompressFormat.JPEG, 70, bos);

            File sdCard = Environment.getExternalStorageDirectory();
            File dir = new File(sdCard.getAbsolutePath() + "/camtest");
            dir.mkdirs();

            String fileName = String.format("%d.jpg", System.currentTimeMillis());

            File outFile = new File(dir, fileName);

            myCameraView.safeToTakePicture = true;

            if (outFile == null) {
                return;
            }

            try {
                FileOutputStream fos = new FileOutputStream(outFile);
                bos.writeTo(fos);
                fos.close();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

CameraPreview.onMeasure

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

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


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


        Log.i(TAG, "Ratio Preview " + ratio);

        getOptimalPictureSize(ratio);

        // One of these methods should be used, second method squishes preview slightly
        setMeasuredDimension((int) (width), (int) (width * ratio));

        _width = mPreviewSize.width;
        _height = mPreviewSize.height;


        waitFlag = false;

    }

CameraPreview.getOptimalPictureSize

    private void getOptimalPictureSize(float ratio) {
        List<Camera.Size> pictureSizes = mCamera.getParameters().getSupportedPictureSizes();

        int lastWidth = 0;
        int candidate = 0;

        for (int i = 0; i < pictureSizes.size(); i++) {

            float ratioPictureSizes = (float) pictureSizes.get(i).width / pictureSizes.get(i).height;

            Log.i(TAG, "Picture Sizes: " + pictureSizes.get(i).width + "," + pictureSizes.get(i).height + ", " + ratioPictureSizes);

            if (ratioPictureSizes / ratio < 1 + TOLERANCE || ratioPictureSizes / ratio < 1 - TOLERANCE) {
                int thisWidth = pictureSizes.get(i).width;
                if (thisWidth < lastWidth) continue;
                else {
                    lastWidth = thisWidth;
                    candidate = i;
                }
            }
        }


        Log.i(TAG, "Size found: " + pictureSizes.get(candidate).width + "," + pictureSizes.get(candidate).height + ", " + (float) pictureSizes.get(candidate).width / pictureSizes.get(candidate).height);
        mCamera.stopPreview();

        Camera.Parameters parameters = mCamera.getParameters();

        parameters.setPictureSize(pictureSizes.get(candidate).width, pictureSizes.get(candidate).height);

        mCamera.setParameters(parameters);

        mCamera.startPreview();
    }

布局

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="#000000">

    <FrameLayout
        android:id="@+id/camera_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center">

    </FrameLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/root"
        android:layout_gravity="center">

        <com.example.raulgotor.phmeter2.DrawGrid
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:id="@+id/grid"
            android:layout_centerInParent="true" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:id="@+id/linearLayout"
            android:layout_alignParentBottom="true"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:layout_marginBottom="20dp">

            <com.example.raulgotor.phmeter2.VerticalSeekBar android:id="@+id/vertical_Seekbar"
                android:layout_width="50dp"
                android:layout_height="110dp"
                android:minHeight="110dip"
                android:maxHeight="110dip"
                android:indeterminate="false" />

            <View
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:layout_centerInParent="true"/>

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Foto"
                android:id="@+id/shotButton"
                android:layout_gravity="center|right" />
        </LinearLayout>

    </RelativeLayout>

</FrameLayout>


  [1]: http://i.stack.imgur.com/70Ni5.jpg

0 个答案:

没有答案