裁剪图片主要是借助于 BitmapDecoder.GetPixelDataAsync() 以及 BitmapTransform对象来实现。
实现的代码如下:
1 using System; 2 using System.Threading.Tasks; 3 using Windows.Storage.Streams; 4 using Windows.Foundation; 5 using Windows.Graphics.Imaging; 6 7 namespace ScanQRCode 8 { 9 public static class ImageHelper 10 { 11 /// <summary> 12 /// Asynchronously get the cropped stream. 13 /// </summary> 14 /// <param name="inputStream">The input stream</param> 15 /// <param name="rect"></param> 16 /// <returns></returns> 17 public static async Task<IRandomAccessStream> GetCroppedStreamAsync(IRandomAccessStream inputStream, Rect rect) 18 { 19 if (inputStream == null) 20 return null; 21 22 var startPointX = (uint)Math.Floor(rect.X); 23 var startPointY = (uint)Math.Floor(rect.Y); 24 var width = (uint)Math.Floor(rect.Width); 25 var height = (uint)Math.Floor(rect.Height); 26 27 return await GetCroppedStreamAsync(inputStream, startPointX, startPointY, width, height); 28 } 29 30 /// <summary> 31 /// Asynchronously get the cropped stream. 32 /// </summary> 33 /// <param name="inputStream">The input stream</param> 34 /// <param name="x"></param> 35 /// <param name="y"></param> 36 /// <param name="width"></param> 37 /// <param name="height"></param> 38 /// <returns></returns> 39 public static async Task<IRandomAccessStream> GetCroppedStreamAsync(IRandomAccessStream inputStream, uint x, uint y, uint width, uint height) 40 { 41 if (inputStream == null) 42 return null; 43 44 var pixelData = await GetCroppedPixelDataAsync(inputStream, x, y, width, height); 45 if (pixelData == null) 46 return null; 47 48 var outputStream = new InMemoryRandomAccessStream(); 49 var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, outputStream); 50 encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, width, height, 72, 72, pixelData); 51 await encoder.FlushAsync(); 52 53 return outputStream; 54 } 55 56 /// <summary> 57 /// Asynchronously get the cropped pixel data. 58 /// </summary> 59 /// <param name="inputStream">The input stream</param> 60 /// <param name="rect"></param> 61 /// <returns></returns> 62 public static async Task<byte[]> GetCroppedPixelDataAsync(IRandomAccessStream inputStream, Rect rect) 63 { 64 if (inputStream == null) 65 return null; 66 67 var startPointX = (uint)Math.Floor(rect.X); 68 var startPointY = (uint)Math.Floor(rect.Y); 69 var width = (uint)Math.Floor(rect.Width); 70 var height = (uint)Math.Floor(rect.Height); 71 72 return await GetCroppedPixelDataAsync(inputStream, startPointX, startPointY, width, height); 73 } 74 75 /// <summary> 76 /// Asynchronously get the cropped pixel data. 77 /// </summary> 78 /// <param name="inputStream">The input stream</param> 79 /// <param name="x"></param> 80 /// <param name="y"></param> 81 /// <param name="width"></param> 82 /// <param name="height"></param> 83 /// <returns></returns> 84 public static async Task<byte[]> GetCroppedPixelDataAsync(IRandomAccessStream inputStream, uint x, uint y, uint width, uint height) 85 { 86 if (inputStream == null) 87 return null; 88 89 var decoder = await BitmapDecoder.CreateAsync(inputStream); 90 91 // Refine the start point 92 if (x + width > decoder.PixelWidth) 93 x = decoder.PixelWidth - width; 94 if (y + height > decoder.PixelHeight) 95 y = decoder.PixelHeight - height; 96 97 var transform = new BitmapTransform() 98 { 99 Bounds = new BitmapBounds 100 { 101 X = x, 102 Y = y, 103 Width = width, 104 Height = height 105 }, 106 InterpolationMode = BitmapInterpolationMode.Fant, 107 ScaledWidth = decoder.PixelWidth, 108 ScaledHeight = decoder.PixelHeight 109 }; 110 111 var pixelProvider = await decoder.GetPixelDataAsync(decoder.BitmapPixelFormat, decoder.BitmapAlphaMode, transform, 112 ExifOrientationMode.RespectExifOrientation, ColorManagementMode.ColorManageToSRgb); 113 114 115 return pixelProvider.DetachPixelData(); 116 } 117 } 118 }