摄像头camera 旋转90度 解决方法

拍照需要竖屏时的解决方法。
zxing官方wiki上面的解决办法。

基本思路如下。
There are 4 relative files:
1.manifest.xml, you need to make CaptureActivity portrait.

2.DecodeHandler.java, rotate data before buildLuminanceSource, it works becuase in YCbCr_420_SP and YCbCr_422_SP, the Y channel is planar and appears first

  1. byte[] rotatedData = new byte[data.length]; 
  2. for (int y = 0; y < height; y++) { 
  3.      for (int x = 0; x < width; x++) 
  4.          rotatedData[x * height + height - y - 1] = data[x + y * width]; 
  5.  }

3.CameraManager.java, getFramingRectInPreview() need to be modified.

  1.  rect.left = rect.left * cameraResolution.y / screenResolution.x;
  2.  rect.right = rect.right * cameraResolution.y / screenResolution.x;
  3.  rect.top = rect.top * cameraResolution.x / screenResolution.y;
  4.  rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;

4.CameraConfigurationManager.java, set camera orientation to portrait in setDesiredCameraParameters() use

  1.  parameters.set("orientation", "portrait");

注:版本兼容请看下面。
and in getCameraResolution(), you need to swap x and y, because camera preview size is something like 480*320, other than 320*480.

  1.  int tmp = cameraResolution.x;
  2.  cameraResolution.x = cameraResolution.y;
  3.  cameraResolution.y = tmp;
  4.  return cameraResolution;

说明:
关于摄像头旋转90度的时候,不同的sdk版本方法不同。
兼容方法如下

  1.  if (Integer.parseInt(Build.VERSION.SDK) >= 8)
  2.     setDisplayOrientation(camera, 90);
  3.    else {
  4.     if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
  5.      parameters.set("orientation", "portrait");
  6.      parameters.set("rotation", 90);
  7.     }
  8.     if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
  9.      parameters.set("orientation", "landscape");
  10.      parameters.set("rotation", 90);
  11.     }
  12.  }
  13.  protected void setDisplayOrientation(Camera camera, int angle) {
  14.    Method downPolymorphic;
  15.    try {
  16.     downPolymorphic = camera.getClass().getMethod(
  17.       "setDisplayOrientation", new Class[] { int.class });
  18.     if (downPolymorphic != null)
  19.      downPolymorphic.invoke(camera, new Object[] { angle });
  20.    } catch (Exception e1) {
  21.    }
  22.   }

转自:http://www.andcoder.com/archives-2011-10-383.html

大意:

1.在DecodeHandler.java中,修改decode方法
  PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(data, width, height);

    byte[] rotatedData = new byte[data.length];
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++)
            rotatedData[x * height + height - y - 1] = data[x + y * width];
    }
    int tmp = width; // Here we are swapping, that's the difference to #11
    width = height;
    height = tmp;
    
    PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(rotatedData, width, height);

2.在CameraManager.java中,注释代码:
            // rect.left = rect.left * cameraResolution.x / screenResolution.x;
            // rect.right = rect.right * cameraResolution.x / screenResolution.x;
            // rect.top = rect.top * cameraResolution.y / screenResolution.y;
            // rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
修改为
            rect.left = rect.left * cameraResolution.y / screenResolution.x;
            rect.right = rect.right * cameraResolution.y / screenResolution.x;
            rect.top = rect.top * cameraResolution.x / screenResolution.y;
            rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;

3.在CameraConfigurationManager.java中,在setDesiredCameraParameters方法中添加一句
  camera.setDisplayOrientation(90);

4.在AndroidManifest.xml中,把Activity的属性android:screenOrientation="landscape"
改为
  android:screenOrientation="portrait"

编译运行即可!


参考:

http://code.google.com/p/zxing/issues/detail?id=178#c46


代码:

https://github.com/pplante/zxing-android

---------------------------------华丽分割线-----------------------------------

在写相机相关应用的时候遇到捕获的画面方向和手机的方向不一致的问题,比如手机是竖着拿的,但是画面是横的,这是由于摄像头默认捕获的画面byte[]是根据横向来的,而你的应用是竖向的,解决办法是调用setDisplayOrientation来设置PreviewDisplay的方向,效果就是将捕获的画面旋转多少度显示。
设置 preview 的顺时针旋转角度。这将影响 preview frames 和拍照之后的相片显示。该方法主要用于垂直模式的应用。注意在旋转之前, front-facing cameras 的 preview 显示是水平 flip 的,这就是说, image 是沿着 camera sensor 的垂直中心轴来反射的。所以用户可以像照镜子一样看到他们自己。这不会影响传入函数 onPreviewFrame(byte[], Camera) 的、 JPEG 相片的、或记录的 video 的 byte array 的顺序,你可以自己做旋转处理。在 preview 期间是不允许调用该方法的。如果你想要是你的照片和显示出来的角度一致,你可以参考下列代码:

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 ;
      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 );
  }

来源:   http://www.fish24k.com/?p=655965

--------------------------------又来-华丽分割线-----------------------------------

android 相机旋转90度的处理方法 

public void surfaceChanged(SurfaceHolder holder, int format, int width,int height)
 {

  Camera.Parameters parameters = camera.getParameters();

//SDK版本选择,兼容

  if (Integer.parseInt(Build.VERSION.SDK) >= 8)
   setDisplayOrientation(camera, 90);
  else {
   if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
    parameters.set("orientation", "portrait");
    parameters.set("rotation", 90);
   }
   if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
    parameters.set("orientation", "landscape");
    parameters.set("rotation", 90);
   }
  }

  parameters.setPictureFormat(PixelFormat.JPEG);
  List sizes = parameters.getSupportedPreviewSizes();
  Size optimalSize = getOptimalPreviewSize(sizes, width, height);
  parameters.setPictureSize(optimalSize.width, optimalSize.height);

  camera.setParameters(parameters);
  camera.startPreview();
 }

// 
 protected void setDisplayOrientation(Camera camera, int angle) {
  Method downPolymorphic;
  try {
   downPolymorphic = camera.getClass().getMethod(
     "setDisplayOrientation", new Class[] { int.class });
   if (downPolymorphic != null)
    downPolymorphic.invoke(camera, new Object[] { angle });
  } catch (Exception e1) {
  }
 } 

// 获得 camera 大小
  private Size getOptimalPreviewSize(List sizes, int w, int h)
  {        
   final double ASPECT_TOLERANCE = 0.2;       
   double targetRatio = (double) w / h;        
   if (sizes == null)            
    return null;         
   Size optimalSize = null;        
   double minDiff = Double.MAX_VALUE;         
   int targetHeight = h;         
   // Try to find an size match aspect ratio and size        
   for (Size size : sizes)
   {            
    Log.d("dd", "Checking size " + size.width + "w " + size.height + "h");           
    double ratio = (double) size.width / size.height;           
    if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)               
     continue;            
    if (Math.abs(size.height - targetHeight) < minDiff)
    {                
     optimalSize = size;                
     minDiff = Math.abs(size.height - targetHeight);            
     }        
    }      

你可能感兴趣的:(Android常用技巧)