private static System.Drawing.RotateFlipType GetRotateFlipType(MediaAssetRotateFlip rotation) { switch (rotation) { case MediaAssetRotateFlip.Rotate0FlipNone: return(System.Drawing.RotateFlipType.RotateNoneFlipNone); case MediaAssetRotateFlip.Rotate90FlipNone: return(System.Drawing.RotateFlipType.Rotate90FlipNone); case MediaAssetRotateFlip.Rotate180FlipNone: return(System.Drawing.RotateFlipType.Rotate180FlipNone); case MediaAssetRotateFlip.Rotate270FlipNone: return(System.Drawing.RotateFlipType.Rotate270FlipNone); case MediaAssetRotateFlip.Rotate0FlipX: return(System.Drawing.RotateFlipType.RotateNoneFlipX); case MediaAssetRotateFlip.Rotate0FlipY: return(System.Drawing.RotateFlipType.RotateNoneFlipY); default: return(System.Drawing.RotateFlipType.RotateNoneFlipNone); } }
/// <summary> /// Generates a <see cref="TransformedBitmap" /> instance based on the <paramref name="stream" /> and <paramref name="requestedRotateFlip" />. /// </summary> /// <param name="stream">A stream generated from the image to be transformed.</param> /// <param name="requestedRotateFlip">The requested amount to rotate and/or flip the image.</param> /// <returns>An instance of <see cref="TransformedBitmap" />.</returns> /// <exception cref="System.ArgumentException">Thrown when <paramref name="requestedRotateFlip" /> is an unrecognized value.</exception> /// <remarks>When a two-step transformation is requested (e.g. <see cref="MediaAssetRotateFlip.Rotate90FlipX" />), this function /// generates two transforms - one for the rotation and one for the flipping.</remarks> private static TransformedBitmap GetRotateFlipBitmap(MemoryStream stream, MediaAssetRotateFlip requestedRotateFlip) { var transform1 = GetRotateBeforeFlipTransformIfNeeded(requestedRotateFlip); Transform transform2; switch (requestedRotateFlip) { case MediaAssetRotateFlip.NotSpecified: case MediaAssetRotateFlip.Rotate0FlipNone: transform2 = new RotateTransform(0); break; case MediaAssetRotateFlip.Rotate90FlipNone: transform2 = new RotateTransform(90); break; case MediaAssetRotateFlip.Rotate180FlipNone: transform2 = new RotateTransform(180); break; case MediaAssetRotateFlip.Rotate270FlipNone: transform2 = new RotateTransform(270); break; case MediaAssetRotateFlip.Rotate0FlipX: case MediaAssetRotateFlip.Rotate90FlipX: case MediaAssetRotateFlip.Rotate180FlipX: case MediaAssetRotateFlip.Rotate270FlipX: transform2 = new ScaleTransform(1, -1); break; case MediaAssetRotateFlip.Rotate0FlipY: case MediaAssetRotateFlip.Rotate90FlipY: case MediaAssetRotateFlip.Rotate180FlipY: case MediaAssetRotateFlip.Rotate270FlipY: transform2 = new ScaleTransform(-1, 1); break; default: throw new ArgumentException($"The function GetRotateFlipBitmap() was not designed to handle the enumeration {requestedRotateFlip}."); } if (transform1 == null) { return(new TransformedBitmap(ReadBitmapFrame(stream), transform2)); } else { var transformGroup = new TransformGroup(); transformGroup.Children.Add(transform1); transformGroup.Children.Add(transform2); return(new TransformedBitmap(ReadBitmapFrame(stream), transformGroup)); } }
private static SixLabors.ImageSharp.Processing.FlipType GetFlipType(MediaAssetRotateFlip rotation) { switch (rotation) { case MediaAssetRotateFlip.Rotate0FlipX: return FlipType.Horizontal; case MediaAssetRotateFlip.Rotate0FlipY: return FlipType.Vertical; default: return FlipType.None; } }
public async Task <IActionResult> RotateFlip(GalleryItem[] galleryItems, MediaAssetRotateFlip rotateFlip, DisplayObjectType viewSize) { try { return(new JsonResult(await _galleryObjectController.RotateFlip(galleryItems, rotateFlip, viewSize))); } catch (Exception ex) { AppEventController.LogError(ex); return(StatusCode(500, _exController.GetExString(ex))); } }
///// <summary> ///// Create an image file having a max length of <paramref name="maxLength" /> and JPEG quality of ///// <paramref ///// name="jpegQuality" /> ///// from the original file of <see cref="GalleryObject" />. The file is saved to the location ///// <paramref ///// name="newFilePath" /> ///// . ///// The width and height of the generated image is returned as a <see cref="Size" /> instance. The GDI+ classes ///// are used to create the image, which are slower than WPF but run in Medium Trust. ///// </summary> ///// <param name="newFilePath">The full path where the image will be saved.</param> ///// <param name="maxLength">The maximum length of one side of the image.</param> ///// <param name="jpegQuality">The JPEG quality.</param> ///// <returns> ///// Returns a <see cref="Size" /> instance containing the width and height of the generated image. ///// </returns> ///// <exception cref="UnsupportedImageTypeException"> ///// Thrown when Gallery Server cannot process the image, ///// most likely because it is corrupt or an unsupported image type. ///// </exception> //private SixLabors.Primitives.Size GenerateImageUsingGdi(string newFilePath, int maxLength, int jpegQuality) //{ // try // { // Size newSize; // using (var source = new System.Drawing.Bitmap(GalleryObject.Original.FileInfo.FullName)) // { // newSize = CalculateWidthAndHeight(new Size(source.Width, source.Height), maxLength, false); // // Generate the new image and save to disk. // newSize = ImageHelper.SaveImageFile(source, newFilePath, System.Drawing.Imaging.ImageFormat.Jpeg, newSize.Width, newSize.Height, jpegQuality); // } // var rotatedSize = ExecuteAutoRotation(newFilePath, jpegQuality); // return rotatedSize.IsEmpty ? newSize : rotatedSize; // } // catch (ArgumentException ex) // { // throw new UnsupportedImageTypeException(GalleryObject, ex); // } // catch (ExternalException ex) // { // throw new UnsupportedImageTypeException(GalleryObject, ex); // } // catch (OutOfMemoryException ex) // { // throw new UnsupportedImageTypeException(GalleryObject, ex); // } //} ///// <summary> ///// Create an image file having a max length of <paramref name="maxLength" /> and JPEG quality of ///// <paramref ///// name="jpegQuality" /> ///// from the original file of <see cref="GalleryObject" />. The file is saved to the location ///// <paramref ///// name="newFilePath" /> ///// . ///// The width and height of the generated image is returned as a <see cref="Size" /> instance. The GDI+ classes ///// are used to create the image, which are slower than WPF but run in Medium Trust. ///// </summary> ///// <param name="newFilePath">The full path where the image will be saved.</param> ///// <param name="maxLength">The maximum length of one side of the image.</param> ///// <param name="jpegQuality">The JPEG quality.</param> ///// <returns> ///// Returns a <see cref="Size" /> instance containing the width and height of the generated image. ///// </returns> ///// <exception cref="UnsupportedImageTypeException"> ///// Thrown when Gallery Server cannot process the image, ///// most likely because it is corrupt or an unsupported image type. ///// </exception> //private Size GenerateImageUsingGdi(string newFilePath, int maxLength, int jpegQuality) //{ // try // { // Size newSize; // using (var source = new System.Drawing.Bitmap(GalleryObject.Original.FileInfo.FullName)) // { // newSize = CalculateWidthAndHeight(new Size(source.Width, source.Height), maxLength, false); // // Generate the new image and save to disk. // newSize = ImageHelper.SaveImageFile(source, newFilePath, System.Drawing.Imaging.ImageFormat.Jpeg, newSize.Width, newSize.Height, jpegQuality); // } // var rotatedSize = ExecuteAutoRotation(newFilePath, jpegQuality); // return rotatedSize.IsEmpty ? newSize : rotatedSize; // } // catch (ArgumentException ex) // { // throw new UnsupportedImageTypeException(GalleryObject, ex); // } // catch (ExternalException ex) // { // throw new UnsupportedImageTypeException(GalleryObject, ex); // } // catch (OutOfMemoryException ex) // { // throw new UnsupportedImageTypeException(GalleryObject, ex); // } //} //private static BitmapFrame ReadBitmapFrame(MemoryStream photoStream) //{ // var photoDecoder = BitmapDecoder.Create(photoStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None); // return photoDecoder.Frames[0]; //} //private static BitmapFrame FastResize(BitmapFrame photo, double width, double height) //{ // var dpiXFactor = (photo.DpiX > 0 ? 96 / photo.DpiX : 1); // var dpiYFactor = (photo.DpiY > 0 ? 96 / photo.DpiY : 1); // var target = new TransformedBitmap( // photo, // new ScaleTransform( // width / photo.Width * dpiXFactor, // height / photo.Height * dpiYFactor, // 0, 0)); // return BitmapFrame.Create(target); //} //private static BitmapFrame Resize(BitmapFrame photo, int width, int height, BitmapScalingMode scalingMode = BitmapScalingMode.Fant) //{ // // This is a more flexible, albiet slower alternative to FastResize. For more info: // // http://weblogs.asp.net/bleroy/archive/2009/12/10/resizing-images-from-the-server-using-wpf-wic-instead-of-gdi.aspx // var group = new DrawingGroup(); // RenderOptions.SetBitmapScalingMode(group, scalingMode); // group.Children.Add(new ImageDrawing(photo, new Rect(0, 0, width, height))); // var targetVisual = new DrawingVisual(); // DrawingContext targetContext = targetVisual.RenderOpen(); // targetContext.DrawDrawing(group); // var target = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default); // targetContext.Close(); // target.Render(targetVisual); // return BitmapFrame.Create(target); //} ///// <summary> ///// Generates the JPEG in <paramref name="targetFrame" /> to a JPEG byte array having the specified <paramref name="quality" />. ///// </summary> ///// <param name="targetFrame">The target frame containing the JPEG.</param> ///// <param name="quality">The quality the generated JPEG is to have.</param> ///// <returns>System.Byte[][].</returns> ///// <exception cref="FileFormatException">Thrown when an input file or a data stream that is supposed to conform to a ///// certain file format specification is malformed. Thrown by <see cref="JpegBitmapEncoder.Save" />.</exception> ///// <exception cref="NotSupportedException">Thrown when <see cref="JpegBitmapEncoder" /> does not have a valid frame.</exception> //private static byte[] GenerateJpegByteArray(BitmapFrame targetFrame, int quality) //{ // byte[] targetBytes; // using (var memoryStream = new MemoryStream()) // { // var targetEncoder = new JpegBitmapEncoder // { // QualityLevel = quality // }; // targetEncoder.Frames.Add(targetFrame); // targetEncoder.Save(memoryStream); // targetBytes = memoryStream.ToArray(); // } // return targetBytes; //} //private Size GetSizeUsingWpf(IDisplayObject displayObject) //{ // try // { // var photoBytes = File.ReadAllBytes(displayObject.FileNamePhysicalPath); // using (var photoStream = new MemoryStream(photoBytes)) // { // var photo = ReadBitmapFrame(photoStream); // return new Size(photo.PixelWidth, photo.PixelHeight); // } // } // catch (NotSupportedException) // { // return GetSizeUsingGdi(displayObject); // } // catch (Exception ex) // { // if (!ex.Data.Contains("SizeMsg")) // { // ex.Data.Add("SizeMsg", String.Format("Unable to get the width and height of media object {0} ({1}). Display Type {2}", GalleryObject.Id, displayObject.FileNamePhysicalPath, displayObject.DisplayType)); // } // EventController.RecordError(ex, AppSetting.Instance, GalleryObject.GalleryId, Factory.LoadGallerySettings()); // return Size.Empty; // } //} //private static Size GetSizeUsingGdi(IDisplayObject displayObject) //{ // try // { // using (var source = new System.Drawing.Bitmap(displayObject.FileNamePhysicalPath)) // { // return new Size(source.Width, source.Height); // } // } // catch (ArgumentException) // { // return Size.Empty; // } // catch (ExternalException) // { // return Size.Empty; // } // catch (OutOfMemoryException) // { // return Size.Empty; // } //} private static SixLabors.ImageSharp.Processing.RotateType GetRotateType(MediaAssetRotateFlip rotation) { switch (rotation) { case MediaAssetRotateFlip.Rotate90FlipNone: return RotateType.Rotate90; case MediaAssetRotateFlip.Rotate180FlipNone: return RotateType.Rotate180; case MediaAssetRotateFlip.Rotate270FlipNone: return RotateType.Rotate270; default: return RotateType.None; } }
public ActionResult RotateFlip(GalleryItem[] galleryItems, MediaAssetRotateFlip rotateFlip, DisplayObjectType viewSize) { try { return(GalleryObjectController.RotateFlip(galleryItems, rotateFlip, viewSize)); } catch (Exception ex) { AppEventController.LogError(ex); throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError) { Content = Utils.GetExStringContent(ex), ReasonPhrase = "Server Error" }); } }
/// <summary> /// Get the <see cref="Transform" /> for situations where both a rotation and a flip are being performed. The returned instance configures /// the rotation aspect of a two-step transformation. It is expected that other code will add a separate transform to handle the flipping. /// Returns null when only a single step transformation is specified. /// </summary> /// <param name="rotateFlipRequest">The requested amount of rotation/flipping.</param> /// <returns>An instance of <see cref="Transform" />.</returns> private static Transform GetRotateBeforeFlipTransformIfNeeded(MediaAssetRotateFlip rotateFlipRequest) { switch (rotateFlipRequest) { case MediaAssetRotateFlip.Rotate90FlipX: case MediaAssetRotateFlip.Rotate90FlipY: return(new RotateTransform(90)); case MediaAssetRotateFlip.Rotate180FlipX: case MediaAssetRotateFlip.Rotate180FlipY: return(new RotateTransform(180)); case MediaAssetRotateFlip.Rotate270FlipX: case MediaAssetRotateFlip.Rotate270FlipY: return(new RotateTransform(270)); default: return(null); } }
/// <summary> /// Gets the rotation filter corresponding to the requested rotation amount. Returns an empty string when /// no rotation is requested. /// </summary> /// <param name="rotation">The amount of rotation being requested.</param> /// <param name="encoderArguments"></param> /// <returns>System.String.</returns> /// <remarks>Documentation: http://ffmpeg.org/ffmpeg-filters.html#transpose, http://ffmpeg.org/ffmpeg-filters.html#hflip, /// http://ffmpeg.org/ffmpeg-filters.html#vflip</remarks> private static string GetAutoRotationFilter(MediaAssetRotateFlip rotation, string encoderArguments) { var filter = string.Empty; if (!encoderArguments.Contains(AutoRotateFilterName)) { return(filter); } switch (rotation) { case MediaAssetRotateFlip.Rotate0FlipNone: break; case MediaAssetRotateFlip.Rotate0FlipX: filter = "vflip"; break; case MediaAssetRotateFlip.Rotate0FlipY: filter = "hflip"; break; case MediaAssetRotateFlip.Rotate90FlipNone: filter = "transpose=clock"; break; case MediaAssetRotateFlip.Rotate90FlipX: filter = "transpose=clock,vflip"; break; case MediaAssetRotateFlip.Rotate90FlipY: filter = "transpose=clock,hflip"; break; case MediaAssetRotateFlip.Rotate180FlipNone: filter = "hflip,vflip"; break; case MediaAssetRotateFlip.Rotate180FlipX: filter = "transpose=clock,transpose=clock,vflip"; break; case MediaAssetRotateFlip.Rotate180FlipY: filter = "transpose=clock,transpose=clock,hflip"; break; case MediaAssetRotateFlip.Rotate270FlipNone: filter = "transpose=cclock"; break; case MediaAssetRotateFlip.Rotate270FlipX: filter = "transpose=cclock,vflip"; break; case MediaAssetRotateFlip.Rotate270FlipY: filter = "transpose=cclock,hflip"; break; default: throw new ArgumentException($"The function FFmpeg.GetAutoRotationFilter is not designed to handle the enumeration {rotation}."); } return(ApplyCommaToRotationFilter(filter, encoderArguments)); }