2011-12-01 104 views
22

我在写一个使用相机的Android应用程序。 我的相机显示方向设置为90,我的活动是在人像方向:拍摄后应该旋转Android摄像头生成的图像吗?

camera.setDisplayOrientation(90); 

我得到一个很好的面向预览图片,但由此产生的图像旋转到-90度(逆时针)和

exif.getAttribute(ExifInterface.TAG_ORIENTATION) 

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

设备 - 的Nexus S,API - 10

+0

同样的事情正在发生在我身上;我也在Nexus S API 10上;感谢您的问题。 – serkanozel

+0

在这里回答http://stackoverflow.com/questions/14066038/why-image-captured-using-camera-intent-gets-rotated-on-some-devices-in-android –

+1

可能的重复[为什么捕获的图像使用相机意图在Android上的某些设备上旋转?](https://stackoverflow.com/questions/14066038/why-does-an-image-captured-using-camera-intent-gets-rotated-on-some-devices -on-a) – bummi

回答

13

问题是相机的方向是一个完整的灾难(如拍摄图像),因为原始设备制造商不符合标准。 HTC手机做事情的方式之一,三星手机做不同的方式,Nexus线似乎坚持不管哪个厂商,基于CM7的ROM我认为遵循标准无论哪个硬件,但你明白了。你必须根据电话/ ROM确定要做什么。看到这里讨论:Android camera unexplainable rotation on capture for some devices (not in EXIF)

21

试试这个

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

对此工作的任何确认? – JoaoFilipeClementeMartins

+2

不,我的工作! – AabidMulani

+2

好奇你是如何得出结论的,这将适用于所有设备。 – sudocoder

1
camera.setDisplayOrientation(90); 

我已经编码只肖像模式的应用程序。

将相机旋转到90度,这可能会导致不适合在Android的 所有设备为了让所有的Android设备使用下面的代码,在开发者网站吹罚正确的预览。

下面,你必须把你的活动,cameraId =后面是0和前置摄像头为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设备。 可以克服使用下面

PLS注意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设备上都使用正确的肖像方向将图片旋转为仅肖像模式。

景观可以让这个为参考,并在下面的块

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 
     } 
+0

我想捕捉图像总是肖像,但我找不到位图的旋转角度。 –

4

我有同样的问题,像你这样的变化,但我已经修复它。
你应该使用相同的代码:

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

我希望你可以使用此代码太。