/// <summary> /// Scales the <see cref="Image"/> in both dimensions without changing its resolution. /// </summary> /// <param name="dst">The destination <see cref="Image"/>. Can be <b>null</b>.</param> /// <param name="scaleFactorX">The horizontal scaling factor.</param> /// <param name="scaleFactorY">The vertical scaling factor.</param> /// <param name="options">The scaling options.</param> /// <returns> /// The destination <see cref="Image"/>. /// </returns> public Image Scale(Image dst, double scaleFactorX, double scaleFactorY, ScalingOptions options) { int newWidth = (int)((this.Width * scaleFactorX) + 0.5); int newHeight = (int)((this.Height * scaleFactorY) + 0.5); return(this.ScaleToSize(dst, newWidth, newHeight, options)); }
/// <summary> /// Fits the <see cref="Image"/> into the area of specified dimensions. /// </summary> /// <param name="width">The width, in pixels, of the required image.</param> /// <param name="height">The height, in pixels, of the required image.</param> /// <param name="options">The scaling options.</param> /// <returns> /// A new scaled <see cref="Image"/>. /// </returns> /// <exception cref="InvalidOperationException"> /// The operation cannot be performed on the image with current color depth. /// </exception> /// <remarks> /// This method modifies the current <see cref="Image"/> by resizing and inflating it when necessary. /// The resulting image should be <paramref name="width"/> x <paramref name="height"/> in size. /// </remarks> public Image FitToSize(int width, int height, ScalingOptions options) { Image dst = this; // if image is bigger than required, crop black area first // try to preserve black area relative position within the image if (dst.Width > width || dst.Height > height) { Rectangle blackArea = dst.BlackArea(); if (!blackArea.IsEmpty && blackArea != dst.Bounds) { ////dst = dst.Crop(blackArea); if (blackArea.Height < height) { int dy = Core.MinMax.Min((height - blackArea.Height) / 2, blackArea.Y, dst.Height - blackArea.Bottom); blackArea.Inflate(0, dy, 0, height - blackArea.Height - dy); } if (width > 0 && blackArea.Width < width) { int dx = Core.MinMax.Min((width - blackArea.Width) / 2, blackArea.X, dst.Width - blackArea.Right); blackArea.Inflate(dx, 0, width - blackArea.Width - dx, 0); } blackArea.Intersect(dst.Bounds); if (blackArea != dst.Bounds) { dst = dst.Crop(blackArea); } } } if (dst.Width > width || dst.Height > height) { double horizontalFactor = (double)width / dst.Width; double verticalFactor = (double)height / dst.Height; double scaleFactor = Core.MinMax.Min(horizontalFactor, verticalFactor); int newWidth = (int)((dst.Width * scaleFactor) + 0.5f); int newHeight = (int)((dst.Height * scaleFactor) + 0.5f); if (dst.Width != newWidth || dst.Height != newHeight) { dst.ScaleToSize(dst, newWidth, newHeight, options); } } if (dst.Width < width || dst.Height < height) { int dx = width - dst.Width; int dy = height - dst.Height; dst = dst.Inflate(dx / 2, dy / 2, dx - (dx / 2), dy - (dy / 2), BorderType.BorderConst, dst.WhiteColor); } return(dst != this ? dst : dst.Copy(null, true)); }
/// <summary> /// Scales the <see cref="Image"/> vertically and horizontally without changing its resolution. /// </summary> /// <param name="dst">The destination <see cref="Image"/>. Can be <b>null</b>.</param> /// <param name="width">The desired width of the image, in pixels.</param> /// <param name="height">The desired height of the image, in pixels.</param> /// <param name="options">The scaling options.</param> /// <returns> /// The destination <see cref="Image"/>. /// </returns> public Image ScaleToSize(Image dst, int width, int height, ScalingOptions options) { if (width == this.Width && height == this.Height) { return(this.Copy(dst, true)); } if (width <= 0) { throw new ArgumentException(Properties.Resources.E_InvalidWidth, nameof(width)); } if (height <= 0) { throw new ArgumentException(Properties.Resources.E_InvalidHeight, nameof(height)); } System.Windows.Media.Matrix matrix = System.Windows.Media.Matrix.Identity; matrix.Scale((double)width / this.Width, (double)height / this.Height); #if false dst = this.Affine(dst, matrix, BorderType.BorderConst, this.WhiteColor); Debug.Assert(width == dst.Width && height == dst.Height, "Image dimensions are wrong."); return(dst); #else // IPP does not support 1bpp images - convert to 8bpp Image src; bool convert1bpp = false; if (this.BitsPerPixel == 1) { src = this.Convert1To8(null); convert1bpp = true; } else { src = this; } bool inplace = dst == this; dst = src.CreateTemplate(dst, width, height, src.BitsPerPixel); IPP.Execute(() => { return(NativeMethods.resize( src.BitsPerPixel, src.Width, src.Height, src.Bits, src.Stride8, dst.Width, dst.Height, dst.Bits, dst.Stride8, options.InterpolationType, options.Antialiasing, options.ValueB, options.ValueC, options.Lobes, BorderType.BorderConst, src.WhiteColor)); }); dst.AppendTransform(new MatrixTransform(matrix)); // convert back to 1bpp if (convert1bpp) { dst.Convert8To1(dst, 1); } if (inplace) { this.Attach(dst); return(this); } return(dst); #endif }
public Image Scale(Image dst, double scaleFactor, ScalingOptions options) => this.Scale(dst, scaleFactor, scaleFactor, options);