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); } }
/// <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); } } }
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 })); }
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); }
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); }
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; } }
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); }
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); } } }
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)))); }
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))); }
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); }
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); }