您的位置:首页 > 其它

Windows Phone 拍照照片方向不对的问题

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

使用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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: