大多数的相机程序都使用横向拍照,这也是摄像头传感器的自然方向。但是这并不影响您在竖屏的时候拍照,设备的方向信息会存储到图片的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,跟照片尺寸比例不一样,所以预览图像会被拉伸。
<SurfaceView
android:id="@+id/preview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:keepScreenOn="true"
>
</SurfaceView>
解决:在程序中使SurfaceView尺寸比例与照片尺寸比例相同,如下面代码所示;
@Override
public 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){@Overridepublic 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();}