Beispiel #1
0
        private void ApplyResizeSettings(ResizeSettings settings, GhostscriptSettings ghostscriptSettings)
        {
            // Parse resize settings

            // - graphicsAlphaBits
            int graphicsAlphaBits = settings.GetValueOrDefault("graphicsbits", 0);

            if (!_validAlphaBitValues.Contains(graphicsAlphaBits))
            {
                // Use default value
                graphicsAlphaBits = _validAlphaBitValues.Last();
            }
            ghostscriptSettings.Add(GhostscriptArgument.GraphicsAlphaBits, graphicsAlphaBits);

            // - textAlphaBits
            int textAlphaBits = settings.GetValueOrDefault("textbits", 0);

            if (!_validAlphaBitValues.Contains(textAlphaBits))
            {
                // Use default value
                textAlphaBits = _validAlphaBitValues.Last();
            }
            ghostscriptSettings.Add(GhostscriptArgument.TextAlphaBits, textAlphaBits);

            ghostscriptSettings[GhostscriptArgument.GridFitTT]     = (settings.Get <bool>("gridfit") == true ? 2 : 0).ToString(NumberFormatInfo.InvariantInfo);
            ghostscriptSettings[GhostscriptArgument.AlignToPixels] = (settings.Get <bool>("subpixels") == true ? 1 : 0).ToString(NumberFormatInfo.InvariantInfo);
            if (settings.Get <bool>("printed", true) == false)
            {
                ghostscriptSettings.Remove(GhostscriptArgument.Printed);
            }
        }
Beispiel #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="format"></param>
        /// <param name="img"></param>
        /// <param name="target"></param>
        /// <param name="colors"></param>
        /// <param name="dither"></param>
        /// <param name="fourPass"></param>
        /// <param name="ditherPercent"></param>
        /// <param name="useGdiQuantization"></param>
        public void SaveIndexed(System.Drawing.Imaging.ImageFormat format, Image img, Stream target, byte colors, bool dither, bool fourPass, int ditherPercent)
        {
            if (PreservePalette && originalPalette != null)
            {
                img.Palette = originalPalette;
                //If we are encoding in PNG, and writing to a non-seekable stream,
                //we have to buffer it all in memory or we'll get an exception
                if (!target.CanSeek && ImageFormat.Png.Equals(format))
                {
                    using (MemoryStream ms = new MemoryStream(4096)) {
                        img.Save(ms, format); //Recursive call
                        ms.WriteTo(target);
                    }
                }
                else
                {
                    //Everything else
                    img.Save(target, format);
                }
                return;
            }


            OctreeQuantizer quantizer = new OctreeQuantizer(colors, GetBitsNeededForColorDepth(colors));

            if (query.Get <bool>("fulltrust", HasFullTrust))
            {
                quantizer.Dither        = dither;
                quantizer.FourPass      = fourPass;
                quantizer.DitherPercent = (float)ditherPercent / 100;
            }
            else
            {
                quantizer.FullTrust          = false;
                quantizer.OmitFinalStage     = true;
                quantizer.ResizeForFirstPass = true;

                quantizer.FirstPassPixelCount     = (long)Math.Pow(query.Get <int>("pixelCount", (int)Math.Sqrt(quantizer.FirstPassPixelCount)), 2);
                quantizer.FirstPassPixelThreshold = (long)Math.Pow(query.Get <int>("pixelThreshold", (int)Math.Sqrt(quantizer.FirstPassPixelThreshold)), 2);
            }
            using (Bitmap quantized = quantizer.Quantize(img)) {
                //If we are encoding in PNG, and writing to a non-seekable stream,
                //we have to buffer it all in memory or we'll get an exception
                if (!target.CanSeek && ImageFormat.Png.Equals(format))
                {
                    using (MemoryStream ms = new MemoryStream(4096)) {
                        quantized.Save(ms, format); //Recursive call
                        ms.WriteTo(target);
                    }
                }
                else
                {
                    //Everything else
                    quantized.Save(target, format);
                }
            }
        }
Beispiel #3
0
        public Bitmap Decode(Stream s, ResizeSettings settings)
        {
            return((Bitmap)DecodeAndCall(s, settings, delegate(ref FIBITMAP b, bool MayDispose) {
                bool usethumb = ("true".Equals(settings["usepreview"], StringComparison.OrdinalIgnoreCase));
                bool autorotate = settings.Get <bool>("autorotate", settings.Get <bool>("autorotate.default", false));


                return Convert(b, autorotate && !usethumb); //because usepreview prevents autorotate from working at the freeimage level
            }));
        }
