Android 相机照片预览即将倒转

标签 android camera android-camera

我正在开发与相机相关的应用程序。我也已成功完成拍摄照片和照片预览。但是出现了一个问题。当我拍照时,照片捕获成功但预览是相反的。我已经尝试了很多堆栈溢出的解决方案,尽管到目前为止运气对我不利。

我的相机预览类是:

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;
    private Context mContext;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mContext = context;
        mCamera = camera;
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        try {
            // create the surface and start camera preview
            if (mCamera == null) {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            }
        } catch (IOException e) {
            Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    public void refreshCamera(Camera camera) {
        if (mHolder.getSurface() == null) {
            // preview surface does not exist
            return;
        }
        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            // ignore: tried to stop a non-existent preview
        }
        // set preview size and make any resize, rotate or
        // reformatting changes here
        // start preview with new settings
        setCamera(camera);

        // TODO: don't hardcode cameraId '0' here... figure this out later.
        setCameraDisplayOrientation(mContext, Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);

        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
        } catch (Exception e) {
            Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
        }
    }

    public static void setCameraDisplayOrientation(Context context, int cameraId, Camera camera) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        int rotation = wm.getDefaultDisplay().getRotation();

        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }

        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            // Compensate for the mirror image.
            result = (360 - result) % 360;
        } else {
            // Back-facing camera.
            result = (info.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.
        refreshCamera(mCamera);
    }

    public void setCamera(Camera camera) {
        //method to set a camera instance
        mCamera = camera;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        // mCamera.release();

    }
}

我的 PhotoCaputeActivity 类如下:

public class PhotoCaptureActivity extends AppCompatActivity {

    private static final String TAG = "PhotoCaptureActivity";

    //Arraylist for image timer animation
    int[] imageArray = {R.drawable.ic_five_128, R.drawable.ic_four_128,
            R.drawable.ic_three_128, R.drawable.ic_two_128, R.drawable.ic_one_128,
            R.drawable.ic_smiley_128
    };
    int i = 0;
    private final static int DELAY = 1000;
    private final Handler handler = new Handler();
    Timer timer = new Timer();

    Thread timerThread;

    // Create variable to handle progress and set it to 0.
    private int progress = 0;

    Bitmap bitmap,photoCaptureBitmap;

    private Camera mCamera;
    private CameraPreview mPreview;
    private PictureCallback mPicture;
    private ImageButton capture, switchCamera;
    private Context myContext;
    private LinearLayout cameraPreview;
    private boolean cameraFront = false;
    private ImageView capturedImageHolder;

    private ProgressBar progressBar_take_photo;
    ImageButton next_button_take_photo;
    ImageButton back_button_take_photo;
    TextView photo_title_text;

    ImageView image_animation;
    private MyPreferences myPreferences;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().setDisplayShowTitleEnabled(false);
        setContentView(R.layout.photo_capture_activity);

        //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        Logger.addLogAdapter(new AndroidLogAdapter());
        myContext = this;
        initialize();
        myPreferences = MyPreferences.getPreferences(this);

