Example #1
0
        /// <summary>
        /// Flood-fill an area.
        /// </summary>
        /// <example>
        /// <code language="lang-csharp">
        /// image.Mutate(x => x.DrawFlood(ink, x, y, out var left, out var top, test: Image, equal: bool));
        /// </code>
        /// </example>
        /// <param name="ink">Color for pixels.</param>
        /// <param name="x">DrawFlood start point.</param>
        /// <param name="y">DrawFlood start point.</param>
        /// <param name="left">Left edge of modified area.</param>
        /// <param name="top">top edge of modified area.</param>
        /// <param name="test">Test pixels in this image.</param>
        /// <param name="equal">DrawFlood while equal to edge.</param>
        public void DrawFlood(double[] ink, int x, int y, out int left, out int top, Image test = null, bool?equal = null)
        {
            var options = new VOption();

            options.AddIfPresent(nameof(test), test);
            options.AddIfPresent(nameof(equal), equal);

            options.Add("left", true);
            options.Add("top", true);

            var results = this.Call("draw_flood", options, ink, x, y) as object[];

            var opts = results?[1] as VOption;

            left = opts?["left"] is int out1 ? out1 : 0;
            top  = opts?["top"] is int out2 ? out2 : 0;
        }
Example #2
0
        internal VOption BuildLoadOptionsFromImageType(ImageType imageType)
        {
            var result = new VOption();

            if (imageType == ImageType.Svg || imageType == ImageType.Pdf)
            {
                result.Add("dpi", Options.Density);
            }
            else if (imageType == ImageType.Magick)
            {
                result.Add("density", Options.Density.ToString(CultureInfo.InvariantCulture));
            }

            if (imageType.SupportsPages)
            {
                result.Add("n", Options.PageCount);
                result.Add("page", Options.PageIndex);
            }

            return(result);
        }
Example #3
0
        public string Execute(string[] args)
        {
            // If you set a number to zero (0), it will resize on the other specified axis.
            var width  = 200;
            var height = 0;

            // "both" - for both up and down.
            // "up" - only upsize.
            // "down" - only downsize.
            // "force" - force size, that is, break aspect ratio.
            const string size = "both";

            // Just for example.
            var buffer = File.ReadAllBytes(Filename);

            // Find the name of the load operation vips will use to load a buffer
            // so that we can work out what options to pass to NewFromBuffer().
            var loader = Image.FindLoadBuffer(buffer);

            if (loader == null)
            {
                // No known loader is found, stop further processing.
                throw new Exception("Invalid or unsupported image format. Is it a valid image?");
            }

            var loadOptions = new VOption
            {
                { "access", Enums.Access.Sequential },
                { "fail", FailOnError }
            };
            var stringOptions = "";

            if (LoaderSupportPage(loader))
            {
                // -1 means "until the end of the document", handy for animated images.
                loadOptions.Add("n", -1);
                stringOptions = "[n=-1]";
            }

            Image image;

            try
            {
                image = (Image)Operation.Call(loader, loadOptions, buffer);

                // Or:
                // image = Image.NewFromBuffer(buffer, kwargs: loadOptions);
                // (but the loader is already found, so the above will be a little faster).
            }
            catch (VipsException e)
            {
                throw new Exception("Image has a corrupt header.", e);
            }

            var inputWidth  = image.Width;
            var inputHeight = image.Height;

            // Use 64-bit unsigned type, to handle PNG decompression bombs.
            if ((ulong)(inputWidth * inputHeight) > MaxImageSize)
            {
                throw new Exception(
                          "Image is too large for processing. Width x height should be less than 71 megapixels.");
            }

            var pageHeight = image.PageHeight;

            var isCmyk          = image.Interpretation == Enums.Interpretation.Cmyk;
            var isLabs          = image.Interpretation == Enums.Interpretation.Labs;
            var embeddedProfile = image.Contains(VipsMetaIccName);

            string importProfile = null;
            string exportProfile = null;
            string intent        = null;

            // Ensure we're using a device-independent color space
            if ((embeddedProfile || isCmyk) && !isLabs)
            {
                // Embedded profile; fallback in case the profile embedded in the image
                // is broken. No embedded profile; import using default CMYK profile.
                importProfile = isCmyk ? Enums.Interpretation.Cmyk : Enums.Interpretation.Srgb;

                // Convert to sRGB using embedded or import profile.
                exportProfile = Enums.Interpretation.Srgb;

                // Use "perceptual" intent to better match imagemagick.
                intent = Enums.Intent.Perceptual;
            }

            // Scaling calculations
            var thumbnailWidth  = width;
            var thumbnailHeight = height;

            if (width > 0 && height > 0) // Fixed width and height
            {
                var xFactor = (double)inputWidth / width;
                var yFactor = (double)pageHeight / height;

                if (xFactor > yFactor) // Or: if (xFactor < yFactor)
                {
                    thumbnailHeight = (int)Math.Round(pageHeight / xFactor);
                }
                else
                {
                    thumbnailWidth = (int)Math.Round(inputWidth / yFactor);
                }
            }
            else if (width > 0) // Fixed width
            {
                if (size == "force")
                {
                    thumbnailHeight = pageHeight;
                    height          = pageHeight;
                }
                else
                {
                    // Auto height
                    var yFactor = (double)inputWidth / width;
                    height = (int)Math.Round(pageHeight / yFactor);

                    // Height is missing, replace with a huuuge value to prevent
                    // reduction or enlargement in that axis
                    thumbnailHeight = VipsMaxCoord;
                }
            }
            else if (height > 0) // Fixed height
            {
                if (size == "force")
                {
                    thumbnailWidth = inputWidth;
                    width          = inputWidth;
                }
                else
                {
                    // Auto width
                    var xFactor = (double)pageHeight / height;
                    width = (int)Math.Round(inputWidth / xFactor);

                    // Width is missing, replace with a huuuge value to prevent
                    // reduction or enlargement in that axis
                    thumbnailWidth = VipsMaxCoord;
                }
            }
            else // Identity transform
            {
                thumbnailWidth = inputWidth;
                width          = inputWidth;

                thumbnailHeight = pageHeight;
                height          = pageHeight;
            }

            // Note: don't use "image.ThumbnailImage". Otherwise, none of the very fast
            // shrink-on-load tricks are possible. This can make thumbnailing of large
            // images extremely slow.
            image = Image.ThumbnailBuffer(buffer, thumbnailWidth, stringOptions, thumbnailHeight, size,
                                          false, importProfile: importProfile, exportProfile: exportProfile, intent: intent);

            image.WriteToFile("thumbnail.webp", new VOption
            {
                { "strip", true }
            });

            // Or:

            /*buffer = image.WriteToBuffer(".webp", new VOption
             * {
             *  {"strip", true}
             * });*/

            return("See thumbnail.webp");
        }
