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;
     }
 }
Example #4
0
        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);
            }
        }
Example #8
0
        /// <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));
        }