PageRenderTime 54ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/Chapter06/PhotoEditor/MainPage.xaml.cs

https://github.com/timothybinkley/Windows-Phone-7-In-Action
C# | 281 lines | 251 code | 27 blank | 3 comment | 18 complexity | 6ebee3b9ba7bf20b616f24a01e6be15c MD5 | raw file
  1. using System;
  2. using System.Linq;
  3. using System.IO;
  4. using System.IO.IsolatedStorage;
  5. using System.Windows.Media;
  6. using System.Windows.Media.Imaging;
  7. using Microsoft.Phone.Controls;
  8. using Microsoft.Phone.Tasks;
  9. using Microsoft.Devices;
  10. using System.Windows.Navigation;
  11. using Microsoft.Phone;
  12. using ExifLib;
  13. namespace PhotoEditor
  14. {
  15. public partial class MainPage : PhoneApplicationPage
  16. {
  17. private WriteableBitmap currentImage;
  18. private PhotoCamera camera;
  19. // Constructor
  20. public MainPage()
  21. {
  22. InitializeComponent();
  23. }
  24. protected override void OnNavigatedTo(NavigationEventArgs e)
  25. {
  26. if (State.ContainsKey("customCamera"))
  27. {
  28. State.Remove("customCamera");
  29. InitializeCamera();
  30. }
  31. }
  32. protected override void OnNavigatedFrom(NavigationEventArgs e)
  33. {
  34. if (camera != null)
  35. {
  36. CleanUpCamera();
  37. State["customCamera"] = true;
  38. }
  39. }
  40. private void Choose_Click(object sender, EventArgs e)
  41. {
  42. var task = new PhotoChooserTask();
  43. task.ShowCamera = true;
  44. task.Completed += chooserTask_Completed;
  45. task.Show();
  46. }
  47. private void Capture_Click(object sender, EventArgs e)
  48. {
  49. var task = new CameraCaptureTask();
  50. task.Completed += chooserTask_Completed;
  51. task.Show();
  52. }
  53. void chooserTask_Completed(object sender, PhotoResult e)
  54. {
  55. if (e.TaskResult == TaskResult.OK)
  56. {
  57. int angle = GetAngleFromExif(e.ChosenPhoto);
  58. currentImage = DecodeImage(e.ChosenPhoto, angle);
  59. //currentImage = PictureDecoder.DecodeJpeg(e.ChosenPhoto);
  60. photoContainer.Fill = new ImageBrush { ImageSource = currentImage };
  61. imageDetails.Text = string.Format("Image from {0}\n", sender.GetType().Name);
  62. imageDetails.Text += string.Format("Image rotated {0} degrees.\n", angle);
  63. imageDetails.Text += string.Format("Original filename:\n{0}", e.OriginalFileName);
  64. }
  65. else
  66. {
  67. photoContainer.Fill = new SolidColorBrush(Colors.Gray);
  68. imageDetails.Text = e.TaskResult.ToString();
  69. }
  70. }
  71. private void Camera_Click(object sender, EventArgs e)
  72. {
  73. if (camera == null)
  74. {
  75. currentImage = null;
  76. imageDetails.Text = string.Format("Choose custom camera again to close camera. Use the hardware shutter button to take a picture.\n");
  77. InitializeCamera();
  78. }
  79. else
  80. {
  81. CleanUpCamera();
  82. photoContainer.Fill = new SolidColorBrush(Colors.Gray);
  83. imageDetails.Text = "Choose an image source from the menu.";
  84. }
  85. }
  86. void InitializeCamera()
  87. {
  88. camera = new PhotoCamera(CameraType.Primary);
  89. camera.Initialized += camera_Initialized;
  90. camera.CaptureImageAvailable += camera_CaptureImageAvailable;
  91. camera.CaptureCompleted += camera_CaptureCompleted;
  92. CameraButtons.ShutterKeyPressed += cameraButtons_ShutterKeyPressed;
  93. // create and rotate the brush since our orientation does not match the cameras default orientation.
  94. var brush = new VideoBrush();
  95. brush.SetSource(camera);
  96. brush.RelativeTransform = new RotateTransform { CenterX = 0.5, CenterY = 0.5, Angle = camera.Orientation };
  97. photoContainer.Fill = brush;
  98. }
  99. void camera_Initialized(object sender, CameraOperationCompletedEventArgs e)
  100. {
  101. Dispatcher.BeginInvoke(() =>
  102. {
  103. imageDetails.Text += string.Format("{0} supported resolutions.\n", camera.AvailableResolutions.Count());
  104. imageDetails.Text += string.Format("Current resolution: {0}\n", camera.Resolution);
  105. imageDetails.Text += string.Format("Preview resolution: {0}\n", camera.PreviewResolution);
  106. });
  107. camera.Initialized -= camera_Initialized;
  108. }
  109. void CleanUpCamera()
  110. {
  111. CameraButtons.ShutterKeyPressed -= cameraButtons_ShutterKeyPressed;
  112. camera.CaptureImageAvailable -= camera_CaptureImageAvailable;
  113. camera.CaptureCompleted -= camera_CaptureCompleted;
  114. camera.Dispose();
  115. camera = null;
  116. }
  117. private void cameraButtons_ShutterKeyPressed(object sender, EventArgs e)
  118. {
  119. camera.CaptureImage();
  120. }
  121. void camera_CaptureImageAvailable(object sender, ContentReadyEventArgs e)
  122. {
  123. Dispatcher.BeginInvoke(() =>
  124. {
  125. currentImage = DecodeImage(e.ImageStream, (int)camera.Orientation);
  126. photoContainer.Fill = new ImageBrush { ImageSource = currentImage };
  127. imageDetails.Text = "Image captured from PhotoCamera.";
  128. });
  129. }
  130. void camera_CaptureCompleted(object sender, CameraOperationCompletedEventArgs e)
  131. {
  132. if (!e.Succeeded)
  133. {
  134. photoContainer.Fill = new SolidColorBrush(Colors.Gray);
  135. imageDetails.Text = "Camera capture failed.\n" + e.Exception.Message;
  136. }
  137. CleanUpCamera();
  138. }
  139. private void Edit_Click(object sender, EventArgs e)
  140. {
  141. if (currentImage != null)
  142. {
  143. currentImage.Invalidate();
  144. var transform = new CompositeTransform
  145. {
  146. ScaleX = currentImage.PixelWidth / photoContainer.ActualWidth,
  147. ScaleY = currentImage.PixelHeight / photoContainer.ActualHeight,
  148. Rotation = -35,
  149. TranslateX = 100 * currentImage.PixelWidth / photoContainer.ActualWidth,
  150. TranslateY = 250 * currentImage.PixelHeight / photoContainer.ActualHeight,
  151. };
  152. currentImage.Render(photoStamp, transform);
  153. currentImage.Invalidate();
  154. imageDetails.Text = "The picture has been stamped.";
  155. }
  156. }
  157. private void Save_Click(object sender, EventArgs e)
  158. {
  159. if (currentImage != null)
  160. {
  161. using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
  162. {
  163. using (IsolatedStorageFileStream stream = storage.CreateFile(@"customphoto.jpg"))
  164. {
  165. currentImage.SaveJpeg(stream, currentImage.PixelWidth, currentImage.PixelHeight, 0, 100);
  166. }
  167. }
  168. imageDetails.Text = string.Format("Image saved with filename:\ncustomphoto.jpg");
  169. }
  170. }
  171. private void Open_Click(object sender, EventArgs e)
  172. {
  173. using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
  174. {
  175. if (storage.FileExists(@"customphoto.jpg"))
  176. {
  177. using (IsolatedStorageFileStream stream =
  178. storage.OpenFile(@"customphoto.jpg", FileMode.Open))
  179. {
  180. currentImage = PictureDecoder.DecodeJpeg(stream);
  181. photoContainer.Fill = new ImageBrush { ImageSource = currentImage };
  182. }
  183. imageDetails.Text = string.Format("Image loaded from filename:\ncustomphoto.jpg");
  184. }
  185. else
  186. {
  187. photoContainer.Fill = new SolidColorBrush(Colors.Gray);
  188. imageDetails.Text = "Image not found!";
  189. }
  190. }
  191. }
  192. private WriteableBitmap DecodeImage(Stream imageStream, int angle)
  193. {
  194. WriteableBitmap source = PictureDecoder.DecodeJpeg(imageStream);
  195. switch (angle)
  196. {
  197. case 90:
  198. case 270:
  199. return RotateBitmap(source, source.PixelHeight, source.PixelWidth, angle);
  200. case 180:
  201. return RotateBitmap(source, source.PixelWidth, source.PixelHeight, angle);
  202. default:
  203. return source;
  204. }
  205. }
  206. private int GetAngleFromExif(Stream imageStream)
  207. {
  208. var position = imageStream.Position;
  209. imageStream.Position = 0;
  210. var orientation = ExifReader.ReadJpeg(imageStream, String.Empty).Orientation;
  211. imageStream.Position = position;
  212. switch (orientation)
  213. {
  214. case ExifOrientation.TopRight:
  215. return 90;
  216. case ExifOrientation.BottomRight:
  217. return 180;
  218. case ExifOrientation.BottomLeft:
  219. return 270;
  220. case ExifOrientation.TopLeft:
  221. case ExifOrientation.Undefined:
  222. default:
  223. return 0;
  224. }
  225. }
  226. private WriteableBitmap RotateBitmap(WriteableBitmap source, int width, int height, int angle)
  227. {
  228. var target = new WriteableBitmap(width, height);
  229. int sourceIndex = 0;
  230. int targetIndex = 0;
  231. for (int x = 0; x < source.PixelWidth; x++)
  232. {
  233. for (int y = 0; y < source.PixelHeight; y++)
  234. {
  235. sourceIndex = x + y * source.PixelWidth;
  236. switch (angle)
  237. {
  238. case 90:
  239. targetIndex = (source.PixelHeight - y - 1) + x * target.PixelWidth;
  240. break;
  241. case 180:
  242. targetIndex = (source.PixelWidth - x - 1) + (source.PixelHeight - y - 1) * source.PixelWidth;
  243. break;
  244. case 270:
  245. targetIndex = y + (source.PixelWidth - x - 1) * target.PixelWidth;
  246. break;
  247. }
  248. target.Pixels[targetIndex] = source.Pixels[sourceIndex];
  249. }
  250. }
  251. return target;
  252. }
  253. }
  254. }