/// <summary> /// Use BitmapTransform to define the region to crop, and then get the pixel data in the region. /// If you want to get the pixel data of a scaled image, set the scaledWidth and scaledHeight /// of the scaled image. /// </summary> /// <returns></returns> async static private Task<byte[]> GetPixelData(BitmapDecoder decoder, uint startPointX, uint startPointY, uint width, uint height, uint scaledWidth, uint scaledHeight) { BitmapTransform transform = new BitmapTransform(); BitmapBounds bounds = new BitmapBounds(); bounds.X = startPointX; bounds.Y = startPointY; bounds.Height = height; bounds.Width = width; transform.Bounds = bounds; transform.ScaledWidth = scaledWidth; transform.ScaledHeight = scaledHeight; // Get the cropped pixels within the bounds of transform. PixelDataProvider pix = await decoder.GetPixelDataAsync( BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, transform, ExifOrientationMode.IgnoreExifOrientation, ColorManagementMode.ColorManageToSRgb); byte[] pixels = pix.DetachPixelData(); return pixels; }
internal static async Task LoadTileImageInternalAsync(string imagePath) { string tileName = "dreaming"; uint MaxImageWidth =360; uint MaxImageHeight = 600; StorageFile origFile = await ApplicationData.Current.LocalFolder.GetFileAsync(imagePath); // open file for the new tile image file StorageFile tileFile = await Windows.Storage.KnownFolders.PicturesLibrary.CreateFileAsync(tileName, CreationCollisionOption.GenerateUniqueName); using (IRandomAccessStream tileStream = await tileFile.OpenAsync(FileAccessMode.ReadWrite)) { // get width and height from the original image IRandomAccessStreamWithContentType stream = await origFile.OpenReadAsync(); ImageProperties properties = await origFile.Properties.GetImagePropertiesAsync(); uint width = properties.Width; uint height = properties.Height; // get proper decoder for the input file - jpg/png/gif BitmapDecoder decoder = await GetProperDecoder(stream, origFile ); if (decoder == null) return; // should not happen // get byte array of actual decoded image PixelDataProvider data = await decoder.GetPixelDataAsync(); byte[] bytes = data.DetachPixelData(); // create encoder for saving the tile image BitmapPropertySet propertySet = new BitmapPropertySet(); // create class representing target jpeg quality - a bit obscure, but it works BitmapTypedValue qualityValue = new BitmapTypedValue(0.5, PropertyType.Single); propertySet.Add("ImageQuality", qualityValue); // create the target jpeg decoder BitmapEncoder be = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, tileStream, propertySet); be.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, width, height, 96.0, 96.0, bytes); // crop the image, if it's too big if (width > MaxImageWidth || height > MaxImageHeight) { BitmapBounds bounds = new BitmapBounds(); if (width > MaxImageWidth) { bounds.Width = MaxImageWidth; bounds.X = (width - MaxImageWidth) / 2; } else bounds.Width = width; if (height > MaxImageHeight) { bounds.Height = MaxImageHeight; bounds.Y = (height - MaxImageHeight) / 2; } else bounds.Height = height; be.BitmapTransform.Bounds = bounds; } // save the target jpg to the file await be.FlushAsync(); } }
public static async Task<byte[]> CropImage(byte[] stream, Crop crop) { byte[] byteArray = null; var imageStream = new MemoryStream(stream); var fileStream = imageStream.AsRandomAccessStream(); BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream); InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream(); BitmapEncoder enc = await BitmapEncoder.CreateForTranscodingAsync(ras, decoder); BitmapBounds bounds = new BitmapBounds(); bounds.Height = (uint)crop.Height; bounds.Width = (uint)crop.Width; bounds.X = (uint)crop.X; bounds.Y = (uint)crop.Y; enc.BitmapTransform.Bounds = bounds; enc.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Linear; enc.IsThumbnailGenerated = false; try { await enc.FlushAsync(); } catch (Exception ex) { Debug.WriteLine("Error croping image", ex); } byteArray = new byte[ras.Size]; DataReader dataReader = new DataReader(ras.GetInputStreamAt(0)); await dataReader.LoadAsync((uint)ras.Size); dataReader.ReadBytes(byteArray); return byteArray; }
/// <summary> /// Helper to get the correct Bounds for 15:9 screens and to set finalPhotoAreaBorder values /// </summary> /// <returns></returns> private BitmapBounds GetFifteenByNineBounds() { var bounds = new BitmapBounds(); //image size is raw pixels, so we need also here raw pixels var logicalPixelWidth = Window.Current.Bounds.Width; var logicalPixelHeight = Window.Current.Bounds.Height; var rawPerViewPixels = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel; var rawPixelHeight = logicalPixelHeight*rawPerViewPixels; var rawPixelWidth = logicalPixelWidth*rawPerViewPixels; //calculate scale factor of UniformToFill Height (remember, we rotated the preview) var scaleFactorVisualHeight = maxResolution().Width/rawPixelHeight; //calculate the visual Width //(because UniFormToFill scaled the previewElement Width down to match the previewElement Height) var visualWidth = maxResolution().Height/scaleFactorVisualHeight; //calculate cropping area for 15:9 var scaledBoundsWidth = maxResolution().Height; var scaledBoundsHeight = (scaledBoundsWidth/9)*15; //we are starting at the top of the image bounds.Y = 0; //cropping the image width bounds.X = 0; bounds.Height = scaledBoundsHeight; bounds.Width = scaledBoundsWidth; //set finalPhotoAreaBorder values that shows the user the area that is captured //finalPhotoAreaBorder.Width = (scaledBoundsWidth / scaleFactorVisualHeight) / rawPerViewPixels; //finalPhotoAreaBorder.Height = (scaledBoundsHeight / scaleFactorVisualHeight) / rawPerViewPixels; //finalPhotoAreaBorder.Margin = new Thickness( // Math.Floor(((rawPixelWidth - visualWidth) / 2) / rawPerViewPixels), // 0, // Math.Floor(((rawPixelWidth - visualWidth) / 2) / rawPerViewPixels), // 0); //finalPhotoAreaBorder.Visibility = Visibility.Visible; return bounds; }
private static async Task<StorageFile> GenerateResizedImageAsync(StorageFile inputFile, uint width, uint height, uint edgePadding = 5, uint bottomPadding = 20, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting) { try { string fileName = inputFile.DisplayName + width + "x" + height; string extension = inputFile.Name.Substring(inputFile.Name.LastIndexOf('.')); string folder = inputFile.Path.Substring(0, inputFile.Path.LastIndexOf('\\')); var outputFolder = await StorageFolder.GetFolderFromPathAsync(folder); var newFile = await outputFolder.CreateFileAsync(fileName + extension, CreationCollisionOption.ReplaceExisting); var inputStream = await inputFile.OpenAsync(Windows.Storage.FileAccessMode.Read); var outputStream = await newFile.OpenTransactedWriteAsync(); var inMemStream = new InMemoryRandomAccessStream(); var decoder = await BitmapDecoder.CreateAsync(inputStream); var encoder = await BitmapEncoder.CreateForTranscodingAsync(inMemStream, decoder); // Find aspect ratio for resize float nPercentW = (((float)width - (edgePadding * 2)) / (float)decoder.PixelWidth); float nPercentH = (((float)height - (edgePadding * 2)) / (float)decoder.PixelHeight); float nPercent = nPercentH < nPercentW ? nPercentH : nPercentW; // Scale height and width if (nPercent < 1) { encoder.BitmapTransform.ScaledHeight = (uint)(decoder.PixelHeight * nPercent); encoder.BitmapTransform.ScaledWidth = (uint)(decoder.PixelWidth * nPercent); } // Image may still exceed intended bounds, resize as appropriate if (encoder.BitmapTransform.ScaledWidth > width || encoder.BitmapTransform.ScaledHeight > height) { BitmapBounds bounds = new BitmapBounds(); if (encoder.BitmapTransform.ScaledWidth > width) { bounds.Width = width; bounds.X = (encoder.BitmapTransform.ScaledWidth - width) / 2; } else bounds.Width = encoder.BitmapTransform.ScaledWidth; if (encoder.BitmapTransform.ScaledHeight > height) { bounds.Height = height; bounds.Y = (encoder.BitmapTransform.ScaledHeight - height) / 2; } else bounds.Height = encoder.BitmapTransform.ScaledHeight; encoder.BitmapTransform.Bounds = bounds; } await encoder.FlushAsync(); var outDecoder = await BitmapDecoder.CreateAsync(inMemStream); var outEncoder = await BitmapEncoder.CreateForTranscodingAsync(outputStream.Stream, outDecoder); var transparentBytes = GenerateTransparentBitmap(width, height); PixelDataProvider data = await outDecoder.GetPixelDataAsync(); uint heightOffset = (height - outDecoder.PixelHeight) / 2 - bottomPadding; uint widthOffset = (width - outDecoder.PixelWidth) / 2; byte[] bytes = MergePixelArrays(transparentBytes, width, height, data.DetachPixelData(), outDecoder.PixelWidth, outDecoder.PixelHeight, widthOffset, heightOffset); outEncoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, width, height, 72.0, 72.0, bytes); await outEncoder.FlushAsync(); return newFile; } catch (Exception) { } return null; }
async public void SaveAndCropCover(StorageFile originalImgFile) { using (IRandomAccessStream stream = await originalImgFile.OpenReadAsync()) { // Create a decoder from the stream. With the decoder, we can get // the properties of the image. BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream); var shortSide = Math.Min(decoder.PixelWidth, decoder.PixelHeight); double scale = Math.Min(1, shortSide / 480); Size corpSize = new Size(shortSide, shortSide); Point startPoint = new Point((decoder.PixelWidth - shortSide) / 2, (decoder.PixelHeight - shortSide) / 2); // Source: https://code.msdn.microsoft.com/windowsapps/CSWin8AppCropBitmap-52fa1ad7 if (double.IsNaN(scale) || double.IsInfinity(scale)) { scale = 1; } // Convert start point and size to integer. uint startPointX = (uint)Math.Floor(startPoint.X * scale); uint startPointY = (uint)Math.Floor(startPoint.Y * scale); uint height = (uint)Math.Floor(corpSize.Height * scale); uint width = (uint)Math.Floor(corpSize.Width * scale); // The scaledSize of original image. uint scaledWidth = (uint)Math.Floor(decoder.PixelWidth * scale); uint scaledHeight = (uint)Math.Floor(decoder.PixelHeight * scale); // Refine the start point and the size. if (startPointX + width > scaledWidth) { startPointX = scaledWidth - width; } if (startPointY + height > scaledHeight) { startPointY = scaledHeight - height; } // Create cropping BitmapTransform and define the bounds. BitmapTransform transform = new BitmapTransform(); BitmapBounds bounds = new BitmapBounds(); bounds.X = startPointX; bounds.Y = startPointY; bounds.Height = height; bounds.Width = width; transform.Bounds = bounds; transform.ScaledWidth = scaledWidth; transform.ScaledHeight = scaledHeight; // Get the cropped pixels within the bounds of transform. PixelDataProvider pix = await decoder.GetPixelDataAsync( BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, transform, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.ColorManageToSRgb); byte[] pixels = pix.DetachPixelData(); // Stream the bytes into a WriteableBitmap WriteableBitmap cropBmp = new WriteableBitmap((int)width, (int)height); Stream pixStream = cropBmp.PixelBuffer.AsStream(); pixStream.Write(pixels, 0, (int)(width * height * 4)); this.SaveCover(cropBmp); } }
private async void BitmapTransform(string filePath) { var client = new HttpClient(); var stream = await client.GetStreamAsync(filePath); var memStream = new MemoryStream(); await stream.CopyToAsync(memStream); memStream.Position = 0; var decoder = await BitmapDecoder.CreateAsync(memStream.AsRandomAccessStream()); var ras = new InMemoryRandomAccessStream(); var enc = await BitmapEncoder.CreateForTranscodingAsync(ras, decoder); var frame = await decoder.GetFrameAsync(0); enc.BitmapTransform.ScaledHeight = frame.PixelHeight; enc.BitmapTransform.ScaledWidth = frame.PixelWidth; var bounds = new BitmapBounds { Height = 80, Width = frame.PixelWidth, X = 0, Y = 0 }; enc.BitmapTransform.Bounds = bounds; try { await enc.FlushAsync(); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } var bImg = BitmapFactory.New((int) frame.PixelWidth, (int) frame.PixelHeight); using (bImg.GetBitmapContext()) { bImg = await BitmapFactory.New((int) frame.PixelWidth, (int) frame.PixelHeight).FromStream(ras); bImg.ForEach( (x, y, color) => color.ToString().Equals("#FFCECECE") ? Color.FromArgb(80, 0, 0, 0) : Colors.WhiteSmoke); } BorderBrushStreamPlayer.ImageSource = bImg; }
//public static async Task<bool> GenerateImageAsync(InMemoryRandomAccessStream ms, string newImageName) //{ // using (var a = ms.AsStream()) // { // byte[] b = new byte[a.Length]; // await a.ReadAsync(b, 0, (int)a.Length); // StorageFile sampleFile = await _originalFolder.CreateFileAsync(newImageName); // await FileIO.WriteBytesAsync(sampleFile, b); // } // return true; //} //public async Task<bool> GenerateResizedImageAsyncOld(int longWidth, double srcWidth, double srcHeight, InMemoryRandomAccessStream srcMemoryStream, string newImageName, location subFolder, int longHeight = 0) //{ // if (_localFolder == null) InitFolders(); // try // { // int width = 0, height = 0; // double factor = srcWidth / srcHeight; // if (factor < 1) // { // height = longWidth; // width = (int)(longWidth * factor); // } // else // { // width = longWidth; // height = (int)(longWidth / factor); // } // if (longHeight > 0) // { // width = longWidth; // height = longHeight; // } // WriteableBitmap wb = await BitmapFactory.New((int)srcWidth, (int)srcHeight).FromStream(srcMemoryStream); // //WRITEABLE BITMAP IS THROWING AN ERROR // var wbthumbnail = wb.Resize(width, height, Windows.UI.Xaml.Media.Imaging.WriteableBitmapExtensions.Interpolation.Bilinear); // switch (subFolder) // { // case location.MediumFolder: // StorageFile sampleFile1 = await _mediumFolder.CreateFileAsync(newImageName, CreationCollisionOption.ReplaceExisting); // await wbthumbnail.SaveToFile(sampleFile1, BitmapEncoder.PngEncoderId); // break; // case location.ThumbFolder: // StorageFile sampleFile2 = await _thumbFolder.CreateFileAsync(newImageName, CreationCollisionOption.ReplaceExisting); // await wbthumbnail.SaveToFile(sampleFile2, BitmapEncoder.PngEncoderId); // break; // case location.TileFolder: // StorageFile sampleFile3 = await _tileFolder.CreateFileAsync(newImageName, CreationCollisionOption.ReplaceExisting); // await wbthumbnail.SaveToFile(sampleFile3, BitmapEncoder.PngEncoderId); // break; // } // return true; // } // catch (Exception ex) // { // return false; // } //} public async Task<bool> GenerateResizedImageAsync(int longWidth, double srcWidth, double srcHeight, InMemoryRandomAccessStream srcMemoryStream, string newImageName, location subFolder, int longHeight = 0) { if (_localFolder == null) InitFolders(); if (srcMemoryStream.Size == 0) return false; try { int width = 0, height = 0; double factor = srcWidth / srcHeight; if (factor < 1) { height = longWidth; width = (int)(longWidth * factor); } else { width = longWidth; height = (int)(longWidth / factor); } if (longHeight > 0) { width = longWidth; height = longHeight; } if (subFolder == location.MediumFolder) { WriteableBitmap wb = await BitmapFactory.New((int)srcWidth, (int)srcHeight).FromStream(srcMemoryStream); var wbthumbnail = wb.Resize(width, height, Windows.UI.Xaml.Media.Imaging.WriteableBitmapExtensions.Interpolation.Bilinear); StorageFile sampleFile1 = await _mediumFolder.CreateFileAsync(newImageName, CreationCollisionOption.ReplaceExisting); await wbthumbnail.SaveToFile(sampleFile1, BitmapEncoder.PngEncoderId); } else if (subFolder == location.ThumbFolder) { WriteableBitmap wb = await BitmapFactory.New((int)srcWidth, (int)srcHeight).FromStream(srcMemoryStream); var wbthumbnail = wb.Resize(width, height, Windows.UI.Xaml.Media.Imaging.WriteableBitmapExtensions.Interpolation.Bilinear); StorageFile sampleFile2 = await _thumbFolder.CreateFileAsync(newImageName, CreationCollisionOption.ReplaceExisting); await wbthumbnail.SaveToFile(sampleFile2, BitmapEncoder.PngEncoderId); } else if (subFolder == location.TileFolder) { //https://social.msdn.microsoft.com/Forums/en-US/490b9c01-db4b-434f-8aff-d5c495e67e55/how-to-crop-an-image-using-bitmaptransform?forum=winappswithcsharp BitmapDecoder decoder = await BitmapDecoder.CreateAsync(srcMemoryStream); using (InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream()) { BitmapEncoder enc = await BitmapEncoder.CreateForTranscodingAsync(ras, decoder); var h = longHeight / srcHeight; var w = longWidth / srcWidth; var r = Math.Max(h, w); enc.BitmapTransform.ScaledWidth = (uint)(srcWidth * r); enc.BitmapTransform.ScaledHeight = (uint)(srcHeight * r); BitmapBounds bounds = new BitmapBounds(); bounds.Width = (uint)longWidth; bounds.Height = (uint)longHeight; bounds.X = 0; bounds.Y = 0; enc.BitmapTransform.Bounds = bounds; await enc.FlushAsync(); WriteableBitmap wb = await BitmapFactory.New(longWidth, longHeight).FromStream(ras); StorageFile sampleFile3 = await _tileFolder.CreateFileAsync(newImageName, CreationCollisionOption.ReplaceExisting); await wb.SaveToFile(sampleFile3, BitmapEncoder.PngEncoderId); } } return true; } catch //(Exception ex) { return false; } }
private Rectangle ConvertPreviewToUiRectangle(BitmapBounds faceBoxInPreviewCoordinates) { var result = new Rectangle(); var previewStream = mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties; // If there is no available information about the preview, return an empty rectangle, as re-scaling to the screen coordinates will be impossible if (previewStream == null) return result; // Similarly, if any of the dimensions is zero (which would only happen in an error case) return an empty rectangle if (previewStream.Width == 0 || previewStream.Height == 0) return result; double streamWidth = previewStream.Width; double streamHeight = previewStream.Height; // Get the rectangle that is occupied by the actual video feed var previewInUI = GetPreviewStreamRectInControl(previewStream, PreviewControl); // Scale the width and height from preview stream coordinates to window coordinates result.Width = (faceBoxInPreviewCoordinates.Width / streamWidth) * previewInUI.Width; result.Height = (faceBoxInPreviewCoordinates.Height / streamHeight) * previewInUI.Height; // Scale the X and Y coordinates from preview stream coordinates to window coordinates var x = (faceBoxInPreviewCoordinates.X / streamWidth) * previewInUI.Width; var y = (faceBoxInPreviewCoordinates.Y / streamHeight) * previewInUI.Height; Canvas.SetLeft(result, x); Canvas.SetTop(result, y); return result; }
async void cropImage(IRandomAccessStream inputStream, uint bw, uint bh, uint w, uint h, string fname, StorageFolder folder) { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(inputStream); InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream(); BitmapEncoder enc = await BitmapEncoder.CreateForTranscodingAsync(ras, decoder); BitmapBounds bounds = new BitmapBounds(); bounds.Height = h; bounds.Width = w; bounds.X = bw; bounds.Y = bh; enc.BitmapTransform.Bounds = bounds; // write out to the stream try { await enc.FlushAsync(); } catch (Exception ex) { string s = ex.ToString(); } ras.Seek(0); // render the stream to the screen BitmapImage bImg = new BitmapImage(); bImg.SetSource(ras); imgHidden.Source = bImg; // image element in xaml if (folder != null) { StorageFile file1 = await folder.CreateFileAsync(fname + "."+imgFormat, CreationCollisionOption.ReplaceExisting); using (var fileStream1 = await file1.OpenAsync(FileAccessMode.ReadWrite)) { await RandomAccessStream.CopyAndCloseAsync(ras.GetInputStreamAt(0), fileStream1.GetOutputStreamAt(0)); } } }
private async Task<InMemoryRandomAccessStream> ResizeImage(InMemoryRandomAccessStream stream, Size requiredSize) { // Make a decoder for the current stream BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream); uint imageHeight = decoder.PixelHeight; uint imageWidth = decoder.PixelWidth; double widthRatio = imageWidth / requiredSize.Width; double heightRatio = imageHeight / requiredSize.Height; uint outputHeight = imageHeight; uint outputWidth = imageWidth; bool centerOnX = false; if (widthRatio < heightRatio) { outputHeight = (uint)(imageHeight / widthRatio); outputWidth = (uint)requiredSize.Width; centerOnX = false; } else { outputWidth = (uint)(imageWidth / heightRatio); outputHeight = (uint)requiredSize.Height; centerOnX = true; } // Make an output stream and an encoder InMemoryRandomAccessStream outputStream = new InMemoryRandomAccessStream(); BitmapEncoder enc = await BitmapEncoder.CreateForTranscodingAsync(outputStream, decoder); // convert the entire bitmap to a 125px by 125px bitmap enc.BitmapTransform.ScaledHeight = outputHeight; enc.BitmapTransform.ScaledWidth = outputWidth; BitmapBounds bound = new BitmapBounds(); bound.Height = (uint)requiredSize.Height; bound.Width = (uint)requiredSize.Width; // Choose Fant for quality over perf. enc.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant; if(centerOnX) { int width = ((int)outputWidth / 2) - ((int)bound.Width / 2); bound.X = (uint)(width > 0 ? width : 0); } else { int height = ((int)outputHeight / 2) - ((int)bound.Height / 2); bound.Y = (uint)(height > 0 ? height : 0); } enc.BitmapTransform.Bounds = bound; // Do it await enc.FlushAsync(); // Return the new stream return outputStream; }
/// <summary> /// Helper to get the correct Bounds for 15:9 screens and to set finalPhotoAreaBorder values /// </summary> /// <returns></returns> private BitmapBounds GetFifteenByNineBounds() { var bounds = new BitmapBounds(); // image size is raw pixels, so we need also here raw pixels var logicalPixelWidth = Window.Current.Bounds.Width; var logicalPixelHeight = Window.Current.Bounds.Height; var rawPerViewPixels = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel; var rawPixelHeight = logicalPixelHeight * rawPerViewPixels; var rawPixelWidth = logicalPixelWidth * rawPerViewPixels; // calculate scale factor of UniformToFill Height (remember, we rotated the preview) var scaleFactorVisualHeight = this.maxResolution().Width / rawPixelHeight; // calculate the visual Width // (because UniFormToFill scaled the previewElement Width down to match the previewElement Height) var visualWidth = this.maxResolution().Height / scaleFactorVisualHeight; // calculate cropping area for 15:9 var scaledBoundsWidth = this.maxResolution().Height; var scaledBoundsHeight = (scaledBoundsWidth / 9) * 15; // we are starting at the top of the image bounds.Y = 0; // cropping the image width bounds.X = 0; bounds.Height = scaledBoundsHeight; bounds.Width = scaledBoundsWidth; return bounds; }
private async Task<InMemoryRandomAccessStream> ResizeImage(InMemoryRandomAccessStream stream, Size requiredSize) { // Make a decoder for the current stream BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream); uint imageHeight = decoder.PixelHeight; uint imageWidth = decoder.PixelWidth; double widthRatio = imageWidth / requiredSize.Width; double heightRatio = imageHeight / requiredSize.Height; uint outputHeight = imageHeight; uint outputWidth = imageWidth; if (widthRatio < heightRatio) { outputHeight = (uint)(imageHeight / widthRatio); outputWidth = (uint)requiredSize.Width; } else { outputWidth = (uint)(imageWidth / heightRatio); outputHeight = (uint)requiredSize.Height; } // Make an output stream and an encoder InMemoryRandomAccessStream outputStream = new InMemoryRandomAccessStream(); BitmapEncoder enc = await BitmapEncoder.CreateForTranscodingAsync(outputStream, decoder); // convert the entire bitmap to a 125px by 125px bitmap enc.BitmapTransform.ScaledHeight = outputHeight; enc.BitmapTransform.ScaledWidth = outputWidth; BitmapBounds bound = new BitmapBounds(); bound.Height = (uint)requiredSize.Height; bound.Width = (uint)requiredSize.Width; enc.BitmapTransform.Bounds = bound; // Do it await enc.FlushAsync(); // Return the new stream return outputStream; }
public static async Task CropandScaleAsync(StorageFile source, StorageFile dest, Point startPoint, Size size, double m_scaleFactor) { uint startPointX = (uint)Math.Floor(startPoint.X); uint startPointY = (uint)Math.Floor(startPoint.Y); uint height = (uint)Math.Floor(size.Height); uint width = (uint)Math.Floor(size.Width); using (IRandomAccessStream sourceStream = await source.OpenReadAsync(), destStream = await dest.OpenAsync(FileAccessMode.ReadWrite)) { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(sourceStream); var m_displayHeightNonScaled = decoder.OrientedPixelHeight; var m_displayWidthNonScaled = decoder.OrientedPixelWidth; // Use the native (no orientation applied) image dimensions because we want to handle // orientation ourselves. BitmapTransform transform = new BitmapTransform(); BitmapBounds bounds = new BitmapBounds(); bounds.X = (uint)(startPointX * m_scaleFactor); bounds.Y = (uint)(startPointY * m_scaleFactor); bounds.Height = (uint)(height * m_scaleFactor); bounds.Width = (uint)(width * m_scaleFactor); transform.Bounds = bounds; // Scaling occurs before flip/rotation, therefore use the original dimensions // (no orientation applied) as parameters for scaling. transform.ScaledHeight = (uint)(decoder.PixelHeight * m_scaleFactor); transform.ScaledWidth = (uint)(decoder.PixelWidth * m_scaleFactor); transform.Rotation = BitmapRotation.None; // Fant is a relatively high quality interpolation mode. transform.InterpolationMode = BitmapInterpolationMode.Fant; BitmapPixelFormat format = decoder.BitmapPixelFormat; BitmapAlphaMode alpha = decoder.BitmapAlphaMode; // Set the encoder's destination to the temporary, in-memory stream. PixelDataProvider pixelProvider = await decoder.GetPixelDataAsync( format, alpha, transform, ExifOrientationMode.IgnoreExifOrientation, ColorManagementMode.ColorManageToSRgb ); byte[] pixels = pixelProvider.DetachPixelData(); Guid encoderID = Guid.Empty; switch (dest.FileType.ToLower()) { case ".png": encoderID = BitmapEncoder.PngEncoderId; break; case ".bmp": encoderID = BitmapEncoder.BmpEncoderId; break; default: encoderID = BitmapEncoder.JpegEncoderId; break; } // Write the pixel data onto the encoder. Note that we can't simply use the // BitmapTransform.ScaledWidth and ScaledHeight members as the user may have // requested a rotation (which is applied after scaling). var encoder = await BitmapEncoder.CreateAsync(encoderID, destStream); encoder.SetPixelData( format, alpha, (bounds.Width), (bounds.Height), decoder.DpiX, decoder.DpiY, pixels ); await encoder.FlushAsync(); } }