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/ 

 

 

 

 

 

 

 

 

 

posted @ 2012-04-05 22:48  acles  阅读(1419)  评论(0编辑  收藏  举报