zoukankan      html  css  js  c++  java
  • 【WP 8.1开发】如何处理摄像头翻转的问题

    模拟器就像我们儿时的梦境,在其上运行应用程序时,一切总是那么美好的;而真机测试如同我们这个纷乱无章的现实世界,你会遇到各种小人和畜生,常常会遭受莫名的挫折。面对挫折,有人迎难而上,或不予理采,走自己的路;有的人则打退堂鼓。

    面对摄像头翻转的问题,有些人也会选择逃避。我为什么不喜欢现在的某些程序员,就是因为这些人只会逃避和制造问题,遇到问题不是去寻找解决方案,而是坐在那里喊爹骂娘。虽然不可能所有问题都可以解决,但是,有许多问题是可以解决的,而这些人总心浮气躁,不愿意静下心来好好思考。

    N+6年前我曾经读过一本好书,名叫《方法总比问题多》,捧着这个心念,我认为摄像头翻转的问题是可以解决的。

    通常,我们很少会调用前置摄像头,多数情况下用到的是后置摄像头。当然了,解决方法是类似的,因此,为了简单易懂,本文我就以后置摄像头为例,分享一下我的解决方案,如果你有更好的方法,也不妨让大伙儿一起参考参考。

    一般而言,真机上的摄像头是与手机横放时的角度一致,即偏了90度(手机逆时针旋转)。

    也就是说,当手机逆时针旋转90度后,机器的方向就与摄像头一致了。针对这一情况,我们只要能做到一件事,那就可以解决摄像头翻转的问题了。

    锁定页面的方向,即当手机方向改变时,禁止页面跟着旋转就可以了。

    此处以Silverlight框架为例,Runtime App比较好办,直接在清单文件中把屏幕方向强制为横向即可。但Silverlight程序就需要一些步骤。

    1、设置页面的SupportedOrientations="Landscape",Orientation="LandscapeLeft",如下面XAML所示。

    <phone:PhoneApplicationPage
        x:Class="AppCamera.MainPage"
        ……
        SupportedOrientations="Landscape" Orientation="LandscapeLeft"
        shell:SystemTray.IsVisible="False">
    ……

    这样做就把页面所支持的方向限制为横向,页面的默认方向也改为LandscapeLeft,即手机逆时针旋转90,如果是LandscapeRight,v那就是手机逆时针旋转270度。

    2、光是把页面强制为横向还不行,因为横向有两个方向——90度和270度,当手机转动90度后,其方向正好与摄像头吻合,但是,一旦手机旋转270度后,就正好与摄像头的方向相反,即转了180度,这时候,你在手机屏幕上看到的摄像预览是倒过来的,而拍出来的照片当然也是倒立的,关于保存照片的问题,稍后再说。

    因此,我们必须想办法,阻止页面更改方向,正好,页面类有一个虚方法叫OnOrientationChanged,当页面的方向发生改变后,会调用该方法。我们只要重写这个方法,并且不要加入任何代码,就能阻止页面基类调用该方法,也就达到了阻止页面改变方向了,“搜狐拍客”就是用这种方法来解决翻转问题的。

            protected override void OnOrientationChanged ( OrientationChangedEventArgs e )
            {
                // 把下面的代码注释掉,页面的方向就会锁定
                //base.OnOrientationChanged(e);
            }

    注意。base.OnOrientationChanged(e);这行代码必须去掉,不然基类会调用

    3、通过上述步骤,是解决了摄像头预览翻转的问题,但又引出另一个新问题:如果屏幕方向与摄像头的方向不一致,那么拍照出来的照片也会反过来的。这个问题就必须在图像文件上做功夫了,也就是把图像的方向调整过来再保存。

    我的示例是使用MediaCapture类来拍摄的,拍到的图片是直接保存到文件或流中了,那我们如何修改图片呢?

    在Windows.Graphics.Imaging命名空间下,BitmapDecoder类可以用来对图像进行解码,并可以提取图像的像素数据;BitmapEncoder类可以对图像的像素数据进行编码为图像文件。

    对,我们就是利用这两个类,先将摄像头拍到的照片解码,然后利用旋转变换来修改图像的方向,最后将修改后的图像重新编码就可以了。至于要把图像向哪个方向旋转,大家不妨自己试一试,对比一下就能知道了。

    以下是参考代码:

            #region 图像解码与编码
    
            async Task EncodeImage ( IRandomAccessStream inStream, IRandomAccessStream outStream )
            {
                Guid jpegIDen = BitmapEncoder.JpegEncoderId; //编码器ID
                Guid jpegIDde = BitmapDecoder.JpegDecoderId; //获取解码器ID
                BitmapDecoder decoder = await BitmapDecoder.CreateAsync(jpegIDde, inStream);
    
                byte[] buffer= ( await decoder.GetPixelDataAsync()).DetachPixelData();
    
                BitmapEncoder encoder = await BitmapEncoder.CreateAsync(jpegIDen, outStream);
                // 判断手机方向,以改变图像方向
                var ort = ortsensor.GetCurrentOrientation();
                switch (ort)
                {
                    case SimpleOrientation.NotRotated:
                        encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees;
                        break;
                    case SimpleOrientation.Rotated180DegreesCounterclockwise:
                        encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise270Degrees;
                        break;
                    case SimpleOrientation.Rotated270DegreesCounterclockwise:
                        encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise180Degrees;
                        break;
                    case SimpleOrientation.Rotated90DegreesCounterclockwise:
                        encoder.BitmapTransform.Rotation = BitmapRotation.None;
                        break;
                }
                // 设置像素数据
                encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, decoder.PixelWidth, decoder.PixelHeight, decoder.DpiX, decoder.DpiY, buffer);
                await encoder.FlushAsync();
            }
            #endregion


    由于在确认图像旋转方向前,我们必须知道手机的当前方向。比较简单的方法是直接访问Windows.Graphics.Display.DisplayProperties类的CurrentOrientation属性,不过这个类在新版本中可能会被删除,所以我就不用这个方法。我于是选用了一个稍稍复杂点的方法——使用方向传感器。这种方法有点装逼,不过正好我们可以发挥一下传感器的用处,其实屏幕方向也是通过方向(重力)传感器来识别的。

    为了让开发者可以轻松识别出手机的几个特殊方向,以SimpleOrientation枚举定义了几个比较通用的方向。这些值的含义如下表所示。

    对应地,在Windows.Devices.Sensors命名空间下,有一个SimpleOrientationSensor类,它表示方向传感器,它可以提供上表所示的几个特殊方向的值的实时报告,这样我们就不用自己来计算坐标值了。

    声明SimpleOrientationSensor实例,处理OrientationChanged事件。

                if (ortsensor == null)
                {
                    ortsensor = SimpleOrientationSensor.GetDefault();
                }
         ……
    ortsensor.OrientationChanged += ortsensor_OrientationChanged;
    
    ..............
    
            void ortsensor_OrientationChanged ( SimpleOrientationSensor sender, SimpleOrientationSensorOrientationChangedEventArgs args )
            {
                // 根据方向旋转拍摄图标
                var o = args.Orientation;
                System.Diagnostics.Debug.WriteLine("方向:{0}", o);
                Dispatcher.BeginInvoke(() =>
                    {
                        UpdateOrientation(o);
                    });
            }

    在上面对图像进行编码的代码中,是通过SimpleOrientationSensor对象的GetCurrentOrientation方法来获取手机当前所处的方向,进而判断出图像应该旋转的方向。

                switch (ort)
                {
                    case SimpleOrientation.NotRotated:
                        encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees;
                        break;
                    case SimpleOrientation.Rotated180DegreesCounterclockwise:
                        encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise270Degrees;
                        break;
                    case SimpleOrientation.Rotated270DegreesCounterclockwise:
                        encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise180Degrees;
                        break;
                    case SimpleOrientation.Rotated90DegreesCounterclockwise:
                        encoder.BitmapTransform.Rotation = BitmapRotation.None;
                        break;
                }


    好了,经过以上几个步骤,摄像头翻转的问题可以得到解决了。

    下面是示例下载地址,和上一篇文章中的示例一样,我只是做了一些修改。

    http://files.cnblogs.com/tcjiaan/AppCamera.zip

  • 相关阅读:
    函数式宏定义与普通函数
    linux之sort用法
    HDU 4390 Number Sequence 容斥原理
    HDU 4407 Sum 容斥原理
    HDU 4059 The Boss on Mars 容斥原理
    UVA12653 Buses
    UVA 12651 Triangles
    UVA 10892
    HDU 4292 Food
    HDU 4288 Coder
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/3944948.html
Copyright © 2011-2022 走看看