zoukankan      html  css  js  c++  java
  • Windows Phone 拍照照片方向不对的问题

    清明小长假完全的在睡梦中度过,看看了两部迅雷下载的电影,稍微搞了搞假前没搞完的应用。节后第一天啥也不相干,不想看书,不想写代码,懒惰之极啊。于是想到开发最近这个应用的时候,遇到的一个问题,网上查了资料,总结了一下,以下是从老外那个文章中总结来的,并非原创。

    使用CameraCaptureTask调用相机拍照的时候,wp会有一个奇怪的现象,那就是不管你拍照的时候你的手机是“portrait”还是“landscape”,它都自认为你使用了“landscape”,所以拍出来的照片,当你使用Image预览的时候,就会感觉方向不对。

     

    手机有四种旋转方向,拍出来的照片的方向都不一样啊,下面借一张另一个老外的图,大家好好看看。


    解释一下啊。

    第一栏就是你的应用的方向,这个和拍照没什么关系。

    第二栏是你拍照时候手机拿的方向,到底怎么拿的你看看你手机就知道了。

    第三栏是拍照后照片在你应用中的现实方向。

    第四栏是需要调整的角度。

    看了以上大家应该明白了,至于你信不信,反正我是信了。

     

    以上是铺垫,下面开始讲解怎么修正以上的问题。

     

    要修正方向不对的问题,就需要知道拍照后照片的方向。要知道照片的方向,就要使用到另一个老外的一个类库ExifLib.这个类库大家一看就知道是获取图片的exif信息的。那个老外开放了源代码,有兴趣大家可以去下载看看。使用这个类库就可以获得拍照的照片的一些信息,当然要包含方向信息了。

    使用CameraCaptureTask之后,Complete之后返回的e.ChosePhoto是一个Stream,由于ExifLib中没有直接操作Stream的方法,所以还需要您劳驾加一个直接操作Stream的方法,方法如下:

    1: public static JpegInfo ReadJpeg(Stream FileStream, string FileName)

       2: {

       3:     DateTime now = DateTime.Now;

       4:     ExifReader reader = new ExifReader(FileStream);

       5:     reader.info.FileSize = (int)FileStream.Length;

       6:     reader.info.FileName = string.Format("{0}.jpg", FileName);

       7:     reader.info.LoadTime = (TimeSpan)(DateTime.Now - now);

       8:     return reader.info;

       9: }

    最后,提供给你的代码中的新的ExifLib已经加了这个方法了,所以也可以直接使用那个库。

     

    这个库改完之后,就要进入纠正方向的正题了。

    纠正方向还有两种方法,其实也是两种不同的需求。

    1、如果只是为了预览照片,完全可以使用Image的那个RenderTransform属性修改旋转度,代码应该是这样的吧:

    1: <Image Margin="8,8,8,159" x:Name="ChosenPicture" RenderTransformOrigin="0.5,0.5">

       2:     <Image.RenderTransform>

       3:         <RotateTransform x:Name="ImageRotate" />

       4:     </Image.RenderTransform>

       5: </Image>

    然后在后台中判断照片的需要旋转度。后台代码如下:

    void OnCameraCaptureCompleted(object sender, PhotoResult e)

       2: {

       3:     capturedImage = e.ChosenPhoto;

       4: 

       5:     BitmapImage bmp = new BitmapImage();

       6:     bmp.SetSource(e.ChosenPhoto);

       7: 

       8:     ChosenPicture.Source = bmp;

       9: 

      10:     // figure out the orientation from EXIF data

      11:     e.ChosenPhoto.Position = 0;

      12:     JpegInfo info = ExifReader.ReadJpeg(e.ChosenPhoto, e.OriginalFileName);

      13:

      14: 

      15:     switch (info.Orientation)

      16:     {

      17:         case ExifOrientation.TopLeft:

      18:         case ExifOrientation.Undefined:

      19:             ImageRotate.Angle = 0d;

      20:             break;

      21:         case ExifOrientation.TopRight:

      22:             ImageRotate.Angle = 90d;

      23:             break;

      24:         case ExifOrientation.BottomRight:

      25:             ImageRotate.Angle = 180d;

      26:             break;

      27:         case ExifOrientation.BottomLeft:

      28:             ImageRotate.Angle = 270d;

      29:             break;

      30:     }

      31: }

    这段代码大家可以结合着上面那个有四个栏的图看,就好理解了。这样操作之后,预览的时候,正常方向拿手机的时候,照片就都是正方向的了。

     

    但是上面的解决方案只能够解决预览的时候方向不对的问题,如果你想把照片保存起来,最后保存的照片的方向还是不对,所以以上方案只是治标并没有治本,那下面就讨论一下治本的方案。

    如果要治本,那就要重新构造图片,怎么重新构造呢,看下面的代码吧,我也懒的写太多了,大家好好看看吧,有些代码真真是没看懂,有懂的可以给解释一下。

    void OnCameraCaptureCompleted(object sender, PhotoResult e)

       2: {

       3:     // figure out the orientation from EXIF data

       4:     e.ChosenPhoto.Position = 0;

       5:     JpegInfo info = ExifReader.ReadJpeg(e.ChosenPhoto, e.OriginalFileName);

       6: 

       7:     _width = info.Width;

       8:     _height = info.Height;

       9:     _orientation = info.Orientation;

      10: 

      11:     PostedUri.Text = info.Orientation.ToString();

      12: 

      13:     switch (info.Orientation)

      14:     {

      15:         case ExifOrientation.TopLeft:

      16:         case ExifOrientation.Undefined:

      17:             _angle = 0;

      18:             break;

      19:         case ExifOrientation.TopRight:

      20:             _angle = 90;

      21:             break;

      22:         case ExifOrientation.BottomRight:

      23:             _angle = 180;

      24:             break;

      25:         case ExifOrientation.BottomLeft:

      26:             _angle = 270;

      27:             break;

      28:     }

      29: 

      30:     if (_angle > 0d)

      31:     {

      32:         capturedImage = RotateStream(e.ChosenPhoto, _angle);

      33:     }

      34:     else

      35:     {

      36:         capturedImage = e.ChosenPhoto;

      37:     }

      38: 

      39:     BitmapImage bmp = new BitmapImage();

      40:     bmp.SetSource(capturedImage);

      41: 

      42:     ChosenPicture.Source = bmp;          

      43: }

      44: 

      45: private Stream RotateStream(Stream stream, int angle)

      46: {

      47:     stream.Position = 0;

      48:     if (angle % 90 != 0 || angle < 0) throw new ArgumentException();

      49:     if (angle % 360 == 0) return stream;

      50: 

      51:     BitmapImage bitmap = new BitmapImage();

      52:     bitmap.SetSource(stream);

      53:     WriteableBitmap wbSource = new WriteableBitmap(bitmap);

      54: 

      55:     WriteableBitmap wbTarget = null;

      56:     if (angle % 180 == 0)

      57:     {

      58:         wbTarget = new WriteableBitmap(wbSource.PixelWidth, wbSource.PixelHeight);

      59:     }

      60:     else

      61:     {

      62:         wbTarget = new WriteableBitmap(wbSource.PixelHeight, wbSource.PixelWidth);

      63:     }

      64:  // 循环体内的代码真真的没看懂啊,有懂的可以解释一下啊。

      65:     for (int x = 0; x < wbSource.PixelWidth; x++)

      66:     {

      67:         for (int y = 0; y < wbSource.PixelHeight; y++)

      68:         {

      69:             switch (angle % 360)

      70:             {

      71:                 case 90:

      72:                     wbTarget.Pixels[(wbSource.PixelHeight - y - 1) + x * wbTarget.PixelWidth] = wbSource.Pixels[x + y * wbSource.PixelWidth];

      73:                     break;

      74:                 case 180:

      75:                     wbTarget.Pixels[(wbSource.PixelWidth - x - 1) + (wbSource.PixelHeight - y - 1) * wbSource.PixelWidth] = wbSource.Pixels[x + y * wbSource.PixelWidth];

      76:                     break;

      77:                 case 270:

      78:                     wbTarget.Pixels[y + (wbSource.PixelWidth - x - 1) * wbTarget.PixelWidth] = wbSource.Pixels[x + y * wbSource.PixelWidth];

      79:                     break;

      80:             }

      81:         }

      82:     }

      83:     MemoryStream targetStream = new MemoryStream();

      84:     wbTarget.SaveJpeg(targetStream, wbTarget.PixelWidth, wbTarget.PixelHeight, 0, 100);

      85:     return targetStream;

      86: }

    这就是重新构造一个正确方向的图片的方法,以上代码是直接从老外的文章中贴过来的,文章最后,我会提供我精炼出的代码,大家可以直接拿过去用。

     

    好了,就写这么多吧,文笔太差,大家尽量看吧,看不懂,可以一起讨论一下。哈哈。

     

    以下提供我总结的以上方法的代码,放在一个实例应用中了,大家可以根据需要修改或者不修改使用,哈哈。

    实例代码下载》》》 

     参考文章:

    Handling picture orientation in CameraCaptureTask in Windows Phone 7

    http://www.mindscapehq.com/blog/index.php/2012/02/28/windows-phone-7-working-with-camera-tasks/ 

  • 相关阅读:
    apache安全—用户访问控制
    hdu 3232 Crossing Rivers 过河(数学期望)
    HDU 5418 Victor and World (可重复走的TSP问题,状压dp)
    UVA 11020 Efficient Solutions (BST,Splay树)
    UVA 11922 Permutation Transformer (Splay树)
    HYSBZ 1208 宠物收养所 (Splay树)
    HYSBZ 1503 郁闷的出纳员 (Splay树)
    HDU 5416 CRB and Tree (技巧)
    HDU 5414 CRB and String (字符串,模拟)
    HDU 5410 CRB and His Birthday (01背包,完全背包,混合)
  • 原文地址:https://www.cnblogs.com/acles/p/2433883.html
Copyright © 2011-2022 走看看