当前位置: 首页 > 科技观察

WP8.1:开发如何处理相机翻转

时间:2023-03-12 12:40:12 科技观察

模拟器就像我们儿时的梦想,在其上运行应用程序时,一切总是美好的;而真机测试就如同我们混沌的现实世界,会遇到形形色色的小人猛兽,经常会遭遇莫名其妙的挫折。面对挫折,有的人迎难而上,或者置之不理,我行我素;有些人退缩了。面对翻转相机的问题,有些人会选择逃避。我之所以不喜欢现在的一些程序员,是因为这些人只能逃避,只能制造问题。遇到问题不找解决办法,坐在那里对爸爸妈妈大吼大叫。虽然不可能解决所有的问题,但是可以解决的问题很多,而这些人总是心神不定,不愿意静下心来仔细思考。N+6年前,我读了一本好书,名叫《方法总比问题多》。考虑到这一点,我认为翻转相机的问题就可以解决了。通常,我们很少调用前置摄像头,更多时候我们使用的是后置摄像头。当然,解决方案是相似的。因此,为了便于理解,我将以后置摄像头为例来分享我的解决方案。如果大家有更好的方法,不妨让大家参考一下。一般来说,真机上的摄像头在水平放置时与手机成同一角度,即偏90度(手机逆时针旋转)。也就是说,当手机逆时针旋转90度时,机器的方向与相机的方向是一致的。针对这种情况,我们只要能做一件事,就可以解决相机翻转的问题。锁定页面方向,即当手机方向改变时,禁止页面旋转即可。这里以Silverlight框架为例,RuntimeApp比较好办,只需要在manifest文件中强制屏幕方向为landscape即可。但是Silverlight程序需要一些步骤。1、设置页面的SupportedOrientations="Landscape"和Orientation="LandscapeLeft",如下面XAML所示。...这样限制了页面支持的方向改为横向,页面v的默认方向也改为LandscapeLeft,即手机逆时针旋转90度。如果是LandscapeRight,v表示手机逆时针旋转270度。2.仅仅强制页面水平是不够的,因为水平方向有两个方向——90度和270度。当手机旋转90度时,其方向与摄像头重合。正好和相机的方向相反,也就是转了180度。这时候你在手机屏幕上看到的相机预览是倒过来的,拍出来的照片当然也是倒过来的。关于保存照片,以后再说。因此,我们必须找到一种方法来防止页面改变其方向。就这样,页面类有一个名为OnOrientationChanged的??虚方法,当页面的方向发生变化时将调用该方法。只要重写这个方法,不加任何代码,就可以阻止页面的基类调用这个方法,从而防止页面改变方向。《搜狐拍客》就是用这种方法来解决翻页问题的。protectedoverridevoidOnOrientationChanged(OrientationChangedEventArgse){//注释掉下面的代码,页面的方向会被锁定//base.OnOrientationChanged(e);}注意。base.OnOrientationChanged(e);这行代码必须去掉,否则会调用基类。3、通过以上步骤,相机预览翻转的问题解决了,但是又出现了一个新的问题:如果屏幕的方向和相机的方向不一致,拍出来的照片也会颠倒。对于这个问题,必须在图片文件上下功夫,即调整图片的方向并保存。我的例子是使用MediaCapture类进行拍摄,拍摄的图片直接保存到文件或流中,那么我们如何修改图片呢?在Windows.Graphics.Imaging命名空间下,可以使用BitmapDecoder类对图像进行解码,提取图像的像素数据;BitmapEncoder类可以将图像的像素数据编码成图像文件。是的,我们使用这两个类首先对相机拍摄的照片进行解码,然后使用旋转变换修改图像的方向,最后对修改后的图像进行重新编码。至于将图片旋转到哪个方向,大家不妨自己尝试一下,对比一下就知道了。下面是参考代码:#region图像解码编码asyncTaskEncodeImage(IRandomAccessStreaminStream,IRandomAccessStreamoutStream){GuidjpegIDen=BitmapEncoder.JpegEncoderId;//编码器IDGuidjpegIDde=BitmapDecoder.JpegDecoderId;//获取解码器IDBitmapDecoderdecoder=awaitBitmapDecoder.CreatepegID);(]buffer=(awaitdecoder.GetPixelDataAsync()).DetachPixelData();BitmapEncoder=awaitBitmapEncoder.CreateAsync(jpegIDen,outStream);//判断手机方向改变图像方向varort=ortsensor.GetCurrentOrientation();switch(ort){caseSimpleOrientation.NotRotated:encoder.BitmapTransform.Rotation=BitmapRotation.Clockwise90Degrees;break;caseSimpleOrientation.Rotated180DegreesCounterclockwise:encoder.BitmapTransform.Rotation=BitmapRotation.Clockwise270Degrees;break;caseSimpleOrientation.Rotated270DegreesCounterclockwise:encoder.BitmapTransform.Rotation=BitmapRotation.Clockwise180Degrees;break;caseSimpleOrientation.Rotated90DegreesCounterclockwise:encoder.BitmapTransform.Rotation=BitmapRotation.无;中断;}//设置像素数据awaitencoder.FlushAsync();}#endregion在确认图片旋转方向之前,我们必须知道手机当前的方向。更简单的方法是直接访问Windows.Graphics.Display.DisplayProperties类的CurrentOrientation属性,但是这个类在新版本中可能会被删除,所以我没有使用这种方法。所以我选择了稍微复杂一点的方法——使用方向传感器。这种方法有点自命不凡,但我们可以直接使用传感器。事实上,屏幕的方向也是由方向(重力)传感器识别的。为了让开发者方便的识别手??机的几个特殊方向,通过SimpleOrientation枚举定义了几个常用的方向。这些值的含义如下表所示。相应的,在Windows.Devices.Sensors命名空间下,有一个SimpleOrientationSensor类,代表方位传感器,可以实时报告上表所示的几种特殊方位的值,让我们不得自己计算坐标值了。声明一个SimpleOrientationSensor实例来处理OrientationChanged事件。if(ortsensor==null){ortsensor=SimpleOrientationSensor.GetDefault();}......ortsensor.OrientationChanged+=ortsensor_OrientationChanged;......voidortsensor_OrientationChanged(SimpleOrientationSensorsender,SimpleOrientationSensorOrientationChangedEventArgsargs){//根据旋转捕获图标的方向varo=args.Orientation;System.Diagnostics.Debug.WriteLine("方向:{0}",o);Dispatcher.BeginInvoke(()=>{UpdateOrientation(o);});}在上面的图片编码代码中,通过SimpleOrientationSensor对象的GetCurrentOrientation方法获取手机当前方向,然后在图像应该旋转哪个被确定。switch(ort){caseSimpleOrientation.NotRotated:encoder.BitmapTransform.Rotation=BitmapRotation.Clockwise90Degrees;break;caseSimpleOrientation.Rotated180DegreesCounterclockwise:encoder.BitmapTransform.Rotation=BitmapRotation.Clockwise270Degrees;break;caseSimpleOrientation.Rotated270DegreesCounterclockwise:encoder.BitmapTransform.Rotation=BitmapRotation.Clockwise180Degrees;break;caseSimpleOrientation.Rotated90DegreesCounterclockwise:encoder.BitmapTransform.Rotation=BitmapRotation.None;break;}好了,经过以上步骤,相机旋转的问题就可以解决了