使用相机拍照后旋转位图

时间:2015-03-10 21:14:23

标签: android bitmap imageview android-camera exif

使用Camera API和预览SurfaceView在设备处于人像状态下拍摄照片后,创建的图像将旋转90度。我知道这是一个影响某些 Android手机的问题,包括我正在开发的三星Galaxy S5 - 有几个堆栈溢出问题 - see herehere 。建议图像文件包含EXIF元数据,该元数据将说明旋转的方向,以便您可以使用它来旋转图像以获得正确的方向。我已经做到了这一点,但出于某种原因,ExifInterface.TAG_ORIENTATION1 - ORIENTATION_NORMAL。因此,我无法确定需要旋转多少图像以确保它可以在所有设备上运行。即使该解决方案似乎对其他人有效。我做错了什么,或者这个问题怎么解决?

一些伪代码:

//in onCreate
camera = getCameraInstance();
setCameraDisplayOrientation(this, cameraID, camera);

//in OnClickListener
camera.takePicture(null, null, picCallback);

//callback:
onPictureTaken {
    //create a File using getExternalStoragePublicDirectory(PICTURES) + "appname" - create directory if doesn't exist
    //write file to disk via FileOutputStream

    //attempt to correct the image orientation if needed
    Bitmap correctBitmap = getCorrectOrientationBitmap(picFile.getAbsolutePath());
}

public Bitmap getCorrectOrientationBitmap(String photoFilePath) {
    // Read EXIF Data
    ExifInterface exif = null;
    try {
        exif = new ExifInterface(photoFilePath);
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
    String orientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
    //problem: orientation is 1 - ORIENTATION_NORMAL despite the fact the image is rotated to the right 90 degrees
    //rotate the image based on EXIF orientation
}

//later on
myImageView.setImageBitmap(correctBitmap); 
//shows image rotated to the right because getCorrectOrientationBitmap didn't rotate it

4 个答案:

答案 0 :(得分:0)

- EDIT-- 在我的代码中......

matrix.postRotate(旋转);

使用felix代码从光标返回的“rotation”值。

我认为你的照片有一个URI ....看看界面与使用类型的静态attr值....

public static int getOrientation(Context context, Uri photoUri) {
    /* it's on the external media. */
    Cursor cursor = context.getContentResolver().query(photoUri,
            new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null);
    if(null == cursor){
        return -1;
    }
    if (cursor.getCount() != 1) {
        return -1;
    }

.....

if (getOrientation(mctx, mURI) != 0 && != -1) doRotate();


public doRotate(){
    Bitmap lbit =   
    BitmapFactory.decodeStream(                                               getContentResolver().openInputStream(_uri),null,options);
    Log.i(TAG, "Rotating... " + rotation);
    lbit = lbit.copy(Bitmap.Config.ARGB_8888, true);
    Matrix matrix = new Matrix();
    matrix.postRotate(rotation);
    lbit = Bitmap.createBitmap(lbit, 0, 0, lbit.getWidth(),
    lbit.getHeight(), matrix, true);
    Picture.setBmp(lbit);

    cursor.moveToFirst();
    return cursor.getInt(0);
    }
}

答案 1 :(得分:0)

前一段时间我正在玩这个问题,并在GitHub here上发布了一些相机代码。问题是你要处理3个不同的实体:

  • 表面方向 - 取决于当前的设备方向
  • 'surfaceChanged'
  • 获取预览宽度/高度
  • 来自' takePicture'
  • 的最终图片方向

在上述示例中,我rotate the final的图片数量与我旋转preview at the beginning时的数量相同。我还没有在S5上测试过,所以如果你这样做,请告诉我它是否适用。

还有一件事,一些平板电脑也存在问题(see readme.md),其中一些平板电脑有'natural' orientation landscape (Nex7 1Gen),其他平板电脑(Nex7 2Gen)的画像与手机相同。

祝你好运

答案 2 :(得分:0)

使用图片回调而不是相机捕捉意图时,不会设置EXIF方向。但另一方面,当用户点击“捕获”按钮或其等效按钮时,您可以确切地知道设备方向。

如果您的活动被锁定在纵向方向,则变得更加容易 - 您可以无条件地将旋转旋转90°。

在内存和性能方面,位图旋转可能相当昂贵,因此如果通过设置正确的TAG_ORIENTATION来满足您的用例,则只需将此更改应用于您保存的图像。请注意ExifInterface适用于文件,而不是byte[],因此违反直觉,您应首先保存缓冲区,然后应用旋转,然后再次保存。

答案 3 :(得分:-1)

在拍照之前,根据当前的设备方向,需要setDisplayOrientation()。这不是自动完成的,默认情况下始终设置为0度,通常对应于横向。

这不是Galaxy s5问题