Beispiel #4
0
            public System.Drawing.Bitmap GetBitmap()
            {
                Bitmap b = null;

                try {
                    int   w     = query.Width > 0 ? query.Width : (query.MaxWidth > 0 ? query.MaxWidth : 8);
                    int   h     = query.Height > 0 ? query.Height : (query.MaxHeight > 0 ? query.MaxHeight : 8);
                    float angle = query.Get <float>("angle", 0);
                    Color c1    = ParseUtils.ParseColor(query["color1"], Color.White);
                    Color c2    = ParseUtils.ParseColor(query["color2"], Color.Black);
                    b = new Bitmap(w, h);

                    using (Graphics g = Graphics.FromImage(b))
                        using (Brush brush = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, w, h), c1, c2, angle)){
                            g.FillRectangle(brush, 0, 0, w, h);
                        }
                } catch {
                    if (b != null)
                    {
                        b.Dispose();
                    }
                    throw;
                }
                return(b);
            }
Beispiel #5
0
        public WicEncoderPlugin(ResizeSettings settings, object original) : base(settings, original)
        {
            Dither      = true;
            Subsampling = settings["subsampling"];

            this.Colors = -1;
            //Parse colors
            int colors = -1;

            if (!string.IsNullOrEmpty(settings["colors"]))
            {
                if (int.TryParse(settings["colors"], out colors))
                {
                    this.Colors = colors;
                }
            }

            if ("false".Equals(settings["dither"], StringComparison.OrdinalIgnoreCase) ||
                "0".Equals(settings["dither"], StringComparison.OrdinalIgnoreCase))
            {
                Dither = false;
            }

            Interlace = settings.Get <bool>("interlace");
        }
        private PdfRenderFlags BuildFlags(ResizeSettings settings)
        {
            var flags = PdfRenderFlags.None;

            if (settings.Get <bool>("annotations").GetValueOrDefault())
            {
                flags |= PdfRenderFlags.Annotations;
            }
            if (settings.Get <bool>("lcd").GetValueOrDefault())
            {
                flags |= PdfRenderFlags.LcdText;
            }
            if (settings.Get <bool>("grayscale").GetValueOrDefault())
            {
                flags |= PdfRenderFlags.Grayscale;
            }
            if (settings.Get <bool>("halftone").GetValueOrDefault())
            {
                flags |= PdfRenderFlags.ForceHalftone;
            }
            if (settings.Get <bool>("print").GetValueOrDefault())
            {
                flags |= PdfRenderFlags.ForPrinting;
            }
            if (settings.Get <bool>("transparent").GetValueOrDefault())
            {
                flags |= PdfRenderFlags.Transparent;
            }
            return(flags);
        }
