控制相机拍摄的人像照片不旋转的最终图像(Controlling the camera to take

2019-08-19 11:15发布

我试图控制Android相机拍照在肖像的应用程序,但是当我保存的图片,它的景观。 我旋转的图像90分的成绩与setCameraDisplayOrientation()方法,但不起作用。

然后我发现这个职位 ,但TAG_ORIENTATION0 (未定义)。 如果我抓住这个数值并应用旋转值,也不管用。

我怎么可以在人像照片,并具有良好的方向保存呢?

    /** Initializes the back/front camera */
private boolean initPhotoCamera() {
    try {
        camera = getCameraInstance(selected_camera);

        Camera.Parameters parameters = camera.getParameters();
   //           parameters.setPreviewSize(width_video, height_video);
   //           parameters.set("orientation", "portrait");
   //           parameters.set("rotation", 1);
   //           camera.setParameters(parameters);


        checkCameraFlash(parameters);

   //            camera.setDisplayOrientation( 0);
        setCameraDisplayOrientation(selected_camera, camera);


        surface_view.getHolder().setFixedSize(width_video, height_video);


        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(width_video, height_video);
        surface_view.setLayoutParams(lp);

        camera.lock();

        surface_holder = surface_view.getHolder();
        surface_holder.addCallback(this);
        surface_holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        setPreviewCamera();

    } catch (Exception e) {
        Log.v("RecordVideo", "Could not initialize the Camera");
        return false;
    }
    return true;
}

public void setCameraDisplayOrientation(int cameraId, Camera camera) {
     Camera.CameraInfo info = new Camera.CameraInfo();
     Camera.getCameraInfo(cameraId, info);
     int rotation = getWindowManager().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;
     }

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

     public static Bitmap rotate(Bitmap bitmap, int degree) {
    int w = bitmap.getWidth();
    int h = bitmap.getHeight();

    Matrix mtx = new Matrix();
   //       mtx.postRotate(degree);
    mtx.setRotate(degree);

    return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}

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



    String timeStamp = Calendar.getInstance().getTime().toString();
    output_file_name = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + timeStamp + ".jpeg";

    File pictureFile = new File(output_file_name);
    if (pictureFile.exists()) {
        pictureFile.delete();
    }

    try {
        FileOutputStream fos = new FileOutputStream(pictureFile);
        fos.write(data);

        Bitmap realImage = BitmapFactory.decodeFile(output_file_name);

        ExifInterface exif=new ExifInterface(pictureFile.toString());

        Log.d("EXIF value", exif.getAttribute(ExifInterface.TAG_ORIENTATION));
        if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("6")){
            realImage= rotate(realImage, 90);
        } else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("8")){
            realImage= rotate(realImage, 270);
        } else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("3")){
            realImage= rotate(realImage, 180);
        } else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("0")){
            realImage= rotate(realImage, 45);
        }

        boolean bo = realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);

        fos.close();

        Log.d("Info", bo + "");

    } catch (FileNotFoundException e) {
        Log.d("Info", "File not found: " + e.getMessage());
    } catch (IOException e) {
        Log.d("TAG", "Error accessing file: " + e.getMessage());
    }
}

Answer 1:

问题是,当我保存的图像我没有做好。

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

    String timeStamp = new SimpleDateFormat( "yyyyMMdd_HHmmss").format( new Date( ));
    output_file_name = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + timeStamp + ".jpeg";

    File pictureFile = new File(output_file_name);
    if (pictureFile.exists()) {
        pictureFile.delete();
    }

    try {
        FileOutputStream fos = new FileOutputStream(pictureFile);

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

        ExifInterface exif=new ExifInterface(pictureFile.toString());

        Log.d("EXIF value", exif.getAttribute(ExifInterface.TAG_ORIENTATION));
        if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("6")){
            realImage= rotate(realImage, 90);
        } else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("8")){
            realImage= rotate(realImage, 270);
        } else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("3")){
            realImage= rotate(realImage, 180);
        } else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("0")){
            realImage= rotate(realImage, 90);
        }

        boolean bo = realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);

        fos.close();

        ((ImageView) findViewById(R.id.imageview)).setImageBitmap(realImage);

        Log.d("Info", bo + "");

    } catch (FileNotFoundException e) {
        Log.d("Info", "File not found: " + e.getMessage());
    } catch (IOException e) {
        Log.d("TAG", "Error accessing file: " + e.getMessage());
    }
}

public static Bitmap rotate(Bitmap bitmap, int degree) {
    int w = bitmap.getWidth();
    int h = bitmap.getHeight();

    Matrix mtx = new Matrix();
   //       mtx.postRotate(degree);
    mtx.setRotate(degree);

    return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}


Answer 2:

setCameraDisplayOrientation()方法可以让你改变预览的方式,而不影响图像是如何记录(显示源 )。

为了改变实际记录的图像,你需要设置相机旋转参数。 你不喜欢这样:

