Android Camera 照相机屏幕旋转问题

时间:2022-04-19 20:27:34
大多数的相机程序都使用横向拍照,这也是摄像头传感器的自然方向。但是这并不影响您在竖屏的时候拍照,设备的方向信息会存储到图片的EXIF信息中。可以通过函数 setCameraDisplayOrientation() 来改变预览的显示方向而不影响图片的保存数据。然而,在API level 14之前的版本中,在修改预览方向之前需要先停止预览窗口然后重新启动预览。
(1)旋转手机时,SurfaceView 预览图像反转或旋转90度。 解决:在拍照过程中应该设置为将内容始终横屏显示,这样,在拍照程序中SurfaceView的内容就不会旋转90度或180度了。 在AndroidManifest.xml中设置android:screenOrientation="landscape"。代码如下: <application android:icon="@drawable/icon" android:label="@string/app_name"android:theme="@android:style/Theme.NoTitleBar"><activity android:name=".MainActivity" android:label="@string/app_name"android:screenOrientation="landscape">     <intent-filter>          <action android:name="android.intent.action.MAIN" />         <category android:name="android.intent.category.LAUNCHER" />     </intent-filter></activity></application>
有些游戏只能横屏玩或只能竖屏玩,所以经常要设置android:screenOrientation,landscape为横屏,portrait为竖屏。
(2)预览图像被拉伸变形 这是由照片图像 跟 预览图像的尺寸比例不一样造成的,例如我的手机是HTC Incredible S 有800万像素,默认的照片尺寸3264*2448(4:3),而我们SurfaceView通常是设为wrap_content如下面mail.xml中的代码所示,拍照时屏幕尺寸大概为800*442(带通知栏)或800*480(全屏),比例约为5:3,跟照片尺寸比例不一样,所以预览图像会被拉伸。 <SurfaceViewandroid:id="@+id/preview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:keepScreenOn="true"></SurfaceView> 解决:在程序中使SurfaceView尺寸比例与照片尺寸比例相同,如下面代码所示; @Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {Camera.Parameters parameters = camera.getParameters();// 获得相机参数Size s = parameters.getPictureSize();double w = s.width;double h = s.height;
if( width>height ){surfaceView.setLayoutParams(new LinearLayout.LayoutParams( (int)(height*(w/h)), height) );}else{surfaceView.setLayoutParams(new LinearLayout.LayoutParams( width, (int)(width*(h/w)) ) );}parameters.setPreviewSize(width, height); // 设置预览图像大小parameters.setPictureFormat(PixelFormat.JPEG); // 设置照片格式camera.setParameters(parameters);// 设置相机参数camera.startPreview();// 开始预览}

(3)拍照图片旋转问题: 解决方法一:要在拍照前,设置rotationn属性,parameters.setRotation()。 在android API Level 14开始出现了android.hardware.Camera.CameraInfo类,可以比较方便地设置摄像机保存图像的旋转角度。
 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);
 
}
解决方法二:在oncreate方法中添加OrientationEventListener,OrientationEventListener(方向事件监听器)是一个当方向发生变化时, 从 SensorManager(传感器管理程序)接收通知的辅助类,我就是通过这个来判断手机屏幕的旋转角度,从而将获取后的图片做相应的旋转。
mOrientationListener = new OrientationEventListener(this){              @Override              public void onOrientationChanged(int orientation) {                  orientations =orientation;                  Log.v("time", "现在是横屏"+orientation);                              }          };  在onResume中启动事件的监听器
if(mOrientationListener!=null){//先判断下防止出现空指针异常              mOrientationListener.enable();          }  在onPictureTaken中将图片旋转相应的角度:
BitmapFactory.Options opts = new BitmapFactory.Options();                  opts.inPreferredConfig = Config.RGB_565;                  opts.inSampleSize =4;                   Bitmap bmp = BitmapFactory.decodeByteArray(images, 0, images.length,opts);                  Matrix matrixs = new Matrix();                      if(orientations > 325 || orientations <= 45){                          Log.v("time", "Surface.ROTATION_0;"+orientations);                          matrixs.setRotate(90);                      }else if(orientations > 45 && orientations <= 135){                          Log.v("time", " Surface.ROTATION_270"+orientations);                      matrixs.setRotate(180);                      }else if(orientations > 135 && orientations < 225){                          Log.v("time", "Surface.ROTATION_180;"+orientations);                      matrixs.setRotate(270);                      }else {                          Log.v("time", "Surface.ROTATION_90"+orientations);                      matrixs.setRotate(0);                      }                  bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrixs, true);   这样图片就旋转过来了,最后别忘了在onPause中将事件监听器关掉:if(mOrientationListener!=null){              mOrientationListener.disable();          }