        nextButton();
        backButton();
        progressBar();
        nameTextShow();

    }

    private int findFrontFacingCamera() {
        int cameraId = -1;
        // Search for the front facing camera
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            CameraInfo info = new CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
                cameraId = i;
                cameraFront = true;
                break;
            }
        }
        return cameraId;
    }

    private int findBackFacingCamera() {
        int cameraId = -1;
        //Search for the back facing camera
        //get the number of cameras
        int numberOfCameras = Camera.getNumberOfCameras();
        //for every camera check
        for (int i = 0; i < numberOfCameras; i++) {
            CameraInfo info = new CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
                cameraId = i;
                cameraFront = false;
                break;
            }
        }
        return cameraId;
    }

    public void onResume() {
        super.onResume();

        if (!hasCamera(myContext)) {
            Toast toast = Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG);
            toast.show();
            finish();
        }
        if (mCamera == null) {
            //if the front facing camera does not exist
            if (findFrontFacingCamera() < 0) {
                //Toast.makeText(this, "", Toast.LENGTH_LONG).show();
                //switchCamera.setVisibility(View.GONE);
            }
            mCamera = Camera.open(findFrontFacingCamera());
            mPicture = getPictureCallback();
            mPreview.refreshCamera(mCamera);
        }else{
            //Visibility
            cameraPreview.setVisibility(View.GONE);
            capturedImageHolder.setVisibility(View.VISIBLE);
            String photoCapturePreview = myPreferences.getVisitorPhoto();
            if(!photoCapturePreview.equals("")) {
                photoCaptureBitmap = decodeToBase64(photoCapturePreview);
            }
            capturedImageHolder.setImageBitmap(photoCaptureBitmap);
        }
    }

    public static Bitmap decodeToBase64(String input) {
        byte[] decodedByte = Base64.decode(input, 0);
        return BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
    }

    // Code for initialization
    public void initialize() {
        cameraPreview = (LinearLayout) findViewById(R.id.cameraFrame);
        mPreview = new CameraPreview(myContext, mCamera);
        cameraPreview.addView(mPreview);

        capture = (ImageButton) findViewById(R.id.button_capture);
        capture.setOnClickListener(captrureListener);

        //switchCamera = (Button) findViewById(R.id.button_ChangeCamera);
        //switchCamera.setOnClickListener(switchCameraListener);

        image_animation = (ImageView) findViewById(R.id.timer_text);
        capturedImageHolder = (ImageView) findViewById(R.id.captured_image);

        next_button_take_photo = (ImageButton) findViewById(R.id.next_button_take_photo);
        back_button_take_photo = (ImageButton) findViewById(R.id.back_button_take_photo);
        progressBar_take_photo = (ProgressBar) findViewById(R.id.progressBar_take_photo);
        photo_title_text = (TextView) findViewById(R.id.photo_title_text);
    }

    //Next Button operation based on mobile number input
    private void nextButton() {
        next_button_take_photo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                hideKeyboard();

                if (bitmap != null) {
                    Intent newIntent = new Intent(getApplicationContext(), ConfirmationActivity.class);
                    startActivity(newIntent);
                }
            }
        });
    }

    //Back button operation
    private void backButton() {
        back_button_take_photo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Intent newIntent = new Intent(getApplicationContext(), AddressInputActivity.class);
                startActivity(newIntent);
            }
        });
    }

    //Progress bar operation
    private void progressBar() {

        //simpleProgressBar.setMax(100); // 100 maximum value for the progress value
        //simpleProgressBar.setProgress(50); // 50 default progress value for the progress bar

        // Get the Drawable custom_progressbar
        //Drawable draw=res.getDrawable(R.drawable.custom_progressbar);
        // set the drawable as progress drawable
        //progressBar.setProgressDrawable(draw);
    }

    //Normal text show
    private void nameTextShow() {
        String vsitorName = myPreferences.getVisitorName();
        photo_title_text.setText(vsitorName + ", please smile for the Camera");
    }

    OnClickListener switchCameraListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            //get the number of cameras
            int camerasNumber = Camera.getNumberOfCameras();
            if (camerasNumber > 1) {
                //release the old camera instance
                //switch camera, from the front and the back and vice versa

                releaseCamera();
                chooseCamera();
            } else {
                Toast toast = Toast.makeText(myContext, "Sorry, your phone has only one camera!", Toast.LENGTH_LONG);
                toast.show();
            }
        }
    };

    public void chooseCamera() {
        //if the camera preview is the front
        if (cameraFront) {
            int cameraId = findBackFacingCamera();
            if (cameraId >= 0) {
                //open the backFacingCamera
                //set a picture callback
                //refresh the preview

                mCamera = Camera.open(cameraId);
                mPicture = getPictureCallback();
                mPreview.refreshCamera(mCamera);
            }
        } else {
            int cameraId = findFrontFacingCamera();
            if (cameraId >= 0) {
                //open the backFacingCamera
                //set a picture callback
                //refresh the preview

                mCamera = Camera.open(cameraId);
                mPicture = getPictureCallback();
                mPreview.refreshCamera(mCamera);
            }
        }


    }

    @Override
    protected void onPause() {
        super.onPause();
        //when on Pause, release camera in order to be used from other applications
        releaseCamera();
    }

    private boolean hasCamera(Context context) {
        //check if the device has camera
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
            return true;
        } else {
            return false;
        }
    }

    private PictureCallback getPictureCallback() {
        PictureCallback picture = new PictureCallback() {

            @Override
            public void onPictureTaken(byte[] data, Camera camera) {

                if (data != null) {
                    //make a new picture file
                    File pictureFile = getOutputMediaFile();
                    bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                    String imageEncoded = Base64.encodeToString(data, Base64.DEFAULT);
                    myPreferences.setVisitorPhoto(imageEncoded);

                    if (bitmap == null) {
                        return;
                    }
                    try {
                        //write the file
                        FileOutputStream fos = new FileOutputStream(pictureFile);
                        fos.write(data);
                        fos.close();
                        //Toast toast = Toast.makeText(myContext, "Picture saved: " + pictureFile.getName(), Toast.LENGTH_LONG);
                        //toast.show();

                        //Method for image view
                        captureImageView();

                    } catch (FileNotFoundException e) {
                    } catch (IOException e) {
                    }

                    //refresh camera to continue preview
                    mPreview.refreshCamera(mCamera);
                }
            }
        };
        return picture;
    }

    **private void captureImageView(){
        //Visibitlity of camera photo
        cameraPreview.setVisibility(View.GONE);
        capturedImageHolder.setVisibility(View.VISIBLE);

        int screenWidth = getResources().getDisplayMetrics().widthPixels;
        int screenHeight = getResources().getDisplayMetrics().heightPixels;

        Camera.CameraInfo info = new Camera.CameraInfo();
        Matrix mtx = new Matrix();


        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            // Notice that width and height are reversed
            Bitmap scaled = Bitmap.createScaledBitmap(bitmap, screenHeight, screenWidth, true);
            int w = scaled.getWidth();
            int h = scaled.getHeight();

            // Perform matrix rotations/mirrors depending on camera that took the photo
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
            {
                float[] mirrorY = { -1, 0, 0, 0, 1, 0, 0, 0, 1};
                Matrix matrixMirrorY = new Matrix();
                matrixMirrorY.setValues(mirrorY);

                mtx.postConcat(matrixMirrorY);
            }

            // Setting post rotate to 90
            mtx.postRotate(270);
            // Rotating Bitmap
            bitmap = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, true);
            //capturedImageHolder.setImageBitmap(bitmap);
            capturedImageHolder.setImageBitmap(scaleDownBitmapImage(bitmap, 350, 450));
        }else{// LANDSCAPE MODE
            //No need to reverse width and height
            Bitmap scaled = Bitmap.createScaledBitmap(bitmap, screenWidth,screenHeight , true);
            bitmap=scaled;
            //capturedImageHolder.setImageBitmap(bitmap);
            capturedImageHolder.setImageBitmap(scaleDownBitmapImage(bitmap, 650, 300));
        }
    }**

    private Bitmap scaleDownBitmapImage(Bitmap bitmap, int newWidth, int newHeight) {
        Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
        return resizedBitmap;
    }

    OnClickListener captrureListener = new OnClickListener() {
        @Override
        public void onClick(View v) {

            //Visibitlity of camera photo
            cameraPreview.setVisibility(View.VISIBLE);
            capturedImageHolder.setVisibility(View.GONE);

            new Loading().execute();
            //timer.schedule(task, DELAY, DELAY);

            timerThread = new Thread()
            {
                public void run() {
                    for (i = 0; i < 6; i++) {
                        runOnUiThread(new Runnable() {
                            public void run() {
                                image_animation.setImageResource(imageArray[i]);
                            }
                        });
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if(i==6){
                            timerThread.interrupt();
                        }
                    }
                }
            };
            timerThread.start();
        }
    };



    private final TimerTask task = new TimerTask() {
        private int counter = 0;

        public void run() {
            handler.post(new Runnable() {
                public void run() {
                    image_animation.setImageResource(imageArray[i]);
                    i++;
                    if (i > imageArray.length - 1) {
                        i = 0;
                    }
                }
            });
            if (++counter == 6) {
                timer.cancel();
                timer.purge();
            }
        }
    };

    public class Loading extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... voids) {
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            // 6000ms=6s at intervals of 1000ms=1s so that means it lasts 5 seconds
            new CountDownTimer(5000, 1000) {

                @Override
                public void onTick(long millisUntilFinished) {
                    // every time 1 second passes
                    //tv.setText("" + millisUntilFinished/1000);
                   /* image_animation.setImageResource(imageArray[i]);
                    i++;
                    if (i > imageArray.length - 1) {
                        i = 0;
                    }*/
                }


                @Override
                public void onFinish() {
                    // count finished
                    //tv.setText("Picture Taken");
                    mCamera.takePicture(null, null, null, mPicture);
                }


            }.start();
        }
    }

    //make picture and save to a folder
    private static File getOutputMediaFile() {
        //make a new file directory inside the "sdcard" folder
        File mediaStorageDir = new File("/sdcard/", "JCG Camera");

        //if this "JCGCamera folder does not exist
        if (!mediaStorageDir.exists()) {
            //if you cannot make this folder return
            if (!mediaStorageDir.mkdirs()) {
                return null;
            }
        }

        //take the current timeStamp
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File mediaFile;
        //and make a media file:
        mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");

        return mediaFile;
    }

    private void releaseCamera() {
        // stop and release camera
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }

    private void hideKeyboard() {
        View view = getCurrentFocus();
        if (view != null) {
            ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).
                    hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

    @Override
    public void onBackPressed()
    {
        // code here to show dialog
        super.onBackPressed();  // optional depending on your needs
    }

    @Override
    protected void onDestroy() {
        if (mCamera != null) {
            mCamera.release();
        }
        super.onDestroy();
    }

    @Override
    public void onStop() {
        if (mCamera != null) {
            mCamera.release();
        }
        super.onStop();
    }
}