//STEP #1: Get rotation degrees
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
    case Surface.ROTATION_0: degrees = 0; break; //Natural orientation
        case Surface.ROTATION_90: degrees = 90; break; //Landscape left
        case Surface.ROTATION_180: degrees = 180; break;//Upside down
        case Surface.ROTATION_270: degrees = 270; break;//Landscape right
    }
int rotate = (info.orientation - degrees + 360) % 360;

//STEP #2: Set the 'rotation' parameter
Camera.Parameters params = mCamera.getParameters();
params.setRotation(rotate); 
mCamera.setParameters(params);

您的解决方案是一种因为你修改图像后,已经记录的一种解决方法。 该解决方案是更清洁,不要求所有这些“如果”保存图像前发言。



Answer 3:

您可以使用下面的方法来使用前置摄像头时,你的正确生成预览。

这个代码进入你的相机预览的surfaceChanged方法

@Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
     int angleToRotate=CommonMethods.getRoatationAngle(mActivity, Camera.CameraInfo.CAMERA_FACING_FRONT);
     mCamera.setDisplayOrientation(angleToRotate);
}

此代码可以被放入一个静态类

 /**
     * Get Rotation Angle
     * 
     * @param mContext
     * @param cameraId
     *            probably front cam
     * @return angel to rotate
     */
    public static int getRoatationAngle(Activity mContext, int cameraId) {
        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(cameraId, info);
        int rotation = mContext.getWindowManager().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;
        }
        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360; // compensate the mirror
        } else { // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        return result;
    }

您可以旋转图像这个way.This仅用于当拍摄图像时,我们要保存的图像

public static Bitmap rotate(Bitmap bitmap, int degree) {
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        Matrix mtx = new Matrix();
        mtx.postRotate(degree);

        return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
    }

将被用于拍摄照片的方法

  @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        int angleToRotate = getRoatationAngle(MainActivity.this, Camera.CameraInfo.CAMERA_FACING_FRONT);
        // Solve image inverting problem
        angleToRotate = angleToRotate + 180;
        Bitmap orignalImage = BitmapFactory.decodeByteArray(data, 0, data.length);
        Bitmap bitmapImage = rotate(orignalImage, angleToRotate);
    }

bitmapImage包含正确的图像。



Answer 4:

这个应该工作,ExifInterface并不适用于所有的工作制成品所以使用CameraInfo代替,只是让摄像机捕获图像与它的默认旋转,然后旋转上PictureCallback结果数据

private PictureCallback mPicture = new PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        File dir = new File(Constant.SDCARD_CACHE_PREFIX);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        File pictureFile = new File(Constant.SDCARD_TAKE_PHOTO_CACHE_PREFIX);                       
        try {
            Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
            android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
            android.hardware.Camera.getCameraInfo(mCurrentCameraId, info);
            Bitmap bitmap = rotate(realImage, info.orientation);

            FileOutputStream fos = new FileOutputStream(pictureFile);               
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.close();                
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }

        resultFileUri = Uri.fromFile(pictureFile);
        startEffectFragment();
    }
};

public static Bitmap rotate(Bitmap bitmap, int degree) {
    int w = bitmap.getWidth();
    int h = bitmap.getHeight();

    Matrix mtx = new Matrix();
    mtx.postRotate(degree);

    return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}


Answer 5:

我没有代表发表评论,所以我不得不离开另一个答案相反,虽然Nvhausid答案是真棒,值得信贷。 简单,优雅,它适用于三星设备,其中的Exif和媒体光标不会在正面和背面摄像头。

答案是缺少对我来说唯一的办法就是从相机面向用户处理镜像。

下面是该代码的变化:

Bitmap bitmap = rotate(realImage, info.orientation, info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT);

而新的旋转方法:

public static Bitmap rotate(Bitmap bitmap, int degree, boolean mirror) {
    int w = bitmap.getWidth();
    int h = bitmap.getHeight();

    Matrix mtx = new Matrix();
    if(mirror)mtx.setScale(1,-1);
    mtx.postRotate(degree);

    return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}


Answer 6:

我找到你了有力的回答,我只是满足了同样的问题,解决它,但不保存文件。该解决方案是注册一个OrientationEventListener获得定向每当它改变。 http://www.androidzeitgeist.com/2013/01/fixing-rotation-camera-picture.html这里给details.My代码如下:

private CameraOrientationListener myOrientationListener;
private int rotation;    

protected void onCreate(Bundle savedInstanceState) {
  setListeners();
  rotation = setCameraDisplayOrientation(CameraActivity.this, Camera.getNumberOfCameras()-1, mCamera);
}

public void setListeners(){
    myOrientationListener = new CameraOrientationListener(this);
    if(myOrientationListener.canDetectOrientation())
        myOrientationListener.enable();
}

public static int setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) {
     CameraInfo info = new CameraInfo();
     Camera.getCameraInfo(cameraId, info);
     int rotation = activity.getWindowManager().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;
     }

     int result;
     if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
         result = (info.orientation + degrees) % 360;
         result = (360 - result) % 360;  // compensate the mirror
     } else {  // back-facing
         result = (info.orientation - degrees + 360) % 360;
     }
     camera.setDisplayOrientation(result);

     return result;
 }