Example #4
0
        public static (Image Image, ImageType ImageType) OpenInput(InputDescriptor descriptor, string accessMethod)
        {
            descriptor = Guard.NotNull(descriptor, nameof(descriptor));

            Image     image;
            ImageType imageType;

            if (descriptor.Buffer != null)
            {
                if (descriptor.RawChannels > 0)
                {
                    // raw, uncompressed pixel data
                    image = Image.NewFromMemory(descriptor.Buffer, descriptor.RawWidth, descriptor.RawHeight, descriptor.RawChannels, Enums.BandFormat.Uchar);
                    image.Set("interpretation", descriptor.RawChannels < 3 ? Enums.Interpretation.Bw : Enums.Interpretation.Srgb);
                    imageType = ImageType.Raw;
                }
                else
                {
                    // Compressed data
                    imageType = ImageType.FromBuffer(descriptor.Buffer);
                    if (imageType == ImageType.Unknown)
                    {
                        throw new VipsException("Input buffer contains unsupported image format.");
                    }

                    try {
                        var option = new VOption {
                            { "access", accessMethod },
                            { "fail", descriptor.FailOnError }
                        };

                        if (imageType == ImageType.Svg || imageType == ImageType.Pdf)
                        {
                            option.Add("dpi", descriptor.Density);
                        }

                        if (imageType == ImageType.Magick)
                        {
                            option.Add("density", descriptor.Density);
                        }

                        if (imageType.SupportsPages)
                        {
                            option.Add("n", descriptor.Pages);
                            option.Add("page", descriptor.Page);
                        }

                        image = Image.NewFromBuffer(descriptor.Buffer, null, null, null, option);

                        if (imageType == ImageType.Svg || imageType == ImageType.Pdf || imageType == ImageType.Magick)
                        {
                            image.SetDensity(descriptor.Density);
                        }
                    }
                    catch (Exception ex) {
                        throw new VipsException($"Input buffer has corrupt header: {ex.Message}", ex);
                    }
                }
            }
            else
            {
                if (descriptor.CreateChannels > 0)
                {
                    // create new image
                    var background = new List <double> {
                        descriptor.CreateBackground[0],
                        descriptor.CreateBackground[1],
                        descriptor.CreateBackground[2]
                    };

                    if (descriptor.CreateChannels == 4)
                    {
                        background.Add(descriptor.CreateBackground[3]);
                    }

                    image = Image.NewFromArray(background.ToArray());                     // TODO: suspect
                    image.Set("interpretation", Enums.Interpretation.Srgb);
                    imageType = ImageType.Raw;
                }
                else
                {
                    imageType = ImageType.FromFile(descriptor.File !);

                    if (imageType == ImageType.Missing)
                    {
                        throw new VipsException($"Input file {descriptor.File} is missing.");
                    }

                    if (imageType == ImageType.Unknown)
                    {
                        throw new VipsException("Input file contains unsupported image format.");
                    }

                    try {
                        var option = new VOption {
                            { "access", accessMethod },
                            { "fail", descriptor.FailOnError }
                        };

                        if (imageType == ImageType.Svg || imageType == ImageType.Pdf)
                        {
                            option.Add("dpi", descriptor.Density);
                        }

                        if (imageType == ImageType.Magick)
                        {
                            option.Add("density", descriptor.Density);
                        }

                        if (imageType.SupportsPages)
                        {
                            option.Add("n", descriptor.Pages);
                            option.Add("page", descriptor.Page);
                        }

                        image = Image.NewFromFile(descriptor.File, null, null, null, option);
                        if (imageType == ImageType.Svg || imageType == ImageType.Pdf || imageType == ImageType.Magick)
                        {
                            image.SetDensity(descriptor.Density);
                        }
                    }
                    catch (Exception ex) {
                        throw new VipsException($"Input file has corrupt header: {ex.Message}", ex);
                    }
                }
            }

            return(image, imageType);
        }