Beispiel #7
0
        public PrettyGifs(ResizeSettings settings, object original)
        {
            this.query = new ResizeSettings(settings);
            ResizeSettings q = settings;

            //Parse output format
            OutputFormat = GetFormatIfSuitable(settings, original);
            //Parse colors
            int colors = -1;

            if (!string.IsNullOrEmpty(q["colors"]))
            {
                if (int.TryParse(q["colors"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out colors))
                {
                    this.Colors = colors;
                }
            }
            //Parse dither settings
            if (!string.IsNullOrEmpty(q["dither"]))
            {
                if ("true".Equals(q["dither"], StringComparison.OrdinalIgnoreCase))
                {
                    this.Dither = true;
                }
                else if ("4pass".Equals(q["dither"], StringComparison.OrdinalIgnoreCase))
                {
                    this.FourPassDither = true;
                }
                else
                {
                    int dither;
                    if (int.TryParse(q["dither"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out dither))
                    {
                        DitherPercent = dither;
                        Dither        = true;
                    }
                }
            }

            PreservePalette = q.Get <bool>("preservePalette", PreservePalette);
            if (PreservePalette && original is Image && ((Image)original).Palette.Entries.Length > 0)
            {
                originalPalette = ((Image)original).Palette;
            }
        }
Beispiel #8
0
        public WicEncoderPlugin(ResizeSettings settings, object original)
            : base(settings,original)
        {
            Dither = true;
            Subsampling = settings["subsampling"];

            this.Colors = -1;
            //Parse colors
            int colors = -1;
            if (!string.IsNullOrEmpty(settings["colors"]))
                if (int.TryParse(settings["colors"], out colors))
                    this.Colors = colors;

            if ("false".Equals(settings["dither"], StringComparison.OrdinalIgnoreCase) ||
                "0".Equals(settings["dither"], StringComparison.OrdinalIgnoreCase)) Dither = false;

            Interlace = settings.Get<bool>("interlace");
        }
        public IEncoder CreateIfSuitable(ResizeSettings settings, object original)
        {
            var forcedFormat = !string.IsNullOrEmpty(settings.Format);
            var shouldEncode = forcedFormat ? _extensions.Contains(settings.Format) : _extensions.Contains(GetExtension(original));

            if (shouldEncode)
            {
                var quality = settings.Get <int>("quality");

                if (quality.HasValue)
                {
                    return(new MozJpegPlugin(quality.Value));
                }

                return(new MozJpegPlugin());
            }

            return(null);
        }
Beispiel #10
0
        private static object ToneMap(ref FIBITMAP b, bool mayUnloadOriginal, ResizeSettings settings, DecodeCallback callback)
        {
            return(callback(ref b, mayUnloadOriginal));//Tone mapping is disabled, not yet functional

            FIBITMAP m = FIBITMAP.Zero;

            try {
                var alg = settings.Get <ToneMappingAlgorithm>("fi.tonemap", ToneMappingAlgorithm.None);
                if (alg == ToneMappingAlgorithm.Drago)
                {
                    m = FreeImage.TmoDrago03(b, 2.2, 0);
                }
                else if (alg == ToneMappingAlgorithm.Reinhard)
                {
                    m = FreeImage.TmoReinhard05(b, 0, 0);
                }
                else if (alg == ToneMappingAlgorithm.Fattal)
                {
                    m = FreeImage.TmoFattal02(b, 0.5, 0.85);
                }
                else
                {
                    return(callback(ref b, mayUnloadOriginal));
                }
                if (mayUnloadOriginal)
                {
                    FreeImage.UnloadEx(ref b);
                }

                return(callback(ref m, true));
            } finally {
                if (!m.IsNull)
                {
                    FreeImage.UnloadEx(ref m);
                }
            }
        }
Beispiel #11
0
        public void ApplySettings(ResizeSettings settings)
        {
            copyRect = determineManualCropWindow(settings);

            //Save the manual crop size.
            SizeF      manualCropSize = copyRect.Size;
            RectangleF manualCropRect = copyRect;

            FitMode fit = determineFitMode(settings);

            //Aspect ratio of the image
            double imageRatio = copyRect.Width / copyRect.Height;

            //Zoom factor
            double zoom = settings.Get <double>("zoom", 1);

            //The target size for the image
            targetSize = new SizeF(-1, -1);
            //Target area for the image
            areaSize = new SizeF(-1, -1);
            //If any dimensions are specified, calculate. Otherwise, use original image dimensions
            if (settings.Width != -1 || settings.Height != -1 || settings.MaxHeight != -1 || settings.MaxWidth != -1)
            {
                //A dimension was specified.
                //We first calculate the largest size the image can be under the width/height/maxwidth/maxheight restriction
                //- pretending stretch=fill and scale=both

                //Temp vars - results stored in targetSize and areaSize
                double width     = settings.Width;
                double height    = settings.Height;
                double maxwidth  = settings.MaxWidth;
                double maxheight = settings.MaxHeight;

                //Eliminate cases where both a value and a max value are specified: use the smaller value for the width/height
                if (maxwidth > 0 && width > 0)
                {
                    width = Math.Min(maxwidth, width); maxwidth = -1;
                }
                if (maxheight > 0 && height > 0)
                {
                    height = Math.Min(maxheight, height); maxheight = -1;
                }

                //Handle cases of width/maxheight and height/maxwidth as in legacy version
                if (width != -1 && maxheight != -1)
                {
                    maxheight = Math.Min(maxheight, (width / imageRatio));
                }
                if (height != -1 && maxwidth != -1)
                {
                    maxwidth = Math.Min(maxwidth, (height * imageRatio));
                }


                //Move max values to width/height. FitMode should already reflect the mode we are using, and we've already resolved mixed modes above.
                width  = Math.Max(width, maxwidth);
                height = Math.Max(height, maxheight);

                //Calculate missing value (a missing value is handled the same everywhere).
                if (width > 0 && height <= 0)
                {
                    height = width / imageRatio;
                }
                else if (height > 0 && width <= 0)
                {
                    width = height * imageRatio;
                }

                //We now have width & height, our target size. It will only be a different aspect ratio from the image if both 'width' and 'height' are specified.

                //FitMode.Max
                if (fit == FitMode.Max)
                {
                    areaSize = targetSize = PolygonMath.ScaleInside(manualCropSize, new SizeF((float)width, (float)height));
                    //FitMode.Pad
                }
                else if (fit == FitMode.Pad)
                {
                    areaSize   = new SizeF((float)width, (float)height);
                    targetSize = PolygonMath.ScaleInside(manualCropSize, areaSize);
                    //FitMode.crop
                }
                else if (fit == FitMode.Crop)
                {
                    //We autocrop - so both target and area match the requested size
                    areaSize = targetSize = new SizeF((float)width, (float)height);
                    RectangleF copyRect;

                    ScaleMode scale             = settings.Scale;
                    bool      cropWidthSmaller  = manualCropSize.Width <= (float)width;
                    bool      cropHeightSmaller = manualCropSize.Height <= (float)height;

                    //TODO: consider mode=crop;fit=upscale

                    // With both DownscaleOnly (where only one dimension is smaller than
                    // requested) and UpscaleCanvas, we will have a targetSize based on the
                    // minWidth & minHeight.
                    // TODO: what happens if mode=crop;scale=down but the target is larger than the source?

                    if ((scale == ScaleMode.DownscaleOnly && (cropWidthSmaller != cropHeightSmaller)) ||
                        (scale == ScaleMode.UpscaleCanvas && (cropHeightSmaller || cropWidthSmaller)))
                    {
                        var minWidth  = Math.Min(manualCropSize.Width, (float)width);
                        var minHeight = Math.Min(manualCropSize.Height, (float)height);

                        targetSize = new SizeF(minWidth, minHeight);

                        copyRect = manualCropRect = new RectangleF(0, 0, minWidth, minHeight);

                        // For DownscaleOnly, the areaSize is adjusted to the new targetSize as well.
                        if (scale == ScaleMode.DownscaleOnly)
                        {
                            areaSize = targetSize;
                        }
                    }
                    else
                    {
                        //Determine the size of the area we are copying
                        Size sourceSize = PolygonMath.RoundPoints(PolygonMath.ScaleInside(areaSize, manualCropSize));
                        //Center the portion we are copying within the manualCropSize
                        copyRect = new RectangleF(0, 0, sourceSize.Width, sourceSize.Height);
                    }


                    // Align the actual source-copy rectangle inside the available
                    // space based on the anchor.
                    this.copyRect = PolygonMath.ToRectangle(PolygonMath.AlignWith(copyRect, this.copyRect, settings.Anchor));
                }
                else
                { //Stretch and carve both act like stretching, so do that:
                    areaSize = targetSize = new SizeF((float)width, (float)height);
                }
            }
            else
            {
                //No dimensions specified, no fit mode needed. Use manual crop dimensions
                areaSize = targetSize = manualCropSize;
            }

            //Multiply both areaSize and targetSize by zoom.
            areaSize.Width    *= (float)zoom;
            areaSize.Height   *= (float)zoom;
            targetSize.Width  *= (float)zoom;
            targetSize.Height *= (float)zoom;

            //Todo: automatic crop is permitted to break the scaling rule Fix!!

            //Now do upscale/downscale check If they take effect, set targetSize to imageSize
            if (settings.Scale == ScaleMode.DownscaleOnly)
            {
                if (PolygonMath.FitsInside(manualCropSize, targetSize))
                {
                    //The image is smaller or equal to its target polygon. Use original image coordinates instead.
                    areaSize = targetSize = manualCropSize;
                    copyRect = manualCropRect;
                }
            }
            else if (settings.Scale == ScaleMode.UpscaleOnly)
            {
                if (!PolygonMath.FitsInside(manualCropSize, targetSize))
                {
                    //The image is larger than its target. Use original image coordinates instead
                    areaSize = targetSize = manualCropSize;
                    copyRect = manualCropRect;
                }
            }
            else if (settings.Scale == ScaleMode.UpscaleCanvas)
            {
                //Same as downscaleonly, except areaSize isn't changed.
                if (PolygonMath.FitsInside(manualCropSize, targetSize))
                {
                    //The image is smaller or equal to its target polygon.

                    //Use manual copy rect/size instead.

                    targetSize = manualCropSize;
                    copyRect   = manualCropRect;
                }
            }


            //May 12: require max dimension and round values to minimize rounding differences later.
            areaSize.Width    = Math.Max(1, (float)Math.Round(areaSize.Width));
            areaSize.Height   = Math.Max(1, (float)Math.Round(areaSize.Height));
            targetSize.Width  = Math.Max(1, (float)Math.Round(targetSize.Width));
            targetSize.Height = Math.Max(1, (float)Math.Round(targetSize.Height));
        }
        private Size GetOutputSize(ResizeSettings settings, double boundingWidth, double boundingHeight)
        {
            // Output size is determined by resize settings, if available.
            //  maxwidth, maxheight
            //      – Fit the image within the specified bounds, preserving aspect ratio.
            //  width, height
            //      – Force the final width and/or height to certain dimensions.
            //        Whitespace will be added if the aspect ratio is different.
            // This plugin renders to a size within the requested size and then expects remaining plugins in the
            // pipeline to perform and additional processing such as adding whitespace, etc.
            // It can safely treat width/height as maxwidth/maxheight.

            double imageRatio = boundingWidth / boundingHeight;
            double width      = settings.Width;
            double height     = settings.Height;
            double maxwidth   = settings.MaxWidth;
            double maxheight  = settings.MaxHeight;

            //Allow overrides with pdfwidth and pdfheight when we *want* to rescale afterwards.
            int pw = settings.Get("pdfwidth", -1);
            int ph = settings.Get("pdfheight", -1);

            if (pw > 0)
            {
                width = pw; maxwidth = -1;
            }
            if (ph > 0)
            {
                height = ph; maxheight = -1;
            }

            //Handle cases of width/maxheight and height/maxwidth as in legacy versions.
            if (width != -1 && maxheight != -1)
            {
                maxheight = Math.Min(maxheight, (width / imageRatio));
            }
            if (height != -1 && maxwidth != -1)
            {
                maxwidth = Math.Min(maxwidth, (height * imageRatio));
            }

            //Eliminate cases where both a value and a max value are specified: use the smaller value for the width/height
            if (maxwidth > 0 && width > 0)
            {
                width = Math.Min(maxwidth, width); maxwidth = -1;
            }
            if (maxheight > 0 && height > 0)
            {
                height = Math.Min(maxheight, height); maxheight = -1;
            }

            //Move values to width/height
            if (width <= 0)
            {
                width = maxwidth;
            }
            if (height <= 0)
            {
                height = maxheight;
            }

            //Calculate missing value(s)
            if (width > 0 && height <= 0)
            {
                height = width / imageRatio;
            }
            else if (height > 0 && width <= 0)
            {
                width = height * imageRatio;
            }
            else if (width <= 0 && height <= 0)
            { // If neither width nor height as specified use default values
                width  = DefaultWidth;
                height = DefaultHeight;
            }

            // Limit maximum output size
            width  = Math.Min(width, this.MaxWidth);
            height = Math.Min(height, this.MaxHeight);


            // Determine the scaling values, and use the smallest to ensure we fit in the bounding box without changing
            // the aspect ratio otherwise we will crop.
            //Use a scaled version of boundingBox inside our maximum width and height constraints.
            return(PolygonMath.RoundPoints(PolygonMath.ScaleInside(new SizeF((float)boundingWidth, (float)boundingHeight), new SizeF((float)width, (float)height))));
        }
Beispiel #13
0
        private Size GetOutputSize(ResizeSettings settings, double boundingWidth, double boundingHeight)
        {
            // Output size is determined by resize settings, if available.
            //  maxwidth, maxheight
            //      – Fit the image within the specified bounds, preserving aspect ratio.
            //  width, height
            //      – Force the final width and/or height to certain dimensions.
            //        Whitespace will be added if the aspect ratio is different.
            // This plugin renders to a size within the requested size and then expects remaining plugins in the
            // pipeline to perform and additional processing such as adding whitespace, etc.
            // It can safely treat width/height as maxwidth/maxheight.

            double imageRatio = boundingWidth / boundingHeight;
            double width = settings.Width;
            double height = settings.Height;
            double maxwidth = settings.MaxWidth;
            double maxheight = settings.MaxHeight;

            //Allow overrides with pdfwidth and pdfheight when we *want* to rescale afterwards.
            int pw = settings.Get<int>("pdfwidth", -1);
            int ph = settings.Get<int>("pdfheight", -1);
            if (pw > 0) { width = pw; maxwidth = -1;}
            if (ph > 0) { height = ph; maxheight = -1; }

            //Handle cases of width/maxheight and height/maxwidth as in legacy versions.
            if (width != -1 && maxheight != -1) maxheight = Math.Min(maxheight, (width / imageRatio));
            if (height != -1 && maxwidth != -1) maxwidth = Math.Min(maxwidth, (height * imageRatio));

            //Eliminate cases where both a value and a max value are specified: use the smaller value for the width/height
            if (maxwidth > 0 && width > 0) { width = Math.Min(maxwidth, width); maxwidth = -1; }
            if (maxheight > 0 && height > 0) { height = Math.Min(maxheight, height); maxheight = -1; }

            //Move values to width/height
            if (width <= 0) width = maxwidth;
            if (height <= 0) height = maxheight;

            //Calculate missing value(s)
            if (width > 0 && height <= 0) height = width / imageRatio;
            else if (height > 0 && width <= 0) width = height * imageRatio;
            else if(width <= 0 && height <= 0) { // If neither width nor height as specified use default values
                width = DefaultWidth;
                height = DefaultHeight;
            }

            // Limit maximum output size
            width = Math.Min(width, this.MaxWidth);
            height = Math.Min(height, this.MaxHeight);

            // Determine the scaling values, and use the smallest to ensure we fit in the bounding box without changing
            // the aspect ratio otherwise we will crop.
            //Use a scaled version of boundingBox inside our maximum width and height constraints.
            return PolygonMath.RoundPoints(PolygonMath.ScaleInside(new SizeF((float)boundingWidth, (float)boundingHeight), new SizeF((float)width, (float)height)));
        }
Beispiel #14
0
        private void ApplyResizeSettings(ResizeSettings settings, GhostscriptSettings ghostscriptSettings)
        {
            // Parse resize settings

            // - graphicsAlphaBits
            int graphicsAlphaBits = settings.GetValueOrDefault("graphicsbits", 0);
            if(!_validAlphaBitValues.Contains(graphicsAlphaBits))
            {
                // Use default value
                graphicsAlphaBits = _validAlphaBitValues.Last();
            }
            ghostscriptSettings.Add(GhostscriptArgument.GraphicsAlphaBits, graphicsAlphaBits);

            // - textAlphaBits
            int textAlphaBits = settings.GetValueOrDefault("textbits", 0);
            if(!_validAlphaBitValues.Contains(textAlphaBits))
            {
                // Use default value
                textAlphaBits = _validAlphaBitValues.Last();
            }
            ghostscriptSettings.Add(GhostscriptArgument.TextAlphaBits, textAlphaBits);

            ghostscriptSettings[GhostscriptArgument.GridFitTT] = (settings.Get<bool>("gridfit") == true ? 2 : 0).ToString(NumberFormatInfo.InvariantInfo);
            ghostscriptSettings[GhostscriptArgument.AlignToPixels] = (settings.Get<bool>("subpixels") == true ? 1 : 0).ToString(NumberFormatInfo.InvariantInfo);
            if (settings.Get<bool>("printed",true) == false) ghostscriptSettings.Remove(GhostscriptArgument.Printed);
        }
Beispiel #15
0
        protected override RequestedAction BuildJob(ImageJob job)
        {
            if (!"wpf".Equals(job.Settings["builder"]))
            {
                return(RequestedAction.None);
            }

            // Estrazione delle ResizeSettings
            ResizeSettings settings = job.Settings;


            Stream s                     = null;
            bool   disposeStream         = !(job.Source is Stream);
            long   originalPosition      = 0;
            bool   restoreStreamPosition = false;

            string path;

            s = c.CurrentImageBuilder.GetStreamFromSource(job.Source, job.Settings, ref disposeStream, out path, out restoreStreamPosition);
            if (s == null)
            {
                return(RequestedAction.None);           //We don't support the source object!
            }
            if (job.ResetSourceStream)
            {
                restoreStreamPosition = true;
            }
            job.SourcePathData = path;

            // Instanzio uno stream locale per le operazioni WPF
            using (MemoryStream localStream = (s is MemoryStream) ? (MemoryStream)s : StreamExtensions.CopyToMemoryStream(s))
            {
                if (s != null && restoreStreamPosition && s.CanSeek)
                {
                    s.Seek(originalPosition, SeekOrigin.Begin);
                }

                if (disposeStream)
                {
                    s.Dispose();
                }

                /* ? ? ? */
                IEncoder managedEncoder       = c.Plugins.GetEncoder(job.Settings, job.SourcePathData);
                bool     supportsTransparency = managedEncoder.SupportsTransparency;

                // Recupero le dimensioni originali
                var frame = BitmapFrame.Create(StreamExtensions.CopyToMemoryStream(localStream));
                System.Windows.Size originalSize = new System.Windows.Size(frame.PixelWidth, frame.PixelHeight);

                // Resetto lo stream locale alla posizione iniziale, dopo aver letto i metadata
                localStream.Position = 0;



                // Uhm... sono costretto a referenziare le System.Drawing (GDI) per questo,
                // TODO: chiedere al tipo se si può prevedere un costruttore di ImageState che non preveda un System.Drawing.Size come parametro
                System.Drawing.Size orig = new System.Drawing.Size((int)originalSize.Width, (int)originalSize.Height);

                using (ImageState imageState = new ImageState(settings, orig, true))
                {
                    c.CurrentImageBuilder.Process(imageState);

                    Rectangle imageDest = PolygonMath.ToRectangle(PolygonMath.GetBoundingBox(imageState.layout["image"]));

                    BitmapSource finalImage;

                    BitmapImage bi = new BitmapImage();
                    bi.CacheOption = BitmapCacheOption.OnLoad;
                    bi.BeginInit();
                    bi.StreamSource = localStream;


                    WpfImageSettings wpfImageSettings = imageState.WpfDestinationImageSettings(settings);

                    bi.DecodePixelWidth  = Convert.ToInt32(wpfImageSettings.DestinationImageWidth);
                    bi.DecodePixelHeight = Convert.ToInt32(wpfImageSettings.DestinationImageHeight);
                    bi.EndInit();

                    // Creation of the encoder
                    WpfEncoderPlugin wpfEncoder = new WpfEncoderPlugin(settings, job.SourcePathData);


                    RenderTargetBitmap final = new RenderTargetBitmap(imageState.finalSize.Width, imageState.finalSize.Height, settings.Get <int>("dpi", 96), settings.Get <int>("dpi", 96), PixelFormats.Default);
                    DrawingVisual      dv    = new DrawingVisual();

                    using (DrawingContext dc = dv.RenderOpen())
                    {
                        string ARGBBackgroundColor = String.Format("#{0:X2}{1:X2}{2:X2}{3:X2}", wpfEncoder.MimeType.Equals("image/jpeg") ? 255 : settings.BackgroundColor.A,
                                                                   settings.BackgroundColor.R,
                                                                   settings.BackgroundColor.G,
                                                                   settings.BackgroundColor.B);

                        System.Windows.Media.Brush BrushBackgroundColor = new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString(ARGBBackgroundColor));

                        /* todo: verificare */
                        dc.DrawRectangle(BrushBackgroundColor, null, new Rect(0, 0, wpfImageSettings.DestinationImageWidth, wpfImageSettings.DestinationImageHeight));

                        Rect rect = new Rect(wpfImageSettings.OffsetX, wpfImageSettings.OffsetY, wpfImageSettings.DestinationImageWidth, wpfImageSettings.DestinationImageHeight);

                        //dc.PushTransform(new RotateTransform(settings.Rotate, (double)imageState.finalSize.Width / 2, (double)imageState.finalSize.Height / 2));

                        dc.DrawImage(bi, rect);
                    }

                    final.Render(dv);
                    finalImage = final;

                    // Write the image to the output stream
                    wpfEncoder.Write(finalImage, (Stream)job.Dest);
                }
            }

            return(RequestedAction.None);
        }
        /// <summary>
        /// Build a layout for the source image given the resize settings
        /// </summary>
        /// <param name="imageSourceSize"></param>
        /// <param name="resizeSettings"></param>
        public ImageLayout BuildLayout(Size imageSourceSize, ResizeSettings resizeSettings)
        {
            // by default, we are taking the entire image
            var sourceRectangle = new RectangleF(new PointF(0, 0), imageSourceSize);

            var fit = resizeSettings.Mode;
            // determine fit mode to use if both vertical and horizontal limits are used.
            if (fit == FitMode.None)
            {
                if (resizeSettings.Width != -1 || resizeSettings.Height != -1)
                {
                    // we specified both width and height
                    // we are looking for exact width and height then
                    // use pad to ensure height and width but ensure aspect ratio
                    // by adding padding where needed
                    fit = FitMode.Pad;
                }
                else
                {
                    fit = FitMode.Max;
                }
            }

            // Aspect source ratio of the image
            var imageRatio = sourceRectangle.Size.Width / sourceRectangle.Size.Height;

            // zoom factor
            var zoom = resizeSettings.Get<double>("zoom", 1);

            // The target size for the image
            var imageSize = new SizeF(-1, -1);

            // Target canvas size for the image
            var canvasSize = new SizeF(-1, -1);

            //If any dimensions are specified, calculate. Otherwise, use original image dimensions
            if (resizeSettings.Width != -1 || resizeSettings.Height != -1 || resizeSettings.MaxHeight != -1 || resizeSettings.MaxWidth != -1)
            {
                // a dimension was specified.
                // we first calculate the largest size the image can be under the width/height/maxwidth/maxheight restrictions.
                // pretending stretch=fill and scale=both

                // temp vars - results stored in targetSize and areaSize
                double width = resizeSettings.Width;
                double height = resizeSettings.Height;
                double maxwidth = resizeSettings.MaxWidth;
                double maxheight = resizeSettings.MaxHeight;

                // eliminate cases where both a value and a max value are specified: use the smaller value for the width/height
                if (maxwidth > 0 && width > 0) { width = Math.Min(maxwidth, width); maxwidth = -1; }
                if (maxheight > 0 && height > 0) { height = Math.Min(maxheight, height); maxheight = -1; }

                // handle cases of width/maxheight and height/maxwidth.
                if (width != -1 && maxheight != -1) maxheight = Math.Min(maxheight, (width / imageRatio));
                if (height != -1 && maxwidth != -1) maxwidth = Math.Min(maxwidth, (height * imageRatio));

                //Move max values to width/height. FitMode should already reflect the mode we are using, and we've already resolved mixed modes above.
                width = Math.Max(width, maxwidth);
                height = Math.Max(height, maxheight);

                // calculate missing value (a missing value is handled the same everywhere).
                if (width > 0 && height <= 0)
                    height = width / imageRatio;
                else if (height > 0 && width <= 0)
                    width = height * imageRatio;

                // we now have width & height, our target size. It will only be a different aspect ratio from the image if both 'width' and 'height' are specified.

                if (fit == FitMode.Max)
                {
                    canvasSize = imageSize = PolygonMath.ScaleInside(sourceRectangle.Size, new SizeF((float)width, (float)height));
                }
                else if (fit == FitMode.Pad)
                {
                    canvasSize = new SizeF((float)width, (float)height);
                    imageSize = PolygonMath.ScaleInside(sourceRectangle.Size, canvasSize);
                }
                else if (fit == FitMode.Crop)
                {
                    canvasSize = new SizeF((float)width, (float)height);
                    imageSize = PolygonMath.RoundPoints(PolygonMath.ScaleOutside(canvasSize, sourceRectangle.Size));

                }
                else
                {
                    // stretch
                    canvasSize = imageSize = new SizeF((float)width, (float)height);
                }
            }
            else
            {
                // no dimensions specified, no fit mode needed.
                canvasSize = imageSize = sourceRectangle.Size;
            }

            //Multiply both areaSize and targetSize by zoom.
            canvasSize.Width *= (float)zoom;
            canvasSize.Height *= (float)zoom;
            imageSize.Width *= (float)zoom;
            imageSize.Height *= (float)zoom;

            // NOTE: automatic crop is permitted to break the scaling rules.

            //Now do upscale/downscale checks. If they take effect, set targetSize to imageSize
            if (resizeSettings.Scale == ScaleMode.DownscaleOnly)
            {
                if (PolygonMath.FitsInside(sourceRectangle.Size, imageSize))
                {
                    // the image is smaller or equal to its target polygon. Use original image coordinates instead.
                    canvasSize = imageSize = sourceRectangle.Size;
                }
            }
            else if (resizeSettings.Scale == ScaleMode.UpscaleOnly)
            {
                if (!PolygonMath.FitsInside(sourceRectangle.Size, imageSize))
                {
                    // the image is larger than its target. Use original image coordintes instead
                    canvasSize = imageSize = sourceRectangle.Size;
                }
            }
            else if (resizeSettings.Scale == ScaleMode.UpscaleCanvas)
            {
                // same as downscaleonly, except areaSize isn't changed.
                if (PolygonMath.FitsInside(sourceRectangle.Size, imageSize))
                {
                    //The image is smaller or equal to its target polygon.
                    imageSize = sourceRectangle.Size;
                }
            }

            // require max dimension and round values to minimize rounding differences.
            canvasSize.Width = Math.Max(1, (float)Math.Round(canvasSize.Width));
            canvasSize.Height = Math.Max(1, (float)Math.Round(canvasSize.Height));
            imageSize.Width = Math.Max(1, (float)Math.Round(imageSize.Width));
            imageSize.Height = Math.Max(1, (float)Math.Round(imageSize.Height));

            //Translate and scale all existing rings

            var image = PolygonMath.ToPoly(new RectangleF(new PointF(0, 0), imageSize));

            var imageArea = PolygonMath.ToPoly(new RectangleF(new PointF(0, 0), canvasSize));

            // center canvas around the image
            image = PolygonMath.AlignWith(image, imageArea, resizeSettings.Anchor);

            return new ImageLayout(PolygonMath.GetBoundingBox(image), canvasSize);
        }