/*
 * record the rotation when take photo
 */
public void takePhoto(){
    myOrientationListener.rememberOrientation();
    rotation += myOrientationListener.getRememberedOrientation();
    rotation = rotation % 360;

    mCamera.takePicture(null, null, mPicture);
}    

class CameraOrientationListener extends OrientationEventListener {
    private int currentNormalizedOrientation;
    private int rememberedNormalizedOrientation;

    public CameraOrientationListener(Context context) {
        super(context, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    public void onOrientationChanged(int orientation) {
        // TODO Auto-generated method stub
        if (orientation != ORIENTATION_UNKNOWN) {
            currentNormalizedOrientation = normalize(orientation);
        }
    }

    private int normalize(int degrees) {
         if (degrees > 315 || degrees <= 45) {
            return 0;
        }

        if (degrees > 45 && degrees <= 135) {
            return 90;
        }

        if (degrees > 135 && degrees <= 225) {
            return 180;
        }

        if (degrees > 225 && degrees <= 315) {
            return 270;
        }

        throw new RuntimeException("The physics as we know them are no more. Watch out for anomalies.");
    }

    public void rememberOrientation() {
        rememberedNormalizedOrientation = currentNormalizedOrientation;
    }

    public int getRememberedOrientation() {
        return rememberedNormalizedOrientation;
    }
}

希望能帮助到你:)



Answer 7:

这是使用(下面提到)当你的布局固定在纵向模式下的最佳方法。

@Override
protected void onResume() {
    super.onResume();
    if (!openCamera(CameraInfo.CAMERA_FACING_BACK)) {
        alertCameraDialog();
    }
    if (cOrientationEventListener == null) {
        cOrientationEventListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {


            public void onOrientationChanged(int orientation) {

                // determine our orientation based on sensor response
                int lastOrientation = mOrientation;


                    if (orientation == ORIENTATION_UNKNOWN) return;
                    Camera.CameraInfo info =
                            new android.hardware.Camera.CameraInfo();
                    android.hardware.Camera.getCameraInfo(cameraId, info);
                    orientation = (orientation + 45) / 90 * 90;
                    int rotation = 0;
                    if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
                        rotation = (info.orientation - orientation + 360) % 360;
                    } else {  // back-facing camera
                        rotation = (info.orientation + orientation) % 360;
                    }
                        Parameters params = camera.getParameters();
                        params.setRotation(rotation);
                        camera.setParameters(params);




            }

            };


        }


    if (cOrientationEventListener.canDetectOrientation()) {
        cOrientationEventListener.enable();
    }
    }

您将使用OrientEventListener和实现这个回调方法。 每当有方向变化。因此您的相机旋转将设置和图像将被旋转时,你会保存onOrientationChanged被调用。

      private PictureCallback myPictureCallback_JPG = new PictureCallback() 

       { 

   @Override
   public void onPictureTaken(byte[] arg0, Camera arg1) {
    try {  
               File pictureFile = getOutputMediaFile();
           if (pictureFile == null) {
               return;
           }
               FileOutputStream fos = new FileOutputStream(pictureFile);
               fos.write(arg0);
               fos.close();     
              camera.startPreview();
       } catch (Exception e) {
           e.printStackTrace();
       }
   } 
 };

getOutputMediaFile

  private static File getOutputMediaFile() {
            File mediaStorageDir = new File(
               Environment


         .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
            "MyCameraApp");
         if (!mediaStorageDir.exists()) {
        if (!mediaStorageDir.mkdirs()) {
            Log.d("MyCameraApp", "failed to create directory");
            return null;
        }
    }
    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
            .format(new Date());
    File mediaFile;
    mediaFile = new File(mediaStorageDir.getPath() + File.separator
            + "IMG_" + timeStamp + ".jpg");

    return mediaFile;
  }

来源这里



Answer 8:

我使用了新的camera2 API来获取传感器的方向,然后相应地旋转它:

  private void detectSensorOrientation()
  {
    CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
    try
    {
      for (String cameraId : manager.getCameraIdList())
      {
        CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);

        // We don't use a front facing camera in this sample.
        Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
        if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT)
        {
          continue;
        }

        cameraOrientaion = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
      }
    } catch (CameraAccessException e)
    {
      e.printStackTrace();
    }
  }

然后用cameraOrientation参数的帮助下,我转动我的cameraPhoto:

  private void generateRotatedBitmap()
  {
    if (cameraOrientaion != 0)
    {
      Matrix matrix = new Matrix();
      matrix.postRotate(cameraOrientaion);
      rotatedPhoto =
          Bitmap.createBitmap(cameraPhoto, 0, 0, cameraPhoto.getWidth(), cameraPhoto.getHeight(),
              matrix, true);
      cameraPhoto.recycle();
    }
  }


文章来源: Controlling the camera to take pictures in portrait doesn't rotate the final images