我现在得到的结果是什么,下面是我想要的。请注意在拍照时手在右侧,但在显示照片预览时手在左侧显示。

那么,如何解决这个问题呢?

enter image description here

最佳答案

不幸的是我们不能禁用镜像预览但是我们可以使用TextureView并申请SetTransform要反转相机预览,这仅适用于 API >= 14 。所以在你的 PhotoCaputeActivity 中尝试下面的代码

mCamera.setDisplayOrientation(90);
Matrix matrix = new Matrix();
matrix.setScale(-1, 1);
matrix.postTranslate(width, 0);
mTextureView.setTransform(matrix);

更多信息请查看this link.

另请注意

This is used with Front camera and when trying with Back camera make mTextureView.setTransform(null);

关于Android 相机照片预览即将倒转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47604896/

相关文章:

android - 我们如何测量物体和安卓手机摄像头之间的距离

android-camera - 透视投影中的笛卡尔坐标系

Android:获取摄像头名称(前置、后置、外置)

java - 将值从 fragment 传递到另一个错误

android - 从服务启动 Activity 总是打开 MainActivity

ios - 如果我们在真正的预提交处理程序中,由于 CA 限制,我们实际上不能添加任何新的栅栏

android - 在 android camera2API 中控制传感器 ISO 和曝光时间

android - Google Play 商店不显示新 apk 的更新选项

android - 未设置 "ArrayAdapter"

android - 释放异常相机预览后调用的方法