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