Example #1
0
        /// <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));
        }
Example #2
0
        /// <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));
        }
Example #3
0
        /// <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
        }
Example #4
0
 public Image Scale(Image dst, double scaleFactor, ScalingOptions options) =>
 this.Scale(dst, scaleFactor, scaleFactor, options);