【问题标题】:Android camera resulted image should be rotated after the capture?Android相机结果图像应在捕获后旋转?
【发布时间】:2011-12-01 19:14:21
【问题描述】:

我正在编写一个使用相机的 Android 应用程序。 我将相机显示方向设置为 90,我的活动是纵向的:

camera.setDisplayOrientation(90);

我得到了一个方向良好的预览图片,但生成的图像旋转到 -90 度(逆时针)并且

exif.getAttribute(ExifInterface.TAG_ORIENTATION)

返回 ORIENTATION_NORMAL
这是预期的行为吗?我应该在捕获后旋转结果图像吗?

设备 - Nexus S,API - 10

【问题讨论】:

标签: android camera rotation


【解决方案1】:

试试这个

try {
        File f = new File(imagePath);
        ExifInterface exif = new ExifInterface(f.getPath());
        int orientation = exif.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);

        int angle = 0;

        if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
            angle = 90;
        } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
            angle = 180;
        } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
            angle = 270;
        }

        Matrix mat = new Matrix();
        mat.postRotate(angle);
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 2;

        Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f),
                null, options);
        bitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(),
                bmp.getHeight(), mat, true);
        ByteArrayOutputStream outstudentstreamOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100,
                outstudentstreamOutputStream);
        imageView.setImageBitmap(bitmap);

    } catch (IOException e) {
        Log.w("TAG", "-- Error in setting image");
    } catch (OutOfMemoryError oom) {
        Log.w("TAG", "-- OOM Error in setting image");
    }

会有用的

【讨论】:

  • 很好奇您是如何得出这适用于所有设备的结论的。
【解决方案2】:

问题是相机方向是一场彻底的灾难(就像捕捉图像一样),因为 OEM 不遵守标准。 HTC 手机以一种方式做事,三星手机以不同的方式做事,Nexus 系列似乎无论哪个供应商都坚持,基于 CM7 的 ROM 我认为无论哪种硬件都遵循标准,但你明白了。您必须根据手机/ROM确定要做什么。请参阅此处的讨论:Android camera unexplainable rotation on capture for some devices (not in EXIF)

【讨论】:

    【解决方案3】:

    我和你有同样的问题,但我已经解决了。
    您应该使用相同的代码:

    Camera.Parameters parameters = camera.getParameters();
    parameters.setRotation(90);
    camera.setParameters(parameters);
    

    我希望你也可以使用这个代码。

    【讨论】:

    • 谢谢,问题解决了!它在我的三星 Galaxy S8+ 上运行良好
    【解决方案4】:
    camera.setDisplayOrientation(90);
    

    我只为纵向模式编写了应用程序。

    将使相机旋转到 90 度,这可能导致不适用于 android 中的所有设备 为了获得所有 android 设备的正确预览,请使用以下代码,该代码在开发人员站点中被引用。

    您必须在下面发送您的活动,cameraId = back 为 0,Front camera 为 1

    public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) {
        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
        android.hardware.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;
        //int currentapiVersion = android.os.Build.VERSION.SDK_INT;
            // do something for phones running an SDK before lollipop
            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);
    } 
    

    这是设置相机的setDisplayOrientation的方法

    现在您可能无法以正确的方向保存捕获的图像,这是相机 API 中的错误,以支持 android 中的所有设备。您可以使用以下步骤克服

    请注意 EXIF 值不会在所有设备中为您提供正确的值,所以这会对您有所帮助

    int CameraEyeValue = setPhotoOrientation(CameraActivity.this, cameraFront==true ? 1:0); // CameraID = 1 : front 0:back
    

    通过使用我们之前用于 DisplayOrientation 的相同概念

    public int setPhotoOrientation(Activity activity, int cameraId) {
        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
        android.hardware.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;
        // do something for phones running an SDK before lollipop
        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;
    }
    

    所以你最终的 PictureCallBack 方法应该看起来像

    private PictureCallback getPictureCallback() {
        PictureCallback picture = new PictureCallback() {
    
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                //make a new picture file
                File pictureFile = getOutputMediaFile();
    
                if (pictureFile == null) {
                    return;
                }
                try {
                    //write the file
                    FileOutputStream fos = new FileOutputStream(pictureFile);
                    Bitmap bm=null;
    
                    // COnverting ByteArray to Bitmap - >Rotate and Convert back to Data
                    if (data != null) {
                        int screenWidth = getResources().getDisplayMetrics().widthPixels;
                        int screenHeight = getResources().getDisplayMetrics().heightPixels;
                        bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0);
    
                        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                            // Notice that width and height are reversed
                            Bitmap scaled = Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true);
                            int w = scaled.getWidth();
                            int h = scaled.getHeight();
                            // Setting post rotate to 90
                            Matrix mtx = new Matrix();
    
                            int CameraEyeValue = setPhotoOrientation(AndroidCameraExample.this, cameraFront==true ? 1:0); // CameraID = 1 : front 0:back
                            if(cameraFront) { // As Front camera is Mirrored so Fliping the Orientation
                                if (CameraEyeValue == 270) {
                                    mtx.postRotate(90);
                                } else if (CameraEyeValue == 90) {
                                    mtx.postRotate(270);
                                }
                            }else{
                                    mtx.postRotate(CameraEyeValue); // CameraEyeValue is default to Display Rotation
                            }
    
                            bm = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, true);
                        }else{// LANDSCAPE MODE
                            //No need to reverse width and height
                            Bitmap scaled = Bitmap.createScaledBitmap(bm, screenWidth, screenHeight, true);
                            bm=scaled;
                        }
                    }
                    // COnverting the Die photo to Bitmap
    
    
    
                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    bm.compress(Bitmap.CompressFormat.JPEG, 100, stream);
                    byte[] byteArray = stream.toByteArray();
                    fos.write(byteArray);
                    //fos.write(data);
                    fos.close();
    
                    Toast toast = Toast.makeText(myContext, "Picture saved: " + pictureFile.getName(), Toast.LENGTH_LONG);
                    toast.show();
    
                } catch (FileNotFoundException e) {
                } catch (IOException e) {
                }
    
                //refresh camera to continue preview
                mPreview.refreshCamera(mCamera);
                mPreview.setCameraDisplayOrientation(CameraActivity.this,GlobalCameraId,mCamera);
            }
        };
        return picture;
    }
    

    仅适用于使用前置和后置摄像头的人像模式图片在所有 android 设备中旋转为仅具有正确人像方向的人像模式。

    对于 LandScape,您可以将此作为参考并在下面的块中进行更改

       if(cameraFront) { // As Front camera is Mirrored so Fliping the Orientation
             if (CameraEyeValue == 270) {
                 mtx.postRotate(90); //change Here 
              } else if (CameraEyeValue == 90) {
                 mtx.postRotate(270);//change Here 
               }
            }else{
               mtx.postRotate(CameraEyeValue); // CameraEyeValue is default to Display Rotation //change Here 
            }
    

    【讨论】:

    • 我希望始终以纵向拍摄图像,但我找不到位图的旋转角度。
    猜你喜欢
    • 2020-02-11
    • 1970-01-01
    • 1970-01-01
    • 2014-01-20
    • 2021-05-11
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多