ImageProcessingExtensions Class
In-place processing operations on images and frames.
public static class ImageProcessingExtensionsRemarks
Image-level operations apply to every displayed frame and to the poster frame. Geometry-changing operations (ImageProcessingExtensions.Crop, ImageProcessingExtensions.AutoCrop, ImageProcessingExtensions.Resize, ImageProcessingExtensions.Pad, ImageProcessingExtensions.ExtendCanvas, ImageProcessingExtensions.Rotate, ImageProcessingExtensions.Rotate, ImageProcessingExtensions.Skew, ImageProcessingExtensions.Transform, ImageProcessingExtensions.AutoOrient) build all replacement buffers and metadata before committing them together: on failure or cancellation before the commit, the image is left exactly as it was (dimensions, pixels, frame identities and order, metadata). The old and new buffers are budgeted together. After a successful commit, existing ImageFrame references designate the same logical frames. ImageProcessingExtensions.ConvertColorProfile is transactional in the same way, so that pixels and their color profile always change together.
Pixel-only operations (ImageProcessingExtensions.Flip, ImageProcessingExtensions.Grayscale, ImageProcessingExtensions.Convolve, the blurs, ImageProcessingExtensions.Sharpen, ImageProcessingExtensions.DetectEdges, ImageProcessingExtensions.Equalize, ImageProcessingExtensions.AutoLevels, ImageProcessingExtensions.Threshold, and the effects ImageProcessingExtensions.Vignette, ImageProcessingExtensions.Glow, ImageProcessingExtensions.Pixelate, ImageProcessingExtensions.OilPaint and ImageProcessingExtensions.Flatten) work in place; on failure or cancellation some frames or rows may already be modified, but the image remains structurally valid.
Operations work in stored-pixel coordinates. Except for ImageProcessingExtensions.AutoOrient, they keep ImageMetadata.Orientation unchanged (the typed orientation stays authoritative when EXIF is serialized). Geometry changes update the existing EXIF pixel-dimension tags of ImageMetadata.ExifProfile to the new canvas, and every operation that changes pixels removes the EXIF thumbnail, which no longer matches them. A malformed EXIF profile is left as is (serializing it fails).
A cursor hotspot (FrameMetadata.Hotspot) follows the pixel it designates: crops, auto-crops and paddings translate it, rotations, mirrors and auto-orient permute it exactly, and a resize moves it to floor(x * newWidth / width) (and likewise vertically, through the kept region for ResizeMode.Cover, and then by the padding for ResizeMode.Pad and ResizeMode.BoxPad), so a hotspot in the top-left corner of an image that is not padded stays there; an arbitrary transformation moves it to the pixel that contains the image of its pixel center. When the pixel it designates is not part of the result (a crop, an auto-crop, a cover resize or a transformation that removes it), the operation throws an UnsupportedImageFeatureException and leaves the image unchanged: clear or move the hotspot first. Pixel-only operations keep it.
Crop, auto-crop, rotations, mirrors and auto-orient are exact pixel permutations: every sample, including 16-bit low bits, floating-point samples of any value (not-a-number payloads included) and alpha, is copied unchanged (an auto-crop that enlarges the canvas also writes the detected background color around the copied pixels, as ImageProcessingExtensions.Pad and ImageProcessingExtensions.ExtendCanvas write their padding color). Operations run on the calling thread, except that ImageProcessingExtensions.Resize, the transformations, ImageProcessingExtensions.Convolve, the blurs, the sharpening, the edge detection, ImageProcessingExtensions.Pixelate, ImageProcessingExtensions.OilPaint and ImageProcessingExtensions.Flatten may also use up to ImageConfiguration.MaxDegreeOfParallelism workers for large frames (identical results).
Methods
| Name | Description |
|---|---|
| AnalyzeAutoCrop(Image, AutoCropOptions?, CancellationToken) | Detects the background and the bounding box of the content of the image, without changing it. |
| AnalyzeAutoCrop<TPixel>(Image<TPixel>, AutoCropOptions?, CancellationToken) | Detects the background and the bounding box of the content of the image, without changing it. The background is given as a pixel of the image. See ImageProcessingExtensions.AnalyzeAutoCrop. |
| ApplyColorMatrix(Image, ColorMatrix, CancellationToken) | Gives every pixel of every frame of the image (including the poster frame) the color a matrix makes of its own one, in place: brightness, contrast, saturation, a tint, a negative. The pixel format is kept. |
| ApplyColorMatrix(ImageFrame, ColorMatrix, CancellationToken) | Gives every pixel of one frame the color a matrix makes of its own one, in place. See ImageProcessingExtensions.ApplyColorMatrix. |
| ApplyLut(Image, CubeLut, LutInterpolation, CancellationToken) | Gives a new color to every pixel of every frame of the image (including the poster frame) from a color lookup table read from a .cube file, in place: a color grade or a film look exported by a video or photo tool. Alpha and the pixel format are kept. The EXIF thumbnail, now stale, is removed. |
| ApplyLut(ImageFrame, CubeLut, LutInterpolation, CancellationToken) | Gives a new color to every pixel of one frame from a color lookup table, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.ApplyLut. |
| ApplyToneCurve(Image, ToneCurve, CancellationToken) | Gives a new value to the red, green and blue samples of every frame of the image (including the poster frame) with a tone curve, in place: a gamma correction, a levels adjustment, a curve through control points or a lookup table (see ToneCurve). Alpha and the pixel format are kept. The EXIF thumbnail, now stale, is removed. |
| ApplyToneCurve(ImageFrame, ToneCurve, CancellationToken) | Gives a new value to the red, green and blue samples of one frame with a tone curve, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.ApplyToneCurve. |
| ApplyToneCurves(Image, ToneCurve, ToneCurve, ToneCurve, CancellationToken) | Gives a new value to the red, green and blue samples of every frame of the image (including the poster frame) with a tone curve per channel, in place: the per-channel curves of photo editors, which also correct or create a color cast. Alpha and the pixel format are kept. The EXIF thumbnail, now stale, is removed. |
| ApplyToneCurves(ImageFrame, ToneCurve, ToneCurve, ToneCurve, CancellationToken) | Gives a new value to the red, green and blue samples of one frame with a tone curve per channel, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.ApplyToneCurves. |
| AutoCrop(Image, AutoCropAnalysis, AutoCropOptions?, CancellationToken) | Crops every frame of the image to the content box of an existing analysis, plus the padding of the options, without analyzing the image again. See ImageProcessingExtensions.AutoCrop. |
| AutoCrop(Image, AutoCropOptions?, CancellationToken) | Crops every frame of the image to the bounding box of its content, detected by ImageProcessingExtensions.AnalyzeAutoCrop, plus the padding of the options. |
| AutoLevels(Image, AutoLevelsOptions?, CancellationToken) | Stretches the contrast of every frame of the image (including the poster frame) in place: the levels between two percentiles of the histogram are spread linearly over the whole sample range. The pixel format and alpha are kept. |
| AutoLevels(ImageFrame, AutoLevelsOptions?, CancellationToken) | Stretches the contrast of one frame in place. See ImageProcessingExtensions.AutoLevels. |
| AutoOrient(Image, CancellationToken) | Transforms every frame so that the stored pixels are displayed upright, according to ImageMetadata.Orientation, then sets the orientation to ExifOrientation.TopLeft (an existing EXIF orientation tag is rewritten to 1 as well). All eight EXIF orientations are supported: mirrors (2, 4), rotations (3, 6, 8) and the diagonal reflections (5: transpose, 7: transverse). Does nothing when the orientation is already ExifOrientation.TopLeft. |
| BilateralFilter(Image, int, double, double, ConvolutionEdgeMode, CancellationToken) | Smooths every displayed frame and the poster frame with a bilateral filter, in place: every pixel becomes a weighted mean of the pixels around it, where the weight falls with the distance and with the difference of colors, so noise and texture are smoothed and edges stay sharp. The EXIF thumbnail, now stale, is removed. |
| BilateralFilter(ImageFrame, int, double, double, ConvolutionEdgeMode, CancellationToken) | Smooths one frame with a bilateral filter, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.BilateralFilter. |
| BlackHat(Image, StructuringElement, ConvolutionEdgeMode, CancellationToken) | Replaces the colors of every displayed frame and the poster frame by their black top-hat transform, in place: the difference between the closing of the frame and the frame, which shows the dark details smaller than the element as bright ones, on black (dark text on a page lit unevenly, scratches). Alpha is kept. The EXIF thumbnail, now stale, is removed. |
| BlackHat(ImageFrame, StructuringElement, ConvolutionEdgeMode, CancellationToken) | Replaces the colors of one frame by their black top-hat transform, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.BlackHat. |
| BoxBlur(Image, int, ConvolutionEdgeMode, ConvolutionWorkingSpace, CancellationToken) | Blurs every displayed frame and the poster frame in place with a box blur. The EXIF thumbnail, now stale, is removed. |
| BoxBlur(ImageFrame, int, ConvolutionEdgeMode, ConvolutionWorkingSpace, CancellationToken) | Blurs one frame in place with a box blur. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.BoxBlur. |
| ComputeHistogram(Image, HistogramChannel, CancellationToken) | Counts the pixels of every level of a channel, over every frame of the image (including the poster frame). The image is not changed. |
| ComputeHistogram(ImageFrame, HistogramChannel, CancellationToken) | Counts the pixels of every level of a channel of one frame. See ImageProcessingExtensions.ComputeHistogram. |
| ConvertColorProfile(Image, IccProfile, IccColorTransformOptions?, CancellationToken) | Converts the colors of every frame of the image (including the poster frame) to the color space described by an ICC profile, and labels the image with that profile. |
| Convolve(Image, ConvolutionOptions, CancellationToken) | Applies a convolution matrix to every frame of the image (including the poster frame) in place. |
| Convolve(ImageFrame, ConvolutionOptions, CancellationToken) | Applies a convolution matrix to one frame in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.Convolve. |
| CorrectPerspective(Image, PointD, PointD, PointD, PointD, Size?, TransformOptions?, CancellationToken) | Straightens a quadrilateral of every frame of the image into an upright rectangle that becomes the whole image: a document, a whiteboard or a painting photographed at an angle, seen from the front. The four corners are given in the image, in order around the quadrilateral. |
| Crop(Image, Rectangle, CancellationToken) | Crops every frame of the image to a rectangle. |
| DetectEdges(Image, EdgeDetector, bool, ConvolutionEdgeMode, CancellationToken) | Replaces every displayed frame and the poster frame by its edges, in place: bright where the colors change, black where they are flat. The EXIF thumbnail, now stale, is removed. |
| DetectEdges(ImageFrame, EdgeDetector, bool, ConvolutionEdgeMode, CancellationToken) | Replaces one frame by its edges, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.DetectEdges. |
| Dilate(Image, StructuringElement, ConvolutionEdgeMode, CancellationToken) | Replaces every sample of every displayed frame and the poster frame by the maximum of the same sample of the pixels of a structuring element around its pixel, in place: a grayscale dilation, which grows the bright areas and fills dark details smaller than the element. The EXIF thumbnail, now stale, is removed. |
| Dilate(ImageFrame, StructuringElement, ConvolutionEdgeMode, CancellationToken) | Dilates one frame in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.Dilate. |
| Equalize(Image, HistogramEqualizationOptions?, CancellationToken) | Equalizes the histogram of every frame of the image (including the poster frame) in place, which spreads its levels over the whole sample range: globally, or by tiles with a contrast limit (CLAHE). The pixel format and alpha are kept. |
| Equalize(ImageFrame, HistogramEqualizationOptions?, CancellationToken) | Equalizes the histogram of one frame in place. See ImageProcessingExtensions.Equalize. |
| Erode(Image, StructuringElement, ConvolutionEdgeMode, CancellationToken) | Replaces every sample of every displayed frame and the poster frame by the minimum of the same sample of the pixels of a structuring element around its pixel, in place: a grayscale erosion, which grows the dark areas and removes bright details smaller than the element. The EXIF thumbnail, now stale, is removed. |
| Erode(ImageFrame, StructuringElement, ConvolutionEdgeMode, CancellationToken) | Erodes one frame in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.Erode. |
| ExtendCanvas(Image, Size, ResizeAnchor, Rgba64?, CancellationToken) | Enlarges the canvas of every frame of the image to a given size, and places the image on it at an anchor. |
| Flatten(Image, Rgba64, CancellationToken) | Composites every pixel of every frame of the image (including the poster frame) over an opaque color and makes it opaque, in place, without changing the pixel format: what a conversion to a format without alpha does with PixelConversionOptions.BackgroundColor, but the alpha stays in the pixels, at its maximum. |
| Flatten(ImageFrame, Rgba64, CancellationToken) | Composites every pixel of one frame over an opaque color and makes it opaque, in place, without changing the pixel format. See ImageProcessingExtensions.Flatten. |
| Flip(Image, FlipMode, CancellationToken) | Mirrors every frame of the image (including the poster frame) in place, in stored-pixel coordinates. |
| Flip(ImageFrame, FlipMode, CancellationToken) | Mirrors one frame in place. The EXIF thumbnail of the image, now stale, is removed. |
| GaussianBlur(Image, double, ConvolutionEdgeMode, ConvolutionWorkingSpace, CancellationToken) | Blurs every displayed frame and the poster frame in place with a Gaussian blur. The EXIF thumbnail, now stale, is removed. |
| GaussianBlur(ImageFrame, double, ConvolutionEdgeMode, ConvolutionWorkingSpace, CancellationToken) | Blurs one frame in place with a Gaussian blur. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.GaussianBlur. |
| Glow(Image, Rgba64, double, double, Rectangle?, CancellationToken) | Lights up (or tints) the center of every frame of the image (including the poster frame) with a color that fades out toward the edges, in place. The pixel format and the alpha of the pixels are kept. |
| Glow(ImageFrame, Rgba64, double, double, Rectangle?, CancellationToken) | Lights up (or tints) the center of one frame, in place. See ImageProcessingExtensions.Glow. |
| Grayscale(Image, CancellationToken) | Converts every frame of the image (including the poster frame) to grayscale in place, keeping the pixel format and alpha. Uses Rec. 709 luma coefficients (0.2126, 0.7152, 0.0722) on the encoded sample values, nearest rounding with ties upward, and clamping, at the storage precision: Y = (2126 R + 7152 G + 722 B + 5000) / 10000, stored into R, G and B. Floating-point samples (RgbaFloat, RgbaHalf) get 0.2126 R + 0.7152 G + 0.0722 B of their stored values in double precision, rounded to the nearest sample and not clamped (a sample that is not a number gives a luma that is not a number). Gray formats are left unchanged. The pixel format is kept, so a compatible RGB profile stays. Use Image.CloneAs to obtain Gray8 or Gray16 storage. |
| Grayscale(ImageFrame, CancellationToken) | Converts one frame to grayscale in place, keeping the pixel format and alpha. See ImageProcessingExtensions.Grayscale. |
| GuidedFilter(Image, int, double, ConvolutionEdgeMode, CancellationToken) | Smooths every displayed frame and the poster frame with a guided filter that uses the frame as its own guide, in place: an edge-preserving smoothing that takes a constant time per pixel, whatever the radius. The EXIF thumbnail, now stale, is removed. |
| GuidedFilter(ImageFrame, int, double, ConvolutionEdgeMode, CancellationToken) | Smooths one frame with a guided filter that uses the frame as its own guide, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.GuidedFilter. |
| MedianBlur(Image, int, ConvolutionEdgeMode, CancellationToken) | Replaces every sample of every displayed frame and the poster frame by the median of its neighborhood, in place. The EXIF thumbnail, now stale, is removed. |
| MedianBlur(ImageFrame, int, ConvolutionEdgeMode, CancellationToken) | Replaces every sample of one frame by the median of its neighborhood, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.MedianBlur. |
| MorphologicalClose(Image, StructuringElement, ConvolutionEdgeMode, CancellationToken) | Applies a morphological closing to every displayed frame and the poster frame, in place: a dilation followed by an erosion with the same element, which fills the dark details smaller than the element (holes, gaps, thin dark lines) and keeps the shape and brightness of larger areas. The EXIF thumbnail, now stale, is removed. |
| MorphologicalClose(ImageFrame, StructuringElement, ConvolutionEdgeMode, CancellationToken) | Applies a morphological closing to one frame in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.MorphologicalClose. |
| MorphologicalOpen(Image, StructuringElement, ConvolutionEdgeMode, CancellationToken) | Applies a morphological opening to every displayed frame and the poster frame, in place: an erosion followed by a dilation with the same element, which removes the bright details smaller than the element (specks, thin lines) and keeps the shape and brightness of larger areas. The EXIF thumbnail, now stale, is removed. |
| MorphologicalOpen(ImageFrame, StructuringElement, ConvolutionEdgeMode, CancellationToken) | Applies a morphological opening to one frame in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.MorphologicalOpen. |
| OilPaint(Image, int, int, CancellationToken) | Gives every frame of the image (including the poster frame) the look of an oil painting, in place: flat strokes of color that keep the edges. The pixel format is kept. The EXIF thumbnail, now stale, is removed. |
| OilPaint(ImageFrame, int, int, CancellationToken) | Gives one frame the look of an oil painting, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.OilPaint. |
| Pad(Image, int, int, int, int, Rgba64?, CancellationToken) | Adds a border around every frame of the image: the canvas grows by the given numbers of pixels on each side. |
| PercentileFilter(Image, int, double, ConvolutionEdgeMode, CancellationToken) | Replaces every sample of every displayed frame and the poster frame by a percentile of the same sample of the square around its pixel, in place: a rank filter, which generalizes the median (50), the minimum (0, an erosion by a square) and the maximum (100, a dilation by a square). The EXIF thumbnail, now stale, is removed. |
| PercentileFilter(ImageFrame, int, double, ConvolutionEdgeMode, CancellationToken) | Replaces every sample of one frame by a percentile of its neighborhood, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.PercentileFilter. |
| Pixelate(Image, int, CancellationToken) | Replaces every block of pixels of every frame of the image (including the poster frame) by its mean color, in place: a mosaic of large pixels. The pixel format is kept. The EXIF thumbnail, now stale, is removed. |
| Pixelate(ImageFrame, int, CancellationToken) | Replaces every block of pixels of one frame by its mean color, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.Pixelate. |
| Quantize(Image, QuantizeOptions?, CancellationToken) | Reduces the colors of every frame of the image (including the poster frame) to a palette, in place, so that each frame has at most QuantizeOptions.MaxColors distinct colors, or only colors of QuantizeOptions.Palette. The pixel format is kept. |
| Quantize(ImageFrame, QuantizeOptions?, CancellationToken) | Reduces the colors of one frame to a palette, in place. See ImageProcessingExtensions.Quantize. |
| RadialBlur(Image, RadialBlurOptions, CancellationToken) | Blurs every displayed frame and the poster frame along lines through a center (a zoom blur) or circles around it (a spin blur), in place: the streaks of a zoom or a rotation during the exposure, sharp at the center. The EXIF thumbnail, now stale, is removed. |
| RadialBlur(ImageFrame, RadialBlurOptions, CancellationToken) | Blurs one frame along lines through a center or circles around it, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.RadialBlur. |
| ReplaceColor(Image, Rgba64, Rgba64, double, CancellationToken) | Gives a color to every pixel of every frame of the image (including the poster frame) whose color is within a tolerance of another one, in place: a background color made transparent, a color of a logo changed. The pixel format is kept. |
| ReplaceColor(ImageFrame, Rgba64, Rgba64, double, CancellationToken) | Gives a color to every pixel of one frame whose color is within a tolerance of another one, in place. See ImageProcessingExtensions.ReplaceColor. |
| Resize(Image, ResizeOptions, CancellationToken) | Resizes every frame of the image. |
| Rotate(Image, RotateMode, CancellationToken) | Rotates every frame of the image clockwise by a multiple of 90 degrees (an exact pixel permutation). |
| Rotate(Image, double, TransformOptions?, CancellationToken) | Rotates every frame of the image clockwise by an angle, around its center. |
| Sharpen(Image, double, double, double, ConvolutionEdgeMode, ConvolutionWorkingSpace, CancellationToken) | Sharpens every displayed frame and the poster frame in place with an unsharp mask. The EXIF thumbnail, now stale, is removed. |
| Sharpen(ImageFrame, double, double, double, ConvolutionEdgeMode, ConvolutionWorkingSpace, CancellationToken) | Sharpens one frame in place with an unsharp mask. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.Sharpen. |
| Skew(Image, double, double, TransformOptions?, CancellationToken) | Skews every frame of the image around its center: its vertical lines lean by one angle and its horizontal lines by another one. |
| SuggestCrop(Image, int, int, CropSuggestionOptions?, CancellationToken) | Suggests where to crop the image to an aspect ratio while keeping its content: the rectangle of the ratio, as large as the image allows (or scaled by CropSuggestionOptions.Scale), that holds the most detail or the most salient colors of every displayed frame and the poster frame. Nothing is changed: pass the rectangle to ImageProcessingExtensions.Crop. |
| SuggestCrop(ImageFrame, int, int, CropSuggestionOptions?, CancellationToken) | Suggests where to crop one frame to an aspect ratio while keeping its content. See ImageProcessingExtensions.SuggestCrop. |
| Threshold(Image, ThresholdOptions?, CancellationToken) | Binarizes every frame of the image (including the poster frame) in place: each pixel becomes ThresholdOptions.UpperColor (white by default) when its luminance is greater than its threshold, and ThresholdOptions.LowerColor (black by default) otherwise. The pixel format is kept. |
| Threshold(ImageFrame, ThresholdOptions?, CancellationToken) | Binarizes one frame in place. See ImageProcessingExtensions.Threshold. |
| TopHat(Image, StructuringElement, ConvolutionEdgeMode, CancellationToken) | Replaces the colors of every displayed frame and the poster frame by their white top-hat transform, in place: the difference between the frame and its opening, which keeps only the bright details smaller than the element, on black. It extracts small bright features from an uneven background (text on a page lit unevenly, stars, cells). Alpha is kept. The EXIF thumbnail, now stale, is removed. |
| TopHat(ImageFrame, StructuringElement, ConvolutionEdgeMode, CancellationToken) | Replaces the colors of one frame by their white top-hat transform, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.TopHat. |
| Transform(Image, AffineTransform, TransformOptions?, CancellationToken) | Transforms every frame of the image with an affine transformation: any combination of translations, scalings, rotations and skews. |
| Transform(Image, ProjectiveTransform, TransformOptions?, CancellationToken) | Transforms every frame of the image with a projective transformation: the image seen in perspective. |
| Vignette(Image, Rgba64, double, double, Rectangle?, CancellationToken) | Darkens (or tints) the edges of every frame of the image (including the poster frame) toward a color, in place: the corners of an old lens. The pixel format and the alpha of the pixels are kept. |
| Vignette(ImageFrame, Rgba64, double, double, Rectangle?, CancellationToken) | Darkens (or tints) the edges of one frame toward a color, in place. See ImageProcessingExtensions.Vignette. |
AnalyzeAutoCrop overloads
AnalyzeAutoCrop(Image, AutoCropOptions?, CancellationToken)
ImageProcessingExtensions.csDetects the background and the bounding box of the content of the image, without changing it.
public static AutoCropAnalysis AnalyzeAutoCrop(this Image image, AutoCropOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to analyze.
optionsAutoCropOptions?- The options, or
nullforAutoCropOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Returns
AutoCropAnalysis The analysis, an AutoCropAnalysis<TPixel> of the pixel type of the image. AutoCropAnalysis.Success is false when no border or no content of at least 3x3 pixels is found, for example for a uniform image.
Exceptions
UnsupportedImageFeatureException- A floating-point sample is not a number or is infinite.
OperationCanceledException- The operation was canceled.
InvalidOperationException- A pixel lease is active on a frame.
ObjectDisposedException- The image is disposed.
Remarks
The analysis reads every displayed frame and the poster frame, in stored-pixel coordinates (call ImageProcessingExtensions.AutoOrient first to work on the displayed orientation), at the storage precision; thresholds are on the 8-bit scale and are multiplied by 257 for 16-bit samples. A fully transparent pixel is read as transparent black: hidden colors never count.
Floating-point samples (RgbaFloat, RgbaHalf) are analyzed as they are stored, in double precision and without clipping, so values above 1 and below 0 count as they are: the reduction to 8 bits of the first step is the nearest point of the 8-bit grid, floor(255 v + 1/2), which can be outside [0, 255]; the luma bucket is that of the luma of that point divided by 255, and is 0 below 0 and 10 above 1; and the thresholds are divided by 255 (the differences are those of the samples). A sample that is not a number or is infinite has no distance to the background: the analysis rejects it. The background of the analysis is the border pixel as stored (AutoCropAnalysis<TPixel>.BackgroundColor).
- The pixels of the one-pixel outer border of every frame are tallied by color, after reduction to 8 bits, in frame order and row by row. At most
AutoCropOptions.ColorThresholddistinct colors are tracked; later ones are ignored. The background is the first pixel seen of the most frequent tracked color (the first tracked among equals). - A border is found when fewer than
AutoCropOptions.ColorThresholddistinct colors were seen, or whenAutoCropOptions.BucketThresholdis set and at least that share of the border pixels falls in the luma bucket of the background:min(10, Y * 11 / 255), whereYis the 8-bit Rec. 709 luma of the color flattened onto white. - Otherwise the first two steps are retried once with half the threshold (rounded up) and without the bucket test, on the canvas without 1/20 of its width and height on each side (rounded down). When the retry finds a border, the halved threshold and the smaller rectangle are used for the next step.
- A pixel is background when
2126 |dR| + 7152 |dG| + 722 |dB| <= threshold * 10000and|dA| < threshold, where the differences are taken from the background color. The content box is the bounding box, over all frames, of the other pixels of the rectangle. The analysis succeeds when the box is at least 3 pixels wide and high. - With
AutoCropOptions.AnalyzeWeights, the weights are the mean over all pixels of all frames ofp * d, wherepis the position of the pixel center relative to the canvas center, from -1 to 1, anddis the color difference above divided by its maximum and multiplied by alpha, from 0 to 1.
A threshold of 1 cannot find a border without AutoCropOptions.BucketThreshold, since a border always has at least one color. The paddings and AutoCropOptions.PaddingMode are not used by the analysis.
AnalyzeAutoCrop<TPixel>(Image<TPixel>, AutoCropOptions?, CancellationToken)
ImageProcessingExtensions.csDetects the background and the bounding box of the content of the image, without changing it. The background is given as a pixel of the image. See ImageProcessingExtensions.AnalyzeAutoCrop.
public static AutoCropAnalysis<TPixel> AnalyzeAutoCrop<TPixel>(this Image<TPixel> image, AutoCropOptions? options = null, CancellationToken cancellationToken = default) where TPixel : unmanagedType parameters
TPixel- The pixel type.
Parameters
imageImage<TPixel>- The image to analyze.
optionsAutoCropOptions?- The options, or
nullforAutoCropOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Returns
AutoCropAnalysis<TPixel> The analysis.
Exceptions
UnsupportedImageFeatureException- A floating-point sample is not a number or is infinite.
OperationCanceledException- The operation was canceled.
InvalidOperationException- A pixel lease is active on a frame.
ObjectDisposedException- The image is disposed.
ApplyColorMatrix overloads
ApplyColorMatrix(Image, ColorMatrix, CancellationToken)
ImageProcessingExtensions.csGives every pixel of every frame of the image (including the poster frame) the color a matrix makes of its own one, in place: brightness, contrast, saturation, a tint, a negative. The pixel format is kept.
public static void ApplyColorMatrix(this Image image, ColorMatrix matrix, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
matrixColorMatrix- The matrix.
cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageormatrixisnull.InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working storage would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The matrix is applied to the stored (encoded) sample values, with straight alpha, at the storage precision: see ColorMatrix for the arithmetic. A pixel format without alpha gets the color of the result over black, and a grayscale format the Rec. 709 luma of the result. Every pixel gets the samples the matrix gives it, the color of a fully transparent pixel included, as ImageProcessingExtensions.Grayscale does: with ColorMatrix.CreateGrayscale, the pixels are the same, bit for bit. No color profile is applied: the colors of the matrix are those of the color space of the image.
The working storage (one row) is charged to the image and rented before a pixel changes. On cancellation, some rows may already be converted, the same ones in every frame. To change the colors of a part of an image, or of a drawing, see DrawingCanvas.FilterBackdrop and DrawingCanvas.Filter.
ApplyColorMatrix(ImageFrame, ColorMatrix, CancellationToken)
ImageProcessingExtensions.csGives every pixel of one frame the color a matrix makes of its own one, in place. See ImageProcessingExtensions.ApplyColorMatrix.
public static void ApplyColorMatrix(this ImageFrame frame, ColorMatrix matrix, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
matrixColorMatrix- The matrix.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be converted.
Exceptions
ArgumentNullExceptionframeormatrixisnull.InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working storage would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
ApplyLut overloads
ApplyLut(Image, CubeLut, LutInterpolation, CancellationToken)
ImageProcessingExtensions.Adjustments.csGives a new color to every pixel of every frame of the image (including the poster frame) from a color lookup table read from a .cube file, in place: a color grade or a film look exported by a video or photo tool. Alpha and the pixel format are kept. The EXIF thumbnail, now stale, is removed.
public static void ApplyLut(this Image image, CubeLut lut, LutInterpolation interpolation = LutInterpolation.Tetrahedral, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
lutCubeLut- The table.
interpolationLutInterpolation- The interpolation of a three-dimensional table.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be changed.
Exceptions
ArgumentNullExceptionimageorlutisnull.ArgumentOutOfRangeExceptioninterpolationis not a defined value.InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The table maps the stored (encoded) colors as fractions of the largest sample value, which is what such tables expect from encoded images (an sRGB photo, or video in the color space the table was made for): no color profile is applied. A three-dimensional table gives each color a new one, interpolated between the points of its lattice as interpolation says; a one-dimensional table maps each channel on its own, interpolated linearly (interpolation does not apply). An input value is clamped to the domain of the table first. With LutInterpolation.Tetrahedral or LutInterpolation.Trilinear, the result is the one of FFmpeg's lut3d filter with the same interpolation, except that the table is read in single precision and interpolated in double precision.
Integer samples are rounded to the nearest level (ties upward) and clamped to the sample range. A gray pixel is mapped as the color of three equal samples and stores the Rec. 709 luma of the result; an alpha mask (A8) is left unchanged. Floating-point samples are mapped as stored, clamped to the domain on input, and the output of the table is stored without clamping; a pixel with a color sample that is not a number gets three of them.
A three-dimensional table is evaluated for every pixel, and a one-dimensional one, like the table of a gray format, once per level. The working memory (a row, and the tables of the levels, at most 384 KiB) is charged to the image and rented before a pixel changes. On cancellation, some frames or rows may already be changed.
Example
[Fact]
public void CubeLut_Apply()
{
// A three-dimensional table of 2 x 2 x 2 points that inverts the colors, as a .cube file holds it
var lut = CubeLut.Parse("""
TITLE "Negative"
LUT_3D_SIZE 2
1 1 1
0 1 1
1 0 1
0 0 1
1 1 0
0 1 0
1 0 0
0 0 0
""");
using var image = new Image<Rgba32>(1, 1, new Rgba32(255, 64, 0, 128));
image.ApplyLut(lut);
Assert.Equal("Negative", lut.Title);
Assert.Equal(new Rgba32(0, 191, 255, 128), image.Frames[0][0, 0]);
}ApplyLut(ImageFrame, CubeLut, LutInterpolation, CancellationToken)
ImageProcessingExtensions.Adjustments.csGives a new color to every pixel of one frame from a color lookup table, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.ApplyLut.
public static void ApplyLut(this ImageFrame frame, CubeLut lut, LutInterpolation interpolation = LutInterpolation.Tetrahedral, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
lutCubeLut- The table.
interpolationLutInterpolation- The interpolation of a three-dimensional table.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be changed.
Exceptions
ArgumentNullExceptionframeorlutisnull.ArgumentOutOfRangeExceptioninterpolationis not a defined value.InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
ApplyToneCurve overloads
ApplyToneCurve(Image, ToneCurve, CancellationToken)
ImageProcessingExtensions.Adjustments.csGives a new value to the red, green and blue samples of every frame of the image (including the poster frame) with a tone curve, in place: a gamma correction, a levels adjustment, a curve through control points or a lookup table (see ToneCurve). Alpha and the pixel format are kept. The EXIF thumbnail, now stale, is removed.
public static void ApplyToneCurve(this Image image, ToneCurve curve, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
curveToneCurve- The curve of the three color channels.
cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageorcurveisnull.InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
Each sample v becomes curve.Evaluate(v / max) * max, where max is the largest sample value: the curve maps the stored (encoded) values, as photo editors do, and no color profile is applied. Integer samples are mapped at the storage precision, through a table of every level (256 for 8-bit formats, 65,536 for 16-bit ones), rounded to the nearest level (ties upward) and clamped to the sample range. The colors are straight (not premultiplied), so the hidden color of a transparent pixel is mapped too. Gray formats map their gray level, and an alpha mask (A8) is left unchanged.
Floating-point samples (RgbaFloat, RgbaHalf) are mapped as stored and stored without clamping: the curve decides what happens outside [0, 1] (a gamma keeps the highlights above 1, the levels and the curves through points clip them, see ToneCurve), and a sample that is not a number stays one.
The working memory (a row, and the tables of the levels, at most 384 KiB) is charged to the image and rented before a pixel changes. ToneCurve.Identity changes nothing. On cancellation, some frames or rows may already be changed.
Example
[Fact]
public void ToneCurve_Levels()
{
using var image = new Image<Rgb24>(2, 1);
image.Frames[0][0, 0] = new Rgb24(64, 128, 192);
image.Frames[0][1, 0] = new Rgb24(10, 240, 255);
// Clip the darkest and the brightest 10% of the levels and brighten the midtones, then add contrast with an
// S curve through control points
var levels = ToneCurve.CreateLevels(inputBlack: 0.1, inputWhite: 0.9, gamma: 1.2);
var contrast = ToneCurve.CreateFromPoints(new PointD(0, 0), new PointD(0.25, 0.2), new PointD(0.75, 0.8), new PointD(1, 1));
image.ApplyToneCurve(levels.Then(contrast));
Assert.Equal(new Rgb24(51, 149, 225), image.Frames[0][0, 0]);
Assert.Equal(new Rgb24(0, 255, 255), image.Frames[0][1, 0]);
}ApplyToneCurve(ImageFrame, ToneCurve, CancellationToken)
ImageProcessingExtensions.Adjustments.csGives a new value to the red, green and blue samples of one frame with a tone curve, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.ApplyToneCurve.
public static void ApplyToneCurve(this ImageFrame frame, ToneCurve curve, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
curveToneCurve- The curve of the three color channels.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be changed.
Exceptions
ArgumentNullExceptionframeorcurveisnull.InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
ApplyToneCurves overloads
ApplyToneCurves(Image, ToneCurve, ToneCurve, ToneCurve, CancellationToken)
ImageProcessingExtensions.Adjustments.csGives a new value to the red, green and blue samples of every frame of the image (including the poster frame) with a tone curve per channel, in place: the per-channel curves of photo editors, which also correct or create a color cast. Alpha and the pixel format are kept. The EXIF thumbnail, now stale, is removed.
public static void ApplyToneCurves(this Image image, ToneCurve red, ToneCurve green, ToneCurve blue, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
redToneCurve- The curve of the red channel.
greenToneCurve- The curve of the green channel.
blueToneCurve- The curve of the blue channel.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be changed.
Exceptions
ArgumentNullExceptionimage,red,greenorblueisnull.InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
Every color sample is mapped by the curve of its channel, as ImageProcessingExtensions.ApplyToneCurve describes. A gray pixel is mapped as the color of three equal samples, and stores the Rec. 709 luma of the result, as ImageProcessingExtensions.Grayscale computes it: equal curves give the gray level of the curve.
ApplyToneCurves(ImageFrame, ToneCurve, ToneCurve, ToneCurve, CancellationToken)
ImageProcessingExtensions.Adjustments.csGives a new value to the red, green and blue samples of one frame with a tone curve per channel, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.ApplyToneCurves.
public static void ApplyToneCurves(this ImageFrame frame, ToneCurve red, ToneCurve green, ToneCurve blue, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
redToneCurve- The curve of the red channel.
greenToneCurve- The curve of the green channel.
blueToneCurve- The curve of the blue channel.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be changed.
Exceptions
ArgumentNullExceptionframe,red,greenorblueisnull.InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
AutoCrop overloads
AutoCrop(Image, AutoCropAnalysis, AutoCropOptions?, CancellationToken)
ImageProcessingExtensions.csCrops every frame of the image to the content box of an existing analysis, plus the padding of the options, without analyzing the image again. See ImageProcessingExtensions.AutoCrop.
public static bool AutoCrop(this Image image, AutoCropAnalysis analysis, AutoCropOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
analysisAutoCropAnalysis- The analysis to apply. The image is left unchanged when
AutoCropAnalysis.Successisfalse. optionsAutoCropOptions?- The options, or
nullforAutoCropOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Returns
bool true if the image was cropped or enlarged; false if it is unchanged.
Exceptions
ArgumentExceptionAutoCropAnalysis.CanvasSizeis not the size of the image.UnsupportedImageFeatureException- The canvas must be enlarged but
AutoCropAnalysis.BackgroundColoris not exactly representable in the pixel format of the image (it comes from an image of another pixel format, or from an image of floating-point pixels of another pixel type, whose background is exact in its own type only), or the cursor hotspot of a frame designates a pixel that the crop removes. The image is unchanged. ImageResourceLimitException- The enlarged canvas exceeds
ImageResourceLimits.MaxWidth,ImageResourceLimits.MaxHeightorImageResourceLimits.MaxFramePixels, or the replacement buffers would exceed the allocation limit. The image is unchanged. OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
The analysis may come from another image of the same canvas size, for example a clone processed differently. Only the paddings and AutoCropOptions.PaddingMode of the options are used.
AutoCrop(Image, AutoCropOptions?, CancellationToken)
ImageProcessingExtensions.csCrops every frame of the image to the bounding box of its content, detected by ImageProcessingExtensions.AnalyzeAutoCrop, plus the padding of the options.
public static bool AutoCrop(this Image image, AutoCropOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
optionsAutoCropOptions?- The options, or
nullforAutoCropOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Returns
bool true if the image was cropped or enlarged; false if it is unchanged.
Exceptions
UnsupportedImageFeatureException- The cursor hotspot of a frame designates a pixel that the crop removes, or a floating-point sample is not a number or is infinite. The image is unchanged.
ImageResourceLimitException- The enlarged canvas exceeds
ImageResourceLimits.MaxWidth,ImageResourceLimits.MaxHeightorImageResourceLimits.MaxFramePixels, or the replacement buffers would exceed the allocation limit. The image is unchanged. OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
The kept rectangle is the content box extended by AutoCropOptions.PaddingX pixels on the left and on the right and by AutoCropOptions.PaddingY pixels above and below, then moved by padding * weight pixels (truncated toward zero) on each axis when AutoCropOptions.AnalyzeWeights is set. Padding inside the canvas keeps the original pixels.
When the rectangle reaches outside the canvas, AutoCropPaddingMode.Contain clamps it to the canvas, and AutoCropPaddingMode.Expand enlarges the canvas: the pixels outside the original canvas get the detected background color in every frame. The image is left unchanged when the analysis does not succeed or when the rectangle is the whole canvas.
AutoLevels overloads
AutoLevels(Image, AutoLevelsOptions?, CancellationToken)
ImageProcessingExtensions.csStretches the contrast of every frame of the image (including the poster frame) in place: the levels between two percentiles of the histogram are spread linearly over the whole sample range. The pixel format and alpha are kept.
public static void AutoLevels(this Image image, AutoLevelsOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
optionsAutoLevelsOptions?- The options, or
nullforAutoLevelsOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentExceptionAutoLevelsOptions.LowPercentileis not less thanAutoLevelsOptions.HighPercentile.UnsupportedImageFeatureException- The pixel format is a floating-point one. Nothing is changed.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
See AutoLevelsOptions for the mapping and HistogramColorMode for the samples it remaps: by default, the luminance, so that the hues do not shift. The mapping works on the stored (encoded) sample values at the storage precision, with 256 levels for 8-bit pixel formats and 65,536 for 16-bit ones. No color profile is applied. Fully transparent pixels are not counted. Floating-point pixel formats have no discrete levels: convert the image to Rgba64 with Image.CloneAs first.
Each frame is stretched alone by default; AutoLevelsOptions.ShareHistogramAcrossFrames gives every frame the levels of their combined histograms, so that an animation does not flicker. The working memory is charged to the image and rented before a pixel changes. On failure or cancellation, some frames or rows may already be remapped.
AutoLevels(ImageFrame, AutoLevelsOptions?, CancellationToken)
ImageProcessingExtensions.csStretches the contrast of one frame in place. See ImageProcessingExtensions.AutoLevels.
public static void AutoLevels(this ImageFrame frame, AutoLevelsOptions? options = null, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
optionsAutoLevelsOptions?- The options, or
nullforAutoLevelsOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be remapped.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentExceptionAutoLevelsOptions.LowPercentileis not less thanAutoLevelsOptions.HighPercentile.UnsupportedImageFeatureException- The pixel format is a floating-point one. Nothing is changed.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
AutoOrient(Image, CancellationToken)
ImageProcessingExtensions.csTransforms every frame so that the stored pixels are displayed upright, according to ImageMetadata.Orientation, then sets the orientation to ExifOrientation.TopLeft (an existing EXIF orientation tag is rewritten to 1 as well). All eight EXIF orientations are supported: mirrors (2, 4), rotations (3, 6, 8) and the diagonal reflections (5: transpose, 7: transverse). Does nothing when the orientation is already ExifOrientation.TopLeft.
public static void AutoOrient(this Image image, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ImageResourceLimitException- The reoriented canvas exceeds
ImageResourceLimits.MaxWidthorImageResourceLimits.MaxHeight, or the replacement buffers would exceed the allocation limit. The image is unchanged. OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
BilateralFilter overloads
BilateralFilter(Image, int, double, double, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Smoothing.csSmooths every displayed frame and the poster frame with a bilateral filter, in place: every pixel becomes a weighted mean of the pixels around it, where the weight falls with the distance and with the difference of colors, so noise and texture are smoothed and edges stay sharp. The EXIF thumbnail, now stale, is removed.
public static void BilateralFilter(this Image image, int radius, double spatialSigma, double rangeSigma, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
radiusint- The radius of the disk of neighbors, in pixels. Must be between 0 and 100; 0 changes nothing.
spatialSigmadouble- The standard deviation of the spatial weights, in pixels. Must be positive and finite; about half the radius.
rangeSigmadouble- The standard deviation of the range weights, as a fraction of the sample range. Must be positive and finite.
edgeModeConvolutionEdgeMode- The pixels the filter reads beyond the edges of the image.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be filtered.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentOutOfRangeExceptionradiusis negative or exceeds 100,spatialSigmaorrangeSigmais not positive and finite, oredgeModeis not a defined value.ImageResourceLimitException- The working copy would exceed a limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The neighbors are the pixels of the disk of radius around the pixel (dx² + dy² ≤ radius²). A neighbor weighs exp(-(dx² + dy²) / (2 spatialSigma²)) × exp(-δ² / (2 rangeSigma²)), where δ is the difference between the two pixels: the root mean square of the differences of their color samples, as fractions of the sample range, with the difference of their alphas added in quadrature. A rangeSigma of 0.1 smooths away differences of about 25 levels of 255 and keeps larger ones. The range weights are read from a table (a relative error below 2e-6), and are 0 for δ beyond 8 rangeSigma.
For a gray image this is OpenCV's cv2.bilateralFilter(src, 2 radius + 1, rangeSigma × 255, spatialSigma) (on 8-bit samples; 65,535 for 16-bit ones, 1 for floating-point ones). For colors, OpenCV adds the absolute differences of the three samples instead: its range sigma is about rangeSigma × 255 × √3 for equal differences. Colors are filtered premultiplied by alpha and alpha is filtered like them, so the hidden color of a transparent pixel does not spread. The samples are filtered as stored (gamma-encoded); 16-bit samples keep their precision, and floating-point samples are not clipped. A sample that is not a number gets no weight in its neighbors, and stays so.
The time per pixel grows with the area of the disk. The frames are copied as single-precision working samples (4 bytes per sample), charged to the image and rented before any pixel changes. Frames of at least 65,536 pixels are split between up to ImageConfiguration.MaxDegreeOfParallelism workers, and the result does not depend on their number.
Example
[Fact]
public void BilateralFilter_SmoothNoiseKeepEdges()
{
// A dark and a bright half, both with a little noise
using var image = new Image<Gray8>(32, 16);
for (var y = 0; y < 16; y++)
{
for (var x = 0; x < 32; x++)
{
var noise = ((x * 7) + (y * 13)) % 5 * 2;
image.Frames[0][x, y] = new Gray8((byte)((x < 16 ? 40 : 200) + noise));
}
}
// Differences of about 10 levels of 255 are smoothed, the step of 160 levels is kept
image.BilateralFilter(radius: 3, spatialSigma: 2, rangeSigma: 0.1);
Assert.InRange(image.Frames[0][5, 8].Value, 42, 46);
Assert.InRange(image.Frames[0][15, 8].Value, 42, 46);
Assert.InRange(image.Frames[0][16, 8].Value, 202, 206);
}BilateralFilter(ImageFrame, int, double, double, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Smoothing.csSmooths one frame with a bilateral filter, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.BilateralFilter.
public static void BilateralFilter(this ImageFrame frame, int radius, double spatialSigma, double rangeSigma, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
radiusint- The radius of the disk of neighbors, in pixels. Must be between 0 and 100; 0 changes nothing.
spatialSigmadouble- The standard deviation of the spatial weights, in pixels. Must be positive and finite.
rangeSigmadouble- The standard deviation of the range weights, as a fraction of the sample range. Must be positive and finite.
edgeModeConvolutionEdgeMode- The pixels the filter reads beyond the edges of the frame.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be filtered.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentOutOfRangeExceptionradiusis negative or exceeds 100,spatialSigmaorrangeSigmais not positive and finite, oredgeModeis not a defined value.ImageResourceLimitException- The working copy would exceed a limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
BlackHat overloads
BlackHat(Image, StructuringElement, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csReplaces the colors of every displayed frame and the poster frame by their black top-hat transform, in place: the difference between the closing of the frame and the frame, which shows the dark details smaller than the element as bright ones, on black (dark text on a page lit unevenly, scratches). Alpha is kept. The EXIF thumbnail, now stale, is removed.
public static void BlackHat(this Image image, StructuringElement element, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
elementStructuringElement- The neighborhood of each pixel: larger than the details to keep.
edgeModeConvolutionEdgeMode- The pixels the filters read beyond the edges of the image.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be changed.
Exceptions
ArgumentNullExceptionimageorelementisnull.ArgumentOutOfRangeExceptionedgeModeis not a defined value.NotSupportedException- The pixel format is
A8, which has no color. Nothing is changed. ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
Every color sample becomes closing - sample, where the closing is the one of ImageProcessingExtensions.MorphologicalClose: the result of OpenCV's cv2.morphologyEx(MORPH_BLACKHAT) for the colors. See ImageProcessingExtensions.TopHat for the differences, alpha and the scratch storage.
BlackHat(ImageFrame, StructuringElement, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csReplaces the colors of one frame by their black top-hat transform, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.BlackHat.
public static void BlackHat(this ImageFrame frame, StructuringElement element, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
elementStructuringElement- The neighborhood of each pixel: larger than the details to keep.
edgeModeConvolutionEdgeMode- The pixels the filters read beyond the edges of the frame.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be changed.
Exceptions
ArgumentNullExceptionframeorelementisnull.ArgumentOutOfRangeExceptionedgeModeis not a defined value.NotSupportedException- The pixel format is
A8, which has no color. Nothing is changed. ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
BoxBlur overloads
BoxBlur(Image, int, ConvolutionEdgeMode, ConvolutionWorkingSpace, CancellationToken)
ImageProcessingExtensions.csBlurs every displayed frame and the poster frame in place with a box blur. The EXIF thumbnail, now stale, is removed.
public static void BoxBlur(this Image image, int radius, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, ConvolutionWorkingSpace workingSpace = ConvolutionWorkingSpace.Encoded, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
radiusint- The number of pixels averaged on each side of a pixel. Must be between 0 and 10000.
edgeModeConvolutionEdgeMode- The pixels the blur reads beyond the edges of the image.
workingSpaceConvolutionWorkingSpace- The numeric space the samples are filtered in.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be blurred.
Exceptions
ArgumentOutOfRangeExceptionradiusis negative or exceeds 10000, oredgeModeorworkingSpaceis not a defined value.UnsupportedImageFeatureExceptionConvolutionWorkingSpace.LinearSrgbis requested for an image with an incompatible ICC profile, or for floating-point samples outside [0, 1] that are not labeled as linear light. Nothing is changed.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
Each sample becomes the mean of the same sample of the (2 radius + 1)^2 pixels of the square centered on its pixel: the convolution by a matrix whose weights are all 1 / (2 radius + 1)^2, which is what cv2.blur and cv2.boxFilter of OpenCV compute. Pixels read beyond the edges are chosen by edgeMode.
The time per pixel does not depend on the radius while the square fits in the frame: the sums of the rows of the square, then of its columns, are computed by blocks of 2 radius + 1 values, three additions per sample whatever their number, without subtractions (a sample that is not a number or an infinity only reaches the pixels whose square contains it), and the sum of the square is divided once and rounded once at the storage precision. A larger square also adds the pixels that the edge mode repeats beyond the frame, one by one, which costs each row and each column a time proportional to the radius (not to its square: each row of a frame no taller than the radius is summed once, however many times the edge mode repeats it). It follows the rules of a convolution (colors filtered premultiplied by alpha, the same result whatever the number of workers); an opaque frame is blurred as its colors alone and keeps the maximum alpha, except with ConvolutionEdgeMode.Zero, which reads transparent pixels beyond the frame. The scratch storage (about three times the radius rows of double-precision samples per worker) is charged to the image allocation scope; a frame no taller than the radius needs less. With a radius of 0, nothing changes.
BoxBlur(ImageFrame, int, ConvolutionEdgeMode, ConvolutionWorkingSpace, CancellationToken)
ImageProcessingExtensions.csBlurs one frame in place with a box blur. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.BoxBlur.
public static void BoxBlur(this ImageFrame frame, int radius, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, ConvolutionWorkingSpace workingSpace = ConvolutionWorkingSpace.Encoded, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
radiusint- The number of pixels averaged on each side of a pixel. Must be between 0 and 10000.
edgeModeConvolutionEdgeMode- The pixels the blur reads beyond the edges of the frame.
workingSpaceConvolutionWorkingSpace- The numeric space the samples are filtered in.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be blurred.
Exceptions
ArgumentOutOfRangeExceptionradiusis negative or exceeds 10000, oredgeModeorworkingSpaceis not a defined value.UnsupportedImageFeatureExceptionConvolutionWorkingSpace.LinearSrgbis requested for an image with an incompatible ICC profile, or for floating-point samples outside [0, 1] that are not labeled as linear light. Nothing is changed.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
ComputeHistogram overloads
ComputeHistogram(Image, HistogramChannel, CancellationToken)
ImageProcessingExtensions.csCounts the pixels of every level of a channel, over every frame of the image (including the poster frame). The image is not changed.
public static ImageHistogram ComputeHistogram(this Image image, HistogramChannel channel, CancellationToken cancellationToken = default)Parameters
imageImage- The image.
channelHistogramChannel- The channel to count.
cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Returns
ImageHistogram The histogram.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentOutOfRangeExceptionchannelis not a definedHistogramChannel.UnsupportedImageFeatureException- The pixel format is a floating-point one.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working storage would exceed the allocation limit.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The levels are the stored (encoded) sample values, at the storage precision: 256 bins for 8-bit pixel formats, 65,536 for 16-bit ones (see ImageHistogram). No color profile is applied. Floating-point pixel formats have no discrete levels: convert the image to Rgba64 with Image.CloneAs first. The working storage (one row) is charged to the image.
ComputeHistogram(ImageFrame, HistogramChannel, CancellationToken)
ImageProcessingExtensions.csCounts the pixels of every level of a channel of one frame. See ImageProcessingExtensions.ComputeHistogram.
public static ImageHistogram ComputeHistogram(this ImageFrame frame, HistogramChannel channel, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame.
channelHistogramChannel- The channel to count.
cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Returns
ImageHistogram The histogram.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentOutOfRangeExceptionchannelis not a definedHistogramChannel.UnsupportedImageFeatureException- The pixel format is a floating-point one.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working storage would exceed the allocation limit.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
ConvertColorProfile(Image, IccProfile, IccColorTransformOptions?, CancellationToken)
ImageProcessingExtensions.csConverts the colors of every frame of the image (including the poster frame) to the color space described by an ICC profile, and labels the image with that profile.
public static void ConvertColorProfile(this Image image, IccProfile destinationProfile, IccColorTransformOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
destinationProfileIccProfile- The profile of the converted pixels.
optionsIccColorTransformOptions?- The conversion options, or
nullforIccColorTransformOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageordestinationProfileisnull.UnsupportedImageFeatureException- The current or the destination profile cannot label the pixel format, the image has both a profile and the linear transfer function label, a profile is of a kind that is not supported, the CICP color description of an image without profile has reserved color primaries or transfer characteristics, or the samples are high dynamic range ones and
optionshas noIccColorTransformOptions.ToneMapping, or a floating-point color sample is outside [0, 1] or is not a number. The image is unchanged. InvalidImageContentException- The current or the destination profile is malformed. The image is unchanged.
ImageResourceLimitException- The replacement buffers would exceed the allocation limit. The image is unchanged.
OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
The source color space is the one of ImageMetadata.IccProfile. An image without profile is sRGB, or sGray for grayscale pixel formats (IccProfile.Srgb, IccProfile.SrgbGray); when ImageMetadata.TransferFunction is ColorTransferFunction.Linear, it is linear light with the sRGB primaries and white point. This is the only operation that applies a color profile: loading, saving, pixel format conversion and the other processing operations never do.
An image without profile whose CICP color description (ImageMetadata.Cicp) is not equivalent to sRGB is converted from the color space of that description: the samples are decoded with the function of its transfer characteristics (Rec. ITU-T H.273, table 3; unspecified ones are sRGB), and its color primaries (table 2; unspecified ones are those of BT.709) are adapted to the white of the profile connection space with the linear Bradford transform. Its matrix coefficients and its range describe how a file stored the samples and play no part. High dynamic range samples (PQ and HLG) are converted only when IccColorTransformOptions.ToneMapping says how their highlights are compressed (HdrToneMappingOptions). After the conversion, a description that is not equivalent to sRGB, ImageMetadata.ContentLightLevel and ImageMetadata.MasteringDisplay are removed: the profile describes the pixels.
The pixel format is kept, so the destination profile must be able to label it: an RGB profile for color formats, a grayscale profile for Gray8 and Gray16. To change the color model, convert the pixel format with Image.CloneAs, or convert sample buffers with IccColorTransform (the only way to reach CMYK).
Colors are converted at the storage precision (16-bit formats are never reduced to 8 bits) by the scalar reference conversion, on the calling thread. Alpha is copied unchanged and the color of transparent pixels is converted like any other. Colors outside the destination gamut are clipped per channel.
Floating-point samples (RgbaFloat, RgbaHalf) are read as they are and the results are stored as the nearest Single or Half, without reduction to 16 bits. A profile and a CICP color description encode values in [0, 1]: a color sample outside that range, or that is not a number, is rejected before anything changes (bring the samples into range first, for example with the tone mapping of PixelConversionOptions.ToneMapping). Alpha is copied unchanged, whatever its value.
The operation is transactional: the converted pixels are built in new buffers, budgeted together with the current ones, and published with the new profile. On failure or cancellation the image is left exactly as it was. After a successful conversion, ImageMetadata.IccProfile is destinationProfile, ImageMetadata.TransferFunction is ColorTransferFunction.Srgb (the samples are described by the profile) and the EXIF thumbnail, which no longer matches the pixels, is removed. When the source and destination profiles have identical bytes, the pixels are not touched and only the label is set.
Convolve overloads
Convolve(Image, ConvolutionOptions, CancellationToken)
ImageProcessingExtensions.csApplies a convolution matrix to every frame of the image (including the poster frame) in place.
public static void Convolve(this Image image, ConvolutionOptions options, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
optionsConvolutionOptions- The convolution options.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be convolved.
Exceptions
UnsupportedImageFeatureExceptionConvolutionWorkingSpace.LinearSrgbis requested for an image with an incompatible ICC profile or with reserved transfer characteristics, or for floating-point samples outside [0, 1] that are not labeled as linear light. Nothing is changed.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
Every sample of a pixel becomes the sum of the same sample of its neighbors multiplied by the weights of ConvolutionOptions.Kernel, which is applied as written (it is not flipped) and not normalized. Pixels read outside the image are chosen by ConvolutionOptions.EdgeMode. The pixel format, the size and the metadata are kept, except for the EXIF thumbnail, which is removed.
Colors are filtered premultiplied by alpha and unpremultiplied afterward, and alpha is filtered too; a pixel whose resulting alpha is zero is transparent black. With ConvolutionOptions.PreserveAlpha, colors are filtered as stored and alpha is left untouched. Samples are filtered in double precision and written at the storage precision (16-bit samples never go through 8 bits), rounded to nearest with ties upward and clamped: negative sums become 0.
Floating-point samples (RgbaFloat, RgbaHalf) follow the rules of ImageProcessingExtensions.Resize: their values are the working samples, the colors are rounded to the nearest Single or Half without clamping (negative sums and values above 1 are kept), alpha is clamped to [0, 1], and a sample that is not a number spreads to the pixels whose kernel reads it. With ConvolutionWorkingSpace.LinearSrgb, samples labeled as linear light are filtered as they are, and the other ones must be numbers in [0, 1], the domain of their transfer function: otherwise nothing changes and the operation is rejected.
The image is rewritten in place; the scratch storage (a few rows per worker, proportional to the kernel height) is charged to the image allocation scope and rented before any pixel changes. When the image configuration allows several workers (ImageConfiguration.MaxDegreeOfParallelism), the rows of a large frame are split into bands convolved concurrently, each with its own scratch; the result is identical to the single-worker result.
Convolve(ImageFrame, ConvolutionOptions, CancellationToken)
ImageProcessingExtensions.csApplies a convolution matrix to one frame in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.Convolve.
public static void Convolve(this ImageFrame frame, ConvolutionOptions options, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
optionsConvolutionOptions- The convolution options.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be convolved.
Exceptions
UnsupportedImageFeatureExceptionConvolutionWorkingSpace.LinearSrgbis requested for an image with an incompatible ICC profile or with reserved transfer characteristics, or for floating-point samples outside [0, 1] that are not labeled as linear light. Nothing is changed.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
CorrectPerspective(Image, PointD, PointD, PointD, PointD, Size?, TransformOptions?, CancellationToken)
ImageProcessingExtensions.Perspective.csStraightens a quadrilateral of every frame of the image into an upright rectangle that becomes the whole image: a document, a whiteboard or a painting photographed at an angle, seen from the front. The four corners are given in the image, in order around the quadrilateral.
public static void CorrectPerspective(this Image image, PointD topLeft, PointD topRight, PointD bottomRight, PointD bottomLeft, Size? size = null, TransformOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
topLeftPointD- The corner of the quadrilateral that becomes the top-left corner of the image.
topRightPointD- The corner that becomes the top-right corner.
bottomRightPointD- The corner that becomes the bottom-right corner.
bottomLeftPointD- The corner that becomes the bottom-left corner.
sizeSize?- The size of the result, or
nullfor the size of the quadrilateral. optionsTransformOptions?- The filter, background color and working space, or
nullfor those ofTransformOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentException- A coordinate is not finite, the points are not the corners of a convex quadrilateral in order around it, or
sizeis empty. UnsupportedImageFeatureException- The pixel format has no alpha and
TransformOptions.BackgroundColoris not opaque;ResizeWorkingSpace.LinearSrgbis requested for an image it cannot decode; or the cursor hotspot of a frame leaves the canvas. The image is unchanged. ImageResourceLimitException- The canvas exceeds the size limits, or the replacement buffers would exceed the allocation limit. The image is unchanged.
OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
The corners are in stored-pixel coordinates, where the image covers [0, width] x [0, height] and the center of pixel (i, j) is (i + 1/2, j + 1/2): the corner of a document whose top-left pixel is (10, 20) is (10, 20), and its center (10.5, 20.5). The result maps topLeft to the corner (0, 0) of a canvas of size and bottomRight to its opposite corner, with the projective transformation that maps the quadrilateral onto the rectangle (ProjectiveTransform.CreateFromQuadrilateral, inverted). The default size is the one a scanner gives: the longer of the top and bottom edges by the longer of the left and right edges, rounded to whole pixels.
The pixels are sampled as ImageProcessingExtensions.Transform samples them, with the filter, the background color (for the parts of a quadrilateral that reach beyond the image) and the working space of options; its canvas mode and canvas size are not used. The operation is transactional across every frame and the poster.
Example
[Fact]
public void CorrectPerspective_Document()
{
// A 32x24 page with a checkerboard of 4-pixel squares
using var page = new Image<Rgb24>(32, 24);
for (var y = 0; y < 24; y++)
{
for (var x = 0; x < 32; x++)
{
page.Frames[0][x, y] = (x / 4) % 2 == (y / 4) % 2 ? new Rgb24(250, 250, 240) : new Rgb24(20, 30, 90);
}
}
// Photographed at an angle on a gray desk: the corners of the page land on a quadrilateral of a 64x48 photo
var topLeft = new PointD(8, 6);
var topRight = new PointD(56, 10);
var bottomRight = new PointD(52, 42);
var bottomLeft = new PointD(12, 40);
using var photo = page.Clone();
photo.Transform(
ProjectiveTransform.CreateFromQuadrilateral(new RectangleD(0, 0, 32, 24), topLeft, topRight, bottomRight, bottomLeft),
new TransformOptions { CanvasMode = TransformCanvasMode.Explicit, CanvasSize = new Size(64, 48), BackgroundColor = new Rgba64(30000, 30000, 30000, 65535) });
// Seen from the front again: the quadrilateral becomes the whole image
photo.CorrectPerspective(topLeft, topRight, bottomRight, bottomLeft, new Size(32, 24), new TransformOptions { BackgroundColor = new Rgba64(30000, 30000, 30000, 65535) });
Assert.Equal(new Size(32, 24), photo.Size);
// The middle of every square has its color back, within the blur of the two resamplings
var largest = 0;
for (var y = 0; y < 24; y++)
{
for (var x = 0; x < 32; x++)
{
if (x % 4 is 1 or 2 && y % 4 is 1 or 2)
{
largest = Math.Max(largest, Math.Abs(page.Frames[0][x, y].B - photo.Frames[0][x, y].B));
}
}
}
Assert.InRange(largest, 0, 16);
}Crop(Image, Rectangle, CancellationToken)
ImageProcessingExtensions.csCrops every frame of the image to a rectangle.
public static void Crop(this Image image, Rectangle rectangle, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
rectangleRectangle- The region to keep. It must be non-empty and entirely inside the canvas; it is never clamped.
cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentOutOfRangeExceptionrectangleis empty or not entirely inside the canvas.UnsupportedImageFeatureException- The cursor hotspot of a frame is outside
rectangle. The image is unchanged. ImageResourceLimitException- The replacement buffers would exceed the allocation limit. The image is unchanged.
OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
DetectEdges overloads
DetectEdges(Image, EdgeDetector, bool, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.csReplaces every displayed frame and the poster frame by its edges, in place: bright where the colors change, black where they are flat. The EXIF thumbnail, now stale, is removed.
public static void DetectEdges(this Image image, EdgeDetector detector, bool grayscale = true, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
detectorEdgeDetector- The edge operator.
grayscalebool- Whether every frame is converted to grayscale first.
edgeModeConvolutionEdgeMode- The pixels the operator reads beyond the edges of the image. The default,
ConvolutionEdgeMode.Clamp, finds no edge along the border of a flat image. cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be changed.
Exceptions
ArgumentOutOfRangeExceptiondetectororedgeModeis not a defined value.UnsupportedImageFeatureExceptiongrayscaleis set and the retained ICC profile is incompatible with the pixel format. Nothing is changed.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
Every color sample becomes the strength of the edge of the operator detector at its pixel, computed from the same sample of the neighboring pixels: the magnitude sqrt(gx^2 + gy^2) of the horizontal and vertical gradients (EdgeDetector.Sobel, EdgeDetector.Scharr, EdgeDetector.Prewitt), the largest response of the eight directions of a compass (EdgeDetector.Kirsch, EdgeDetector.Robinson), or the absolute value of a Laplacian (EdgeDetector.Laplacian3x3, EdgeDetector.Laplacian5x5, EdgeDetector.LaplacianOfGaussian). The matrices are the presets of ConvolutionKernel, applied as ImageProcessingExtensions.Convolve applies them. With ConvolutionEdgeMode.Clamp, the result is the one of OpenCV with BORDER_REPLICATE: cv2.magnitude(cv2.Sobel(f, cv2.CV_64F, 1, 0), cv2.Sobel(f, cv2.CV_64F, 0, 1)) for EdgeDetector.Sobel (and cv2.Scharr for EdgeDetector.Scharr), and abs(cv2.Laplacian(f, cv2.CV_64F, ksize=1)) or ksize=5 for the Laplacians, rounded.
With grayscale (the default), every frame is first converted to grayscale as ImageProcessingExtensions.Grayscale does, so the edges of the brightness are white on black; otherwise every color is processed on its own, and the edges keep the colors that change. Colors are filtered as stored, and alpha is kept unchanged: the hidden colors of transparent pixels take part, as with ConvolutionOptions.PreserveAlpha. The sums of the encoded samples are computed and combined in double precision, then rounded once at the storage precision (ties upward) and clamped to the sample range: 16-bit samples keep their precision. Floating-point samples are not clamped, and a sample that is not a number spreads to the pixels whose matrices read it. The scratch storage (a few rows per worker, and one row per matrix of the operator) is charged to the image allocation scope and rented before any pixel changes; the result does not depend on the number of workers.
DetectEdges(ImageFrame, EdgeDetector, bool, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.csReplaces one frame by its edges, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.DetectEdges.
public static void DetectEdges(this ImageFrame frame, EdgeDetector detector, bool grayscale = true, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
detectorEdgeDetector- The edge operator.
grayscalebool- Whether the frame is converted to grayscale first.
edgeModeConvolutionEdgeMode- The pixels the operator reads beyond the edges of the frame.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be changed.
Exceptions
ArgumentOutOfRangeExceptiondetectororedgeModeis not a defined value.UnsupportedImageFeatureExceptiongrayscaleis set and the ICC profile of the image is incompatible with the pixel format. Nothing is changed.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
Dilate overloads
Dilate(Image, StructuringElement, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csReplaces every sample of every displayed frame and the poster frame by the maximum of the same sample of the pixels of a structuring element around its pixel, in place: a grayscale dilation, which grows the bright areas and fills dark details smaller than the element. The EXIF thumbnail, now stale, is removed.
public static void Dilate(this Image image, StructuringElement element, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
elementStructuringElement- The neighborhood of each pixel.
edgeModeConvolutionEdgeMode- The pixels the filter reads beyond the edges of the image.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be filtered.
Exceptions
ArgumentNullExceptionimageorelementisnull.ArgumentOutOfRangeExceptionedgeModeis not a defined value.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The dilation is the counterpart of ImageProcessingExtensions.Erode, which describes the samples, the edges and the costs: it gives the result of OpenCV's cv2.dilate and of SciPy's ndimage.grey_dilation. Alpha is filtered too: a dilation grows the opaque areas of a mask.
Dilate(ImageFrame, StructuringElement, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csDilates one frame in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.Dilate.
public static void Dilate(this ImageFrame frame, StructuringElement element, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
elementStructuringElement- The neighborhood of each pixel.
edgeModeConvolutionEdgeMode- The pixels the filter reads beyond the edges of the frame.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be filtered.
Exceptions
ArgumentNullExceptionframeorelementisnull.ArgumentOutOfRangeExceptionedgeModeis not a defined value.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
Equalize overloads
Equalize(Image, HistogramEqualizationOptions?, CancellationToken)
ImageProcessingExtensions.csEqualizes the histogram of every frame of the image (including the poster frame) in place, which spreads its levels over the whole sample range: globally, or by tiles with a contrast limit (CLAHE). The pixel format and alpha are kept.
public static void Equalize(this Image image, HistogramEqualizationOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
optionsHistogramEqualizationOptions?- The options, or
nullforHistogramEqualizationOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageisnull.UnsupportedImageFeatureException- The pixel format is a floating-point one. Nothing is changed.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
See HistogramEqualizationMode for the mappings and HistogramColorMode for the samples they remap: by default, the luminance, so that the hues do not shift. The mappings work on the stored (encoded) sample values at the storage precision, with 256 levels for 8-bit pixel formats and 65,536 for 16-bit ones, and are deterministic: the same on every platform. No color profile is applied. Fully transparent pixels are not counted. Floating-point pixel formats have no discrete levels: convert the image to Rgba64 with Image.CloneAs first.
Each frame is equalized alone by default; HistogramEqualizationOptions.ShareHistogramAcrossFrames gives every frame the mapping of their combined histograms, so that an animation does not flicker.
The working memory (the tables of the tiles: up to 25 MiB for 8 x 8 tiles of 16-bit samples remapped per channel) is charged to the image and rented before a pixel changes. On failure or cancellation, some frames or rows may already be remapped.
Example
[Fact]
public void Histogram_Clahe()
{
// A dim, low-contrast image: the levels are between 100 and 131
using var image = new Image<Rgb24>(64, 64);
image.Frames[0].ProcessPixelRows(pixels =>
{
for (var y = 0; y < pixels.Height; y++)
{
var row = pixels.GetRowSpan(y);
for (var x = 0; x < row.Length; x++)
{
var level = (byte)(100 + ((x + y) % 32));
row[x] = new Rgb24(level, level, (byte)(level - 20));
}
}
});
var before = image.ComputeHistogram(HistogramChannel.Luminance);
var contrastBefore = before.Counts.LastIndexOfAnyExcept(0L) - before.Counts.IndexOfAnyExcept(0L);
// Contrast-limited adaptive equalization of the luminance, on a 4 x 4 grid of tiles
image.Equalize(new HistogramEqualizationOptions
{
Mode = HistogramEqualizationMode.Adaptive,
TileCountX = 4,
TileCountY = 4,
ClipLimit = 2,
});
// The levels spread over a range more than twice as wide; the clip limit keeps the contrast from growing further
var after = image.ComputeHistogram(HistogramChannel.Luminance);
var contrastAfter = after.Counts.LastIndexOfAnyExcept(0L) - after.Counts.IndexOfAnyExcept(0L);
Assert.InRange(contrastAfter, 2 * contrastBefore, 255);
}Equalize(ImageFrame, HistogramEqualizationOptions?, CancellationToken)
ImageProcessingExtensions.csEqualizes the histogram of one frame in place. See ImageProcessingExtensions.Equalize.
public static void Equalize(this ImageFrame frame, HistogramEqualizationOptions? options = null, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
optionsHistogramEqualizationOptions?- The options, or
nullforHistogramEqualizationOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be remapped.
Exceptions
ArgumentNullExceptionframeisnull.UnsupportedImageFeatureException- The pixel format is a floating-point one. Nothing is changed.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
Erode overloads
Erode(Image, StructuringElement, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csReplaces every sample of every displayed frame and the poster frame by the minimum of the same sample of the pixels of a structuring element around its pixel, in place: a grayscale erosion, which grows the dark areas and removes bright details smaller than the element. The EXIF thumbnail, now stale, is removed.
public static void Erode(this Image image, StructuringElement element, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
elementStructuringElement- The neighborhood of each pixel.
edgeModeConvolutionEdgeMode- The pixels the filter reads beyond the edges of the image.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be filtered.
Exceptions
ArgumentNullExceptionimageorelementisnull.ArgumentOutOfRangeExceptionedgeModeis not a defined value.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The element is flat (see StructuringElement), so the result is one of the samples: nothing is computed or rounded, 16-bit samples keep their precision, and there is no working space, since a transfer function keeps the order of the samples. Every sample of a pixel is filtered on its own, alpha included, as stored: an erosion also shrinks the opaque areas of a mask. The result is the one of OpenCV's cv2.erode with borderType=cv2.BORDER_REPLICATE and of SciPy's ndimage.grey_erosion(footprint=...), whose modes nearest, reflect, wrap and constant (0) are the edge modes ConvolutionEdgeMode.Clamp, ConvolutionEdgeMode.Mirror, ConvolutionEdgeMode.Wrap and ConvolutionEdgeMode.Zero. ConvolutionEdgeMode.Clamp, the default, gives the result of ignoring the pixels outside the frame, the default of OpenCV. Floating-point samples are ordered as numbers, -0 below +0, and every sample that is not a number above the positive infinity (it comes back with a positive sign), as ImageProcessingExtensions.MedianBlur orders them.
A rectangle takes a constant time per pixel, whatever its size (the algorithm of van Herk and of Gil and Werman, in two passes); an ellipse takes a time per pixel that grows with its height (each row filtered once per distinct row width of the ellipse, then one comparison per row of the ellipse). The scratch storage (about three blocks of 2 RadiusY + 1 rows of keys of 1, 2 or 4 bytes per sample for a rectangle; for an ellipse, as many rows filtered by each distinct width, 4 widths for a disk of radius 5 and 31 for radius 50) is charged to the image and rented before any pixel changes. The frames are filtered on the calling thread. An element of radius 0 changes nothing.
Example
[Fact]
public void Morphology_RemoveSpecks()
{
// A dark page with a bright one-pixel speck and a bright 5x5 square
using var image = new Image<Gray8>(16, 16, new Gray8(20));
image.Frames[0][2, 2] = new Gray8(250);
for (var y = 8; y < 13; y++)
{
for (var x = 8; x < 13; x++)
{
image.Frames[0][x, y] = new Gray8(200);
}
}
// An opening by a 3x3 square removes what is smaller than the square, and keeps the larger square intact
image.MorphologicalOpen(StructuringElement.CreateRectangle(1, 1));
Assert.Equal(20, image.Frames[0][2, 2].Value);
Assert.Equal(200, image.Frames[0][8, 8].Value);
Assert.Equal(200, image.Frames[0][12, 12].Value);
Assert.Equal(20, image.Frames[0][13, 13].Value);
}Erode(ImageFrame, StructuringElement, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csErodes one frame in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.Erode.
public static void Erode(this ImageFrame frame, StructuringElement element, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
elementStructuringElement- The neighborhood of each pixel.
edgeModeConvolutionEdgeMode- The pixels the filter reads beyond the edges of the frame.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be filtered.
Exceptions
ArgumentNullExceptionframeorelementisnull.ArgumentOutOfRangeExceptionedgeModeis not a defined value.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
ExtendCanvas(Image, Size, ResizeAnchor, Rgba64?, CancellationToken)
ImageProcessingExtensions.csEnlarges the canvas of every frame of the image to a given size, and places the image on it at an anchor.
public static void ExtendCanvas(this Image image, Size size, ResizeAnchor anchor = ResizeAnchor.Center, Rgba64? backgroundColor = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
sizeSize- The size of the new canvas. Each dimension must be at least that of the image; use
ImageProcessingExtensions.Cropto make the canvas smaller. anchorResizeAnchor- Where the image is placed on the canvas. Defaults to
ResizeAnchor.Center. backgroundColorRgba64?- The color of the new area, or
nullfor transparent black, which requires a pixel format with alpha. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentOutOfRangeExceptionsizeis smaller than the image in a dimension, oranchoris not a definedResizeAnchor.UnsupportedImageFeatureException- The pixel format has no alpha and
backgroundColoris not an opaque color. The image is unchanged. ImageResourceLimitException- The new canvas exceeds
ImageResourceLimits.MaxWidth,ImageResourceLimits.MaxHeightorImageResourceLimits.MaxFramePixels, or the replacement buffers would exceed the allocation limit. The image is unchanged. OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
The pixels are copied unchanged, and the rest of the canvas is backgroundColor converted to the pixel format of the image. The image lies at floor((size - imageSize) * a / 2) on each axis, where a is 0 for the left or top side, 1 for the center and 2 for the right or bottom side: a centered image gets the extra pixel of an odd padding on its right or bottom side. A canvas of the current size leaves the image unchanged.
Example
using var banner = new Image<Rgba32>(4, 2, new Rgba32(200, 0, 0, 255));
// A square canvas with the image at the bottom; the new area is transparent
banner.ExtendCanvas(new Size(4, 4), ResizeAnchor.Bottom);
Assert.Equal(new Rgba32(0, 0, 0, 0), banner.Frames[0][0, 0]);
Assert.Equal(new Rgba32(200, 0, 0, 255), banner.Frames[0][0, 2]);Flatten overloads
Flatten(Image, Rgba64, CancellationToken)
ImageProcessingExtensions.Effects.csComposites every pixel of every frame of the image (including the poster frame) over an opaque color and makes it opaque, in place, without changing the pixel format: what a conversion to a format without alpha does with PixelConversionOptions.BackgroundColor, but the alpha stays in the pixels, at its maximum.
public static void Flatten(this Image image, Rgba64 backgroundColor, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
backgroundColorRgba64- The opaque color under the pixels. An
Rgba32converts implicitly. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentExceptionbackgroundColoris not fully opaque.NotSupportedException- The pixel format is not supported (
A8). Nothing is changed. InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The formulas are those of the conversions (Image.CloneAs), on the encoded samples: (s a + bg (max - a) + max / 2) / max for the integer formats, with the background reduced to their precision first, so that a flattened Rgba32 image converted to Rgb24 is the Rgb24 conversion of the image with that background, bit for bit; c a + bg (1 - a) in double precision for the floating-point formats, with the alpha kept between 0 and 1 and the colors not clamped. An opaque pixel is not changed. A pixel format without alpha is already opaque: nothing changes. A gray format with alpha (La16, La32) gets the luma of the flattened colors, as its conversion to Gray8 or Gray16 does. An alpha mask (A8) has no color to hold the result: it is rejected.
No color profile is applied: the color is in the color space of the image. On failure or cancellation, some frames or rows may already be changed.
Flatten(ImageFrame, Rgba64, CancellationToken)
ImageProcessingExtensions.Effects.csComposites every pixel of one frame over an opaque color and makes it opaque, in place, without changing the pixel format. See ImageProcessingExtensions.Flatten.
public static void Flatten(this ImageFrame frame, Rgba64 backgroundColor, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
backgroundColorRgba64- The opaque color under the pixels. An
Rgba32converts implicitly. cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be changed.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentExceptionbackgroundColoris not fully opaque.NotSupportedException- The pixel format is not supported (
A8). Nothing is changed. InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
Flip overloads
Flip(Image, FlipMode, CancellationToken)
ImageProcessingExtensions.csMirrors every frame of the image (including the poster frame) in place, in stored-pixel coordinates.
public static void Flip(this Image image, FlipMode mode, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
modeFlipMode- The mirror axis.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames may already be mirrored.
Exceptions
ArgumentOutOfRangeExceptionmodeis not a definedFlipMode.InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Flip(ImageFrame, FlipMode, CancellationToken)
ImageProcessingExtensions.csMirrors one frame in place. The EXIF thumbnail of the image, now stale, is removed.
public static void Flip(this ImageFrame frame, FlipMode mode, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
modeFlipMode- The mirror axis.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be mirrored.
Exceptions
ArgumentOutOfRangeExceptionmodeis not a definedFlipMode.InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
GaussianBlur overloads
GaussianBlur(Image, double, ConvolutionEdgeMode, ConvolutionWorkingSpace, CancellationToken)
ImageProcessingExtensions.csBlurs every displayed frame and the poster frame in place with a Gaussian blur. The EXIF thumbnail, now stale, is removed.
public static void GaussianBlur(this Image image, double sigma, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, ConvolutionWorkingSpace workingSpace = ConvolutionWorkingSpace.Encoded, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
sigmadouble- The standard deviation of the blur, in pixels. Must be between 0 and 10000.
edgeModeConvolutionEdgeMode- The pixels the blur reads beyond the edges of the image.
workingSpaceConvolutionWorkingSpace- The numeric space the samples are filtered in.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be blurred.
Exceptions
ArgumentExceptionsigmais not a finite number.ArgumentOutOfRangeExceptionsigmais negative or exceeds 10000, oredgeModeorworkingSpaceis not a defined value.UnsupportedImageFeatureExceptionConvolutionWorkingSpace.LinearSrgbis requested for an image with an incompatible ICC profile, or for floating-point samples outside [0, 1] that are not labeled as linear light. Nothing is changed.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
Each pixel becomes the mean of the pixels around it, weighted by a bell curve of standard deviation sigma: the weight of a pixel at a distance d is exp(-d^2 / (2 sigma^2)), up to three standard deviations. A deviation of 1 softens an image; the blur a CSS filter or a shadow calls a radius is twice the deviation.
The blur is one separable convolution (ImageProcessingExtensions.Convolve): every row is filtered by a row of 2 ceil(3 sigma) + 1 weights, then the filtered rows by the same weights as a column, in double precision without rounding in between, so the result is the one of the two-dimensional matrix of their products, and the time grows with the deviation, not with its square. It follows the rules of a convolution (colors filtered premultiplied by alpha, samples rounded to nearest at the storage precision once, the same result whatever the number of workers); an opaque frame is blurred as its colors alone and keeps the maximum alpha, except with ConvolutionEdgeMode.Zero, which reads transparent pixels beyond the frame. The weights are computed without any function of the platform, and are the same everywhere. Without deviation, nothing changes.
GaussianBlur(ImageFrame, double, ConvolutionEdgeMode, ConvolutionWorkingSpace, CancellationToken)
ImageProcessingExtensions.csBlurs one frame in place with a Gaussian blur. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.GaussianBlur.
public static void GaussianBlur(this ImageFrame frame, double sigma, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, ConvolutionWorkingSpace workingSpace = ConvolutionWorkingSpace.Encoded, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
sigmadouble- The standard deviation of the blur, in pixels. Must be between 0 and 10000.
edgeModeConvolutionEdgeMode- The pixels the blur reads beyond the edges of the frame.
workingSpaceConvolutionWorkingSpace- The numeric space the samples are filtered in.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be blurred.
Exceptions
ArgumentExceptionsigmais not a finite number.ArgumentOutOfRangeExceptionsigmais negative or exceeds 10000, oredgeModeorworkingSpaceis not a defined value.UnsupportedImageFeatureExceptionConvolutionWorkingSpace.LinearSrgbis requested for an image with an incompatible ICC profile, or for floating-point samples outside [0, 1] that are not labeled as linear light. Nothing is changed.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
Glow overloads
Glow(Image, Rgba64, double, double, Rectangle?, CancellationToken)
ImageProcessingExtensions.Effects.csLights up (or tints) the center of every frame of the image (including the poster frame) with a color that fades out toward the edges, in place. The pixel format and the alpha of the pixels are kept.
public static void Glow(this Image image, Rgba64 color, double radiusX, double radiusY, Rectangle? rectangle = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
colorRgba64- The color at the center, with straight alpha. An
Rgba32converts implicitly. radiusXdouble- The horizontal half-axis of the ellipse where the glow ends, in pixels. Must be positive.
radiusYdouble- The vertical half-axis of the ellipse where the glow ends, in pixels. Must be positive.
rectangleRectangle?- The pixels the effect applies to, centered on it, or
null(the default) for the whole canvas. It may extend beyond the canvas. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentOutOfRangeException- A radius is not positive, is not a finite number or exceeds 16777216, or
rectangleis empty. InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working storage would exceed the allocation limit.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The effect is the opposite of ImageProcessingExtensions.Vignette: a radial gradient centered on rectangle, drawn on the pixels of the rectangle with CompositeMode.SourceAtop, that is color at the center and transparent on the ellipse of half-axes radiusX and radiusY and beyond it. At a pixel whose distance to the center is the fraction t of the ellipse in its direction, the color is composited with 1 - t times its alpha. The alpha of every pixel is kept: to light up transparent pixels too, fill a RadialGradientBrush with the canvas (Image.Draw).
The color is composited over the pixels: a light color with a partial alpha gives a soft glow. On failure or cancellation, some frames or rows may already be changed.
Glow(ImageFrame, Rgba64, double, double, Rectangle?, CancellationToken)
ImageProcessingExtensions.Effects.csLights up (or tints) the center of one frame, in place. See ImageProcessingExtensions.Glow.
public static void Glow(this ImageFrame frame, Rgba64 color, double radiusX, double radiusY, Rectangle? rectangle = null, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
colorRgba64- The color at the center, with straight alpha. An
Rgba32converts implicitly. radiusXdouble- The horizontal half-axis of the ellipse where the glow ends, in pixels. Must be positive.
radiusYdouble- The vertical half-axis of the ellipse where the glow ends, in pixels. Must be positive.
rectangleRectangle?- The pixels the effect applies to, centered on it, or
null(the default) for the whole canvas. It may extend beyond the canvas. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentOutOfRangeException- A radius is not positive, is not a finite number or exceeds 16777216, or
rectangleis empty. InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working storage would exceed the allocation limit.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
Grayscale overloads
Grayscale(Image, CancellationToken)
ImageProcessingExtensions.csConverts every frame of the image (including the poster frame) to grayscale in place, keeping the pixel format and alpha. Uses Rec. 709 luma coefficients (0.2126, 0.7152, 0.0722) on the encoded sample values, nearest rounding with ties upward, and clamping, at the storage precision: Y = (2126 R + 7152 G + 722 B + 5000) / 10000, stored into R, G and B. Floating-point samples (RgbaFloat, RgbaHalf) get 0.2126 R + 0.7152 G + 0.0722 B of their stored values in double precision, rounded to the nearest sample and not clamped (a sample that is not a number gives a luma that is not a number). Gray formats are left unchanged. The pixel format is kept, so a compatible RGB profile stays. Use Image.CloneAs to obtain Gray8 or Gray16 storage.
public static void Grayscale(this Image image, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames may already be converted.
Exceptions
UnsupportedImageFeatureException- The retained ICC profile is incompatible with the pixel format (it would be kept silently on gray pixels otherwise). Nothing is changed.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Grayscale(ImageFrame, CancellationToken)
ImageProcessingExtensions.csConverts one frame to grayscale in place, keeping the pixel format and alpha. See ImageProcessingExtensions.Grayscale.
public static void Grayscale(this ImageFrame frame, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be converted.
Exceptions
UnsupportedImageFeatureException- The ICC profile of the image is incompatible with the pixel format. Nothing is changed.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
GuidedFilter overloads
GuidedFilter(Image, int, double, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Smoothing.csSmooths every displayed frame and the poster frame with a guided filter that uses the frame as its own guide, in place: an edge-preserving smoothing that takes a constant time per pixel, whatever the radius. The EXIF thumbnail, now stale, is removed.
public static void GuidedFilter(this Image image, int radius, double epsilon, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
radiusint- The radius of the windows, in pixels. Must be between 0 and 1000; 0 changes nothing.
epsilondouble- The regularization, a squared fraction of the sample range. Must be positive and finite.
edgeModeConvolutionEdgeMode- The pixels the windows read beyond the edges of the image.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be filtered.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentOutOfRangeExceptionradiusis negative or exceeds 1000,epsilonis not positive and finite, oredgeModeis not a defined value.ImageResourceLimitException- The working memory would exceed a limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The filter of He, Sun and Tang ("Guided Image Filtering", 2010): in every window of (2 radius + 1)² pixels, each sample is approached by a linear function of the colors of the window, a · I + b, whose slope is held back by epsilon; every pixel then takes the mean of the functions of the windows that contain it. Where the colors of a window vary much less than √epsilon (noise, fine texture), the slope is close to 0 and the window is flattened to its mean; where they vary much more (an edge), the slope is close to 1 and the pixels are kept. The guide of a color image is its three colors (the color version of the paper, with their 3×3 covariance), that of a gray image its gray level, both as fractions of the sample range: an epsilon of 0.01 (0.1²) treats variations of about 25 levels of 255 as noise. The result matches OpenCV's cv2.ximgproc.guidedFilter(image, image, radius, epsilon × 255²) on 8-bit samples, whose windows reach beyond the edges like ConvolutionEdgeMode.Mirror.
Colors are filtered premultiplied by alpha, and alpha is filtered too, guided by the colors. The samples are filtered as stored (gamma-encoded), in double precision; the result can overshoot a little near edges, so integer samples are clamped to their range when stored and floating-point colors are not. A sample that is not a number spreads to the pixels whose windows contain it.
The frames are copied as single-precision working samples (4 bytes per sample), and the coefficients of every pixel are kept in single precision (up to 64 bytes per pixel), both charged to the image with a scratch of 2 radius + 3 rows of window sums (up to 25 doubles per pixel), and rented before any pixel changes. The frames are filtered on the calling thread.
Example
[Fact]
public void GuidedFilter_SmoothNoiseKeepEdges()
{
// A dark and a bright half, both with a little noise
using var image = new Image<Gray8>(32, 16);
for (var y = 0; y < 16; y++)
{
for (var x = 0; x < 32; x++)
{
var noise = ((x * 7) + (y * 13)) % 5 * 2;
image.Frames[0][x, y] = new Gray8((byte)((x < 16 ? 40 : 200) + noise));
}
}
// Variations below √0.01 = 0.1 (25 levels of 255) are smoothed, the step of 160 levels is kept
image.GuidedFilter(radius: 4, epsilon: 0.01);
Assert.InRange(image.Frames[0][5, 8].Value, 42, 46);
Assert.InRange(image.Frames[0][11, 8].Value, 40, 50);
Assert.InRange(image.Frames[0][20, 8].Value, 200, 208);
}GuidedFilter(ImageFrame, int, double, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Smoothing.csSmooths one frame with a guided filter that uses the frame as its own guide, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.GuidedFilter.
public static void GuidedFilter(this ImageFrame frame, int radius, double epsilon, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
radiusint- The radius of the windows, in pixels. Must be between 0 and 1000; 0 changes nothing.
epsilondouble- The regularization, a squared fraction of the sample range. Must be positive and finite.
edgeModeConvolutionEdgeMode- The pixels the windows read beyond the edges of the frame.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be filtered.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentOutOfRangeExceptionradiusis negative or exceeds 1000,epsilonis not positive and finite, oredgeModeis not a defined value.ImageResourceLimitException- The working memory would exceed a limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
MedianBlur overloads
MedianBlur(Image, int, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.csReplaces every sample of every displayed frame and the poster frame by the median of its neighborhood, in place. The EXIF thumbnail, now stale, is removed.
public static void MedianBlur(this Image image, int radius, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
radiusint- The number of pixels on each side of a pixel. Must be between 0 and 1000.
edgeModeConvolutionEdgeMode- The pixels the filter reads beyond the edges of the image.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be filtered.
Exceptions
ArgumentOutOfRangeExceptionradiusis negative or exceeds 1000, oredgeModeis not a defined value.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
Each sample becomes the median of the same sample of the (2 radius + 1)^2 pixels of the square centered on its pixel: the middle value once they are sorted, one of them. Isolated dots (salt-and-pepper noise) disappear while edges stay sharp. Every sample of a pixel is filtered on its own, alpha included, as stored: the result is the one of cv2.medianBlur of OpenCV and of -statistic Median of ImageMagick. Pixels read beyond the edges are chosen by edgeMode (ConvolutionEdgeMode.Zero reads transparent black).
Nothing is computed or rounded, so 16-bit samples keep their precision, and there is no working space: a transfer function keeps the order of the samples, so their median in linear light is the same sample. Floating-point samples are ordered as numbers, -0 below +0, and every sample that is not a number above the positive infinity (it comes back with a positive sign). Samples of up to 16 bits (the integer formats and RgbaHalf) are counted in histograms, and the time per pixel grows with the radius; the samples of RgbaFloat are sorted for every pixel, and the time grows with the square of the radius. The result does not depend on the number of workers. With a radius of 0, nothing changes.
MedianBlur(ImageFrame, int, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.csReplaces every sample of one frame by the median of its neighborhood, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.MedianBlur.
public static void MedianBlur(this ImageFrame frame, int radius, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
radiusint- The number of pixels on each side of a pixel. Must be between 0 and 1000.
edgeModeConvolutionEdgeMode- The pixels the filter reads beyond the edges of the frame.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be filtered.
Exceptions
ArgumentOutOfRangeExceptionradiusis negative or exceeds 1000, oredgeModeis not a defined value.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
MorphologicalClose overloads
MorphologicalClose(Image, StructuringElement, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csApplies a morphological closing to every displayed frame and the poster frame, in place: a dilation followed by an erosion with the same element, which fills the dark details smaller than the element (holes, gaps, thin dark lines) and keeps the shape and brightness of larger areas. The EXIF thumbnail, now stale, is removed.
public static void MorphologicalClose(this Image image, StructuringElement element, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
elementStructuringElement- The neighborhood of each pixel.
edgeModeConvolutionEdgeMode- The pixels the filters read beyond the edges of the image.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be filtered.
Exceptions
ArgumentNullExceptionimageorelementisnull.ArgumentOutOfRangeExceptionedgeModeis not a defined value.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
See ImageProcessingExtensions.Erode for the samples, the edges and the costs; the erosion reads the dilated frame with the same edge mode, as OpenCV's cv2.morphologyEx(MORPH_CLOSE) does.
MorphologicalClose(ImageFrame, StructuringElement, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csApplies a morphological closing to one frame in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.MorphologicalClose.
public static void MorphologicalClose(this ImageFrame frame, StructuringElement element, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
elementStructuringElement- The neighborhood of each pixel.
edgeModeConvolutionEdgeMode- The pixels the filters read beyond the edges of the frame.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be filtered.
Exceptions
ArgumentNullExceptionframeorelementisnull.ArgumentOutOfRangeExceptionedgeModeis not a defined value.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
MorphologicalOpen overloads
MorphologicalOpen(Image, StructuringElement, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csApplies a morphological opening to every displayed frame and the poster frame, in place: an erosion followed by a dilation with the same element, which removes the bright details smaller than the element (specks, thin lines) and keeps the shape and brightness of larger areas. The EXIF thumbnail, now stale, is removed.
public static void MorphologicalOpen(this Image image, StructuringElement element, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
elementStructuringElement- The neighborhood of each pixel.
edgeModeConvolutionEdgeMode- The pixels the filters read beyond the edges of the image.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be filtered.
Exceptions
ArgumentNullExceptionimageorelementisnull.ArgumentOutOfRangeExceptionedgeModeis not a defined value.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
See ImageProcessingExtensions.Erode for the samples, the edges and the costs; the dilation reads the eroded frame with the same edge mode, as OpenCV's cv2.morphologyEx(MORPH_OPEN) does.
MorphologicalOpen(ImageFrame, StructuringElement, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csApplies a morphological opening to one frame in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.MorphologicalOpen.
public static void MorphologicalOpen(this ImageFrame frame, StructuringElement element, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
elementStructuringElement- The neighborhood of each pixel.
edgeModeConvolutionEdgeMode- The pixels the filters read beyond the edges of the frame.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be filtered.
Exceptions
ArgumentNullExceptionframeorelementisnull.ArgumentOutOfRangeExceptionedgeModeis not a defined value.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
OilPaint overloads
OilPaint(Image, int, int, CancellationToken)
ImageProcessingExtensions.Effects.csGives every frame of the image (including the poster frame) the look of an oil painting, in place: flat strokes of color that keep the edges. The pixel format is kept. The EXIF thumbnail, now stale, is removed.
public static void OilPaint(this Image image, int levels, int radius, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
levelsint- The number of intensity levels, between 1 and 256: 20 is a good start.
radiusint- The number of pixels of the brush on each side of a pixel, between 0 and 500.
cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentOutOfRangeExceptionlevelsis not between 1 and 256, orradiusis not between 0 and 500.NotSupportedException- The pixel format is not supported. Nothing is changed.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working storage would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The intensity of every pixel, the Rec. 709 luma 0.2126 R + 0.7152 G + 0.0722 B of its color over black (premultiplied by its alpha) as a fraction of the largest sample, is cut into levels equal levels: floor(intensity levels), at most levels - 1 (a gray level is its own intensity). Each pixel then gets the mean of the pixels of the square of side 2 radius + 1 around it, inside the image, that have the most frequent level of that square (the lowest level among the most frequent ones). The mean is alpha-aware: premultiplied colors and alpha, computed on the stored sample values in double precision and rounded once, as the blurs do; floating-point samples are not clamped. Fewer levels give flatter areas, a larger radius larger strokes.
The working storage (a window of rows) is charged to the image and rented before a pixel changes. The window moves by one column at a time for the integer formats, whose sums are exact, so the time per pixel grows with the radius; for RgbaFloat and RgbaHalf, the sums of every window are made again, and it grows with its square. With a radius of 0, nothing changes. On cancellation, some frames or rows may already be changed.
OilPaint(ImageFrame, int, int, CancellationToken)
ImageProcessingExtensions.Effects.csGives one frame the look of an oil painting, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.OilPaint.
public static void OilPaint(this ImageFrame frame, int levels, int radius, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
levelsint- The number of intensity levels, between 1 and 256.
radiusint- The number of pixels of the brush on each side of a pixel, between 0 and 500.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be changed.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentOutOfRangeExceptionlevelsis not between 1 and 256, orradiusis not between 0 and 500.NotSupportedException- The pixel format is not supported. Nothing is changed.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working storage would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
Pad(Image, int, int, int, int, Rgba64?, CancellationToken)
ImageProcessingExtensions.csAdds a border around every frame of the image: the canvas grows by the given numbers of pixels on each side.
public static void Pad(this Image image, int left, int top, int right, int bottom, Rgba64? backgroundColor = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
leftint- The number of columns added on the left. Must not be negative.
topint- The number of rows added on the top. Must not be negative.
rightint- The number of columns added on the right. Must not be negative.
bottomint- The number of rows added on the bottom. Must not be negative.
backgroundColorRgba64?- The color of the border, or
nullfor transparent black, which requires a pixel format with alpha. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentOutOfRangeException- A padding is negative.
UnsupportedImageFeatureException- The pixel format has no alpha and
backgroundColoris not an opaque color. The image is unchanged. ImageResourceLimitException- The new canvas exceeds
ImageResourceLimits.MaxWidth,ImageResourceLimits.MaxHeightorImageResourceLimits.MaxFramePixels, or the replacement buffers would exceed the allocation limit. The image is unchanged. OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
The pixels are copied unchanged, and the border is backgroundColor converted to the pixel format of the image. Padding by zero on every side leaves the image unchanged. To center the image on a canvas of a given size, use ImageProcessingExtensions.ExtendCanvas.
Example
using var image = new Image<Rgb24>(4, 3, new Rgb24(10, 20, 30));
// A 2-pixel white border on the left and on the right, 1 pixel above and below
image.Pad(left: 2, top: 1, right: 2, bottom: 1, backgroundColor: new Rgba64(65535, 65535, 65535));
Assert.Equal(new Size(8, 5), image.Size);
Assert.Equal(new Rgb24(255, 255, 255), image.Frames[0][0, 0]);
Assert.Equal(new Rgb24(10, 20, 30), image.Frames[0][2, 1]);PercentileFilter overloads
PercentileFilter(Image, int, double, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csReplaces every sample of every displayed frame and the poster frame by a percentile of the same sample of the square around its pixel, in place: a rank filter, which generalizes the median (50), the minimum (0, an erosion by a square) and the maximum (100, a dilation by a square). The EXIF thumbnail, now stale, is removed.
public static void PercentileFilter(this Image image, int radius, double percentile, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
radiusint- The number of pixels on each side of a pixel. Must be between 0 and 1000.
percentiledouble- The percentile, from 0 (the minimum) to 100 (the maximum).
edgeModeConvolutionEdgeMode- The pixels the filter reads beyond the edges of the image.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be filtered.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentOutOfRangeExceptionradiusis negative or exceeds 1000,percentileis not between 0 and 100, oredgeModeis not a defined value.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The n = (2 radius + 1)^2 samples of the square are sorted, and the sample of rank floor(n * percentile / 100) (from 0, and n - 1 for 100) is kept: the rank of SciPy's ndimage.percentile_filter(size=2 radius + 1), whose result it gives with the same edges. A low percentile, such as 10, darkens like an erosion but ignores a few dark outliers; a high one brightens like a dilation.
Everything else is ImageProcessingExtensions.MedianBlur: the same histograms, costs, samples (alpha included), edges and workers.
PercentileFilter(ImageFrame, int, double, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csReplaces every sample of one frame by a percentile of its neighborhood, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.PercentileFilter.
public static void PercentileFilter(this ImageFrame frame, int radius, double percentile, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
radiusint- The number of pixels on each side of a pixel. Must be between 0 and 1000.
percentiledouble- The percentile, from 0 (the minimum) to 100 (the maximum).
edgeModeConvolutionEdgeMode- The pixels the filter reads beyond the edges of the frame.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be filtered.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentOutOfRangeExceptionradiusis negative or exceeds 1000,percentileis not between 0 and 100, oredgeModeis not a defined value.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
Pixelate overloads
Pixelate(Image, int, CancellationToken)
ImageProcessingExtensions.Effects.csReplaces every block of pixels of every frame of the image (including the poster frame) by its mean color, in place: a mosaic of large pixels. The pixel format is kept. The EXIF thumbnail, now stale, is removed.
public static void Pixelate(this Image image, int size, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
sizeint- The side of a block, in pixels. Must be positive.
cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentOutOfRangeExceptionsizeis not positive.NotSupportedException- The pixel format is not supported. Nothing is changed.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working storage would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The blocks are the squares of size by size pixels from the top-left corner; those of the right and bottom edges have the pixels that remain. Every pixel of a block gets the mean of its pixels, alpha-aware: the colors are averaged premultiplied by their alpha, so that the hidden color of a transparent pixel takes no part, and the alpha is the mean alpha. The means are computed on the stored sample values in double precision and rounded once, as the blurs do (a block whose alpha rounds to 0 becomes transparent black); floating-point samples are not clamped.
The working storage (two rows) is charged to the image and rented before a pixel changes. With a size of 1, nothing changes. On cancellation, some frames or rows may already be changed.
Pixelate(ImageFrame, int, CancellationToken)
ImageProcessingExtensions.Effects.csReplaces every block of pixels of one frame by its mean color, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.Pixelate.
public static void Pixelate(this ImageFrame frame, int size, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
sizeint- The side of a block, in pixels. Must be positive.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be changed.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentOutOfRangeExceptionsizeis not positive.NotSupportedException- The pixel format is not supported. Nothing is changed.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working storage would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
Quantize overloads
Quantize(Image, QuantizeOptions?, CancellationToken)
ImageProcessingExtensions.csReduces the colors of every frame of the image (including the poster frame) to a palette, in place, so that each frame has at most QuantizeOptions.MaxColors distinct colors, or only colors of QuantizeOptions.Palette. The pixel format is kept.
public static void Quantize(this Image image, QuantizeOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
optionsQuantizeOptions?- The options, or
nullforQuantizeOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentException- The fixed palette has no color the pixel format can store. Nothing is changed.
UnsupportedImageFeatureException- A floating-point sample is outside [0, 1] or is not a number.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The pixels are read as 8-bit RGBA, with the conversion of Image.CloneAs, and every pixel gets the palette color of its frame that the mapping gives it (see QuantizeOptions and DitheringMode): a 16-bit or floating-point sample gets the exact value of an 8-bit sample, and every fully transparent pixel becomes transparent black, so that the frame really has no more colors than its palette. Without a fixed palette, each frame gets its own palette, which holds its exact colors when they fit (such a frame only changes by those two rules). Alpha is reduced with the colors: translucent colors are palette entries of their own, and an opaque pixel always gets an opaque color.
A fixed palette is restricted to the colors the pixel format stores: the opaque entries for a format without alpha, the opaque gray entries for a gray format. The colors of an image are those of its color space: no color profile is applied. The result is deterministic: the same on every platform.
The working memory (about 1.3 MiB, 2.6 MiB for a pixel format with alpha, and a few rows) is charged to the image and rented before a pixel changes. On failure or cancellation, some frames or rows may already be reduced.
Example
[Fact]
public void Quantize_Dithering()
{
// A smooth gradient: 64 x 64 pixels of 4,096 different colors
using var image = new Image<Rgba32>(64, 64);
image.Frames[0].ProcessPixelRows(pixels =>
{
for (var y = 0; y < pixels.Height; y++)
{
var row = pixels.GetRowSpan(y);
for (var x = 0; x < row.Length; x++)
{
row[x] = new Rgba32((byte)(x * 4), (byte)(y * 4), 128);
}
}
});
// At most 16 colors, with Floyd–Steinberg error diffusion to hide the bands
image.Quantize(new QuantizeOptions { MaxColors = 16, Dithering = DitheringMode.FloydSteinberg });
var colors = new HashSet<Rgba32>();
image.Frames[0].ProcessPixelRows(pixels =>
{
for (var y = 0; y < pixels.Height; y++)
{
colors.UnionWith(pixels.GetRowSpan(y).ToArray());
}
});
Assert.HasCountLessThanOrEqual(16, colors);
}Quantize(ImageFrame, QuantizeOptions?, CancellationToken)
ImageProcessingExtensions.csReduces the colors of one frame to a palette, in place. See ImageProcessingExtensions.Quantize.
public static void Quantize(this ImageFrame frame, QuantizeOptions? options = null, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
optionsQuantizeOptions?- The options, or
nullforQuantizeOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be reduced.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentException- The fixed palette has no color the pixel format can store. Nothing is changed.
UnsupportedImageFeatureException- A floating-point sample is outside [0, 1] or is not a number.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
RadialBlur overloads
RadialBlur(Image, RadialBlurOptions, CancellationToken)
ImageProcessingExtensions.Smoothing.csBlurs every displayed frame and the poster frame along lines through a center (a zoom blur) or circles around it (a spin blur), in place: the streaks of a zoom or a rotation during the exposure, sharp at the center. The EXIF thumbnail, now stale, is removed.
public static void RadialBlur(this Image image, RadialBlurOptions options, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
optionsRadialBlurOptions- The kind of blur, its center and its amount.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be blurred.
Exceptions
ArgumentNullExceptionimageoroptionsisnull.UnsupportedImageFeatureExceptionConvolutionWorkingSpace.LinearSrgbis requested for an image with an incompatible ICC profile, or for floating-point samples outside [0, 1] that are not labeled as linear light. Nothing is changed.ImageResourceLimitException- The working copy would exceed a limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
Every pixel becomes the mean of the frame sampled along a path centered on it, whose length grows with its distance to the center (see RadialBlurOptions): the samples are evenly spaced, at most one pixel apart up to RadialBlurOptions.MaxSampleCount, and read with bilinear interpolation; the samples beyond the edges are read with RadialBlurOptions.EdgeMode. The time per pixel grows with the length of its path, up to that count.
As for ImageProcessingExtensions.Convolve, colors are averaged premultiplied by alpha and alpha is averaged too, 16-bit samples keep their precision, floating-point samples are not clipped, and RadialBlurOptions.WorkingSpace can average linear light. The frames are copied as single-precision working samples (4 bytes per sample), charged to the image and rented before any pixel changes. Frames of at least 65,536 pixels are split between up to ImageConfiguration.MaxDegreeOfParallelism workers, and the result does not depend on their number.
Example
[Fact]
public void RadialBlur_Zoom()
{
// Vertical stripes, 2 pixels wide
using var image = new Image<Rgb24>(64, 64);
for (var y = 0; y < 64; y++)
{
for (var x = 0; x < 64; x++)
{
image.Frames[0][x, y] = x / 2 % 2 == 0 ? new Rgb24(0, 0, 0) : new Rgb24(255, 255, 255);
}
}
// A zoom blur toward the center: the center stays sharp, the stripes far away along the horizontal axis blur to gray
image.RadialBlur(new RadialBlurOptions(RadialBlurKind.Zoom, center: new PointD(34.5, 32.5), amount: 0.5));
Assert.Equal(255, image.Frames[0][34, 32].R);
Assert.InRange(image.Frames[0][10, 32].R, 96, 160);
}RadialBlur(ImageFrame, RadialBlurOptions, CancellationToken)
ImageProcessingExtensions.Smoothing.csBlurs one frame along lines through a center or circles around it, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.RadialBlur.
public static void RadialBlur(this ImageFrame frame, RadialBlurOptions options, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
optionsRadialBlurOptions- The kind of blur, its center and its amount.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be blurred.
Exceptions
ArgumentNullExceptionframeoroptionsisnull.UnsupportedImageFeatureExceptionConvolutionWorkingSpace.LinearSrgbis requested for an image with an incompatible ICC profile, or for floating-point samples outside [0, 1] that are not labeled as linear light. Nothing is changed.ImageResourceLimitException- The working copy would exceed a limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
ReplaceColor overloads
ReplaceColor(Image, Rgba64, Rgba64, double, CancellationToken)
ImageProcessingExtensions.csGives a color to every pixel of every frame of the image (including the poster frame) whose color is within a tolerance of another one, in place: a background color made transparent, a color of a logo changed. The pixel format is kept.
public static void ReplaceColor(this Image image, Rgba64 color, Rgba64 replacement, double tolerance = 0d, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
colorRgba64- The color of the pixels to change, with straight alpha.
replacementRgba64- The color they get, with straight alpha.
tolerancedouble- How far, as a fraction of the range of a sample, each sample of a pixel can be from the one of
color: from 0 (the default) to 1. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentOutOfRangeExceptiontoleranceis not between 0 and 1.UnsupportedImageFeatureException- A floating-point sample is outside [0, 1] or is not a number.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
Each pixel is read as a 16-bit color (Rgba64), with the conversion of Image.CloneAs: 8-bit and 16-bit samples exactly, a gray level as its three colors, and an opaque alpha for a format without alpha. It matches when each of its four samples (alpha included) differs from the sample of color by at most tolerance times 65535, rounded to nearest with ties upward: 0 matches the exact color only, and 1 / 255 the next 8-bit value on each side. A matching pixel gets replacement, converted to the pixel format with the same rules as a color drawn on the image (Rec. 709 luma on a gray format, rounded to 8 bits on an 8-bit one, its alpha lost on a format without alpha); the others are not changed.
No color profile is applied: the colors are those of the color space of the image. The comparison is made on integers: the pixels are the same on every platform. A floating-point pixel is compared through its 16-bit color, so its samples must be in [0, 1]. On failure or cancellation, some frames or rows may already be changed.
ReplaceColor(ImageFrame, Rgba64, Rgba64, double, CancellationToken)
ImageProcessingExtensions.csGives a color to every pixel of one frame whose color is within a tolerance of another one, in place. See ImageProcessingExtensions.ReplaceColor.
public static void ReplaceColor(this ImageFrame frame, Rgba64 color, Rgba64 replacement, double tolerance = 0d, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
colorRgba64- The color of the pixels to change, with straight alpha.
replacementRgba64- The color they get, with straight alpha.
tolerancedouble- How far, as a fraction of the range of a sample, each sample of a pixel can be from the one of
color: from 0 (the default) to 1. cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be changed.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentOutOfRangeExceptiontoleranceis not between 0 and 1.UnsupportedImageFeatureException- A floating-point sample is outside [0, 1] or is not a number.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
Resize(Image, ResizeOptions, CancellationToken)
ImageProcessingExtensions.csResizes every frame of the image.
public static void Resize(this Image image, ResizeOptions options, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
optionsResizeOptions- The resize options.
cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentException- Upscaling is required but
ResizeOptions.AllowUpscalingisfalse(forResizeMode.StretchandResizeMode.Cover), or downscaling is required butResizeOptions.AllowDownscalingisfalse(for every mode butResizeMode.Contain). UnsupportedImageFeatureExceptionResizeWorkingSpace.LinearSrgbis requested for an image with an incompatible ICC profile or with reserved transfer characteristics, or for floating-point samples outside [0, 1] that are not labeled as linear light; the result is padded, the pixel format has no alpha andResizeOptions.BackgroundColoris not an opaque color; or the cursor hotspot of a frame designates a pixel thatResizeMode.Coverremoves. The image is unchanged.ImageResourceLimitException- The new canvas exceeds
ImageResourceLimits.MaxWidth,ImageResourceLimits.MaxHeightorImageResourceLimits.MaxFramePixels, or the replacement buffers would exceed the allocation limit. The image is unchanged. OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
The output size is computed exactly from ResizeOptions.Size and ResizeOptions.Mode (nearest rounding, ties upward, at least one pixel); a resize to the current size leaves the image unchanged. Output pixel centers are mapped exactly onto the source, kernels are widened when downsampling and normalized, and image edges are clamped.
ResizeMode.Pad and ResizeMode.BoxPad resize the image as ResizeMode.Contain does, then place it on a canvas of exactly the target size at ResizeOptions.Anchor: the padding offset is floor((target - size) * a / 2) on each axis, where a is 0 for the left or top side, 1 for the center and 2 for the right or bottom side. The padding is ResizeOptions.BackgroundColor, and the edges of the image are clamped as for any resize: the padding does not blend into the image. When no resampling is needed (ResizeMode.BoxPad of an image that fits), the pixels are copied unchanged. Otherwise each frame is resized into a temporary storage of the resized size, charged to the image allocation scope too.
Colors are filtered premultiplied by alpha and unpremultiplied afterward; a pixel whose resulting alpha is zero is transparent black. A frame whose pixels read by the filter are all opaque is filtered as its colors alone and keeps the maximum alpha. Samples are filtered in double precision and written at the storage precision (16-bit samples never go through 8 bits), rounded to nearest with ties upward and clamped. 8-bit samples filtered as stored (ResizeWorkingSpace.Encoded) without translucent pixels are filtered in fixed point (14-bit weights, 16-bit intermediate rows): about 0.2% of them are one unit off the correctly rounded value, none more. Nearest neighbor copies source pixels exactly. The scratch storage is charged to the image allocation scope together with the original and replacement storages.
Floating-point samples (RgbaFloat, RgbaHalf) go through the same double-precision filters, their values being the working samples (premultiplied by alpha, which is a fraction of 1). The colors are rounded to the nearest Single or Half and are not clamped, so values above 1 (high dynamic range highlights) and the negative lobes of the filters survive; a finite value beyond the largest half becomes an infinity. Alpha is clamped to [0, 1]. A sample that is not a number is not treated apart: it spreads to every output sample whose filter reads it. Nearest neighbor copies them exactly too.
With ResizeWorkingSpace.LinearSrgb, floating-point samples labeled as linear light (ImageMetadata.TransferFunction, the default of these formats) are filtered as they are, whatever their values. Samples labeled with another transfer function are decoded and encoded again with it in double precision: its domain is [0, 1], so a color sample outside it, or that is not a number, is rejected before anything changes, and the filtered light is clamped to [0, 1] before it is encoded, as for the integer formats.
When the image configuration allows several workers (ImageConfiguration.MaxDegreeOfParallelism), the output rows of a large frame are split into bands resized concurrently, each with its own scratch; the result is identical to the single-worker result.
Rotate overloads
Rotate(Image, RotateMode, CancellationToken)
ImageProcessingExtensions.csRotates every frame of the image clockwise by a multiple of 90 degrees (an exact pixel permutation).
public static void Rotate(this Image image, RotateMode mode, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
modeRotateMode- The rotation.
cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentOutOfRangeExceptionmodeis not a definedRotateMode.ImageResourceLimitException- The rotated canvas exceeds
ImageResourceLimits.MaxWidthorImageResourceLimits.MaxHeight, or the replacement buffers would exceed the allocation limit. The image is unchanged. OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Rotate(Image, double, TransformOptions?, CancellationToken)
ImageProcessingExtensions.csRotates every frame of the image clockwise by an angle, around its center.
public static void Rotate(this Image image, double degrees, TransformOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
degreesdouble- The angle, in degrees. A positive angle turns clockwise.
optionsTransformOptions?- The options, or
nullforTransformOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentExceptiondegreesis not a finite number, orTransformOptions.CanvasModeisTransformCanvasMode.ExplicitandTransformOptions.CanvasSizeis empty.UnsupportedImageFeatureException- The pixel format has no alpha, the result shows the background and
TransformOptions.BackgroundColoris not opaque;ResizeWorkingSpace.LinearSrgbis requested for an image it cannot decode; or the cursor hotspot of a frame leaves the canvas. The image is unchanged. ImageResourceLimitException- The canvas exceeds
ImageResourceLimits.MaxWidth,ImageResourceLimits.MaxHeightorImageResourceLimits.MaxFramePixels, or the replacement buffers would exceed the allocation limit. The image is unchanged. OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
The center of the image goes to the center of the canvas. With the default TransformCanvasMode.Expand, the canvas grows to hold the whole rotated image, and the corners it gains get TransformOptions.BackgroundColor (transparent by default). A rotation by a multiple of 90 degrees whose canvas holds exactly the rotated image (always the case with TransformCanvasMode.Expand) is the exact pixel permutation of ImageProcessingExtensions.Rotate, which also swaps the axes of ImageMetadata.PixelAspectRatio; a rotation by a multiple of 360 degrees leaves the image unchanged. See ImageProcessingExtensions.Transform for the sampling, the background and the canvas.
Sharpen overloads
Sharpen(Image, double, double, double, ConvolutionEdgeMode, ConvolutionWorkingSpace, CancellationToken)
ImageProcessingExtensions.csSharpens every displayed frame and the poster frame in place with an unsharp mask. The EXIF thumbnail, now stale, is removed.
public static void Sharpen(this Image image, double sigma, double amount = 1d, double threshold = 0d, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, ConvolutionWorkingSpace workingSpace = ConvolutionWorkingSpace.Encoded, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
sigmadouble- The standard deviation of the blur, in pixels. Must be between 0 and 10000.
amountdouble- The multiple of the difference from the blur that is added. Must be a finite number, not negative.
thresholddouble- The smallest difference from the blur that is sharpened, a fraction of the sample range. Must be between 0 and 1.
edgeModeConvolutionEdgeMode- The pixels the blur reads beyond the edges of the image.
workingSpaceConvolutionWorkingSpace- The numeric space the samples are filtered in.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be sharpened.
Exceptions
ArgumentExceptionsigma,amountorthresholdis not a finite number.ArgumentOutOfRangeExceptionsigmais negative or exceeds 10000,amountis negative,thresholdis outside [0, 1], oredgeModeorworkingSpaceis not a defined value.UnsupportedImageFeatureExceptionConvolutionWorkingSpace.LinearSrgbis requested for an image with an incompatible ICC profile, or for floating-point samples outside [0, 1] that are not labeled as linear light. Nothing is changed.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
The image is compared with its Gaussian blur of standard deviation sigma (the blur of ImageProcessingExtensions.GaussianBlur) and their difference is added back, multiplied by amount: every sample o whose blur is b becomes o + amount (o - b), which raises the contrast of the details smaller than the blur. A sample whose difference |o - b| is less than threshold times the range of the sample keeps its value, so that flat areas and their noise are left alone. The default amount of 1 with no threshold is the classic Gaussian sharpen; -unsharp 0x{sigma}+{amount}+0 of ImageMagick computes the same.
The sharpened samples are those of the blur: colors premultiplied by alpha and alpha sharpened too, in double precision, rounded once at the storage precision and clamped to the sample range (ringing beyond black and white is clipped, except for the colors of floating-point samples). An opaque frame is sharpened as its colors alone and keeps the maximum alpha, except with ConvolutionEdgeMode.Zero. The threshold is compared with the samples as they are filtered: premultiplied colors range up to the maximum sample squared, and linear light from 0 to 1 (times alpha). Without deviation or amount, nothing changes.
Sharpen(ImageFrame, double, double, double, ConvolutionEdgeMode, ConvolutionWorkingSpace, CancellationToken)
ImageProcessingExtensions.csSharpens one frame in place with an unsharp mask. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.Sharpen.
public static void Sharpen(this ImageFrame frame, double sigma, double amount = 1d, double threshold = 0d, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, ConvolutionWorkingSpace workingSpace = ConvolutionWorkingSpace.Encoded, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
sigmadouble- The standard deviation of the blur, in pixels. Must be between 0 and 10000.
amountdouble- The multiple of the difference from the blur that is added. Must be a finite number, not negative.
thresholddouble- The smallest difference from the blur that is sharpened, a fraction of the sample range. Must be between 0 and 1.
edgeModeConvolutionEdgeMode- The pixels the blur reads beyond the edges of the frame.
workingSpaceConvolutionWorkingSpace- The numeric space the samples are filtered in.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be sharpened.
Exceptions
ArgumentExceptionsigma,amountorthresholdis not a finite number.ArgumentOutOfRangeExceptionsigmais negative or exceeds 10000,amountis negative,thresholdis outside [0, 1], oredgeModeorworkingSpaceis not a defined value.UnsupportedImageFeatureExceptionConvolutionWorkingSpace.LinearSrgbis requested for an image with an incompatible ICC profile, or for floating-point samples outside [0, 1] that are not labeled as linear light. Nothing is changed.ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
Skew(Image, double, double, TransformOptions?, CancellationToken)
ImageProcessingExtensions.csSkews every frame of the image around its center: its vertical lines lean by one angle and its horizontal lines by another one.
public static void Skew(this Image image, double degreesX, double degreesY, TransformOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
degreesXdouble- The angle the vertical lines lean by, in degrees. Must be between -90 and 90, excluded.
degreesYdouble- The angle the horizontal lines lean by, in degrees. Must be between -90 and 90, excluded.
optionsTransformOptions?- The options, or
nullforTransformOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentOutOfRangeException- An angle is not between -90 and 90 degrees, excluded.
ArgumentException- The two angles flatten the image to a line (their tangents multiply to 1), or
TransformOptions.CanvasModeisTransformCanvasMode.ExplicitandTransformOptions.CanvasSizeis empty. UnsupportedImageFeatureException- The pixel format has no alpha, the result shows the background and
TransformOptions.BackgroundColoris not opaque;ResizeWorkingSpace.LinearSrgbis requested for an image it cannot decode; or the cursor hotspot of a frame leaves the canvas. The image is unchanged. ImageResourceLimitException- The canvas exceeds
ImageResourceLimits.MaxWidth,ImageResourceLimits.MaxHeightorImageResourceLimits.MaxFramePixels, or the replacement buffers would exceed the allocation limit. The image is unchanged. OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
A point moves horizontally by tan(degreesX) times its distance to the center row, and vertically by tan(degreesY) times its distance to the center column (AffineTransform.CreateSkew). The center of the image goes to the center of the canvas. With the default TransformCanvasMode.Expand, the canvas grows to hold the whole skewed image. See ImageProcessingExtensions.Transform for the sampling, the background and the canvas.
SuggestCrop overloads
SuggestCrop(Image, int, int, CropSuggestionOptions?, CancellationToken)
ImageProcessingExtensions.CropSuggestion.csSuggests where to crop the image to an aspect ratio while keeping its content: the rectangle of the ratio, as large as the image allows (or scaled by CropSuggestionOptions.Scale), that holds the most detail or the most salient colors of every displayed frame and the poster frame. Nothing is changed: pass the rectangle to ImageProcessingExtensions.Crop.
public static Rectangle SuggestCrop(this Image image, int aspectWidth, int aspectHeight, CropSuggestionOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image.
aspectWidthint- The width of the aspect ratio, such as 16 for 16:9. Must be positive.
aspectHeightint- The height of the aspect ratio, such as 9 for 16:9. Must be positive.
optionsCropSuggestionOptions?- The energy and the scale of the crop, or
nullfor the largest crop that keeps the most detail. cancellationTokenCancellationToken- The token checked between rows.
Returns
Rectangle The suggested rectangle, inside the image.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentOutOfRangeExceptionaspectWidthoraspectHeightis not positive.ImageResourceLimitException- The table or the buffers exceed a limit.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
UnsupportedImageFeatureException- A floating-point sample is not finite.
Remarks
Every pixel gets an energy (CropSuggestionOptions.Energy): the differences of its luma and alpha with its right and lower neighbors, or how much its color stands out from the mean color of the frame (the frequency-tuned saliency of Achanta et al., in Oklab). The energies of the frames are added, and the rectangle of the requested size with the largest total wins. The energies are integers (from 16-bit samples, or saliencies rounded to 1/65,536), so the totals are exact and the suggestion is deterministic: among equal totals, the rectangle nearest to the center of the image wins, then the topmost, then the leftmost; an image without detail gets the centered crop.
The size of the crop is the largest rectangle of the ratio inside the image, its other side rounded to the nearest whole pixel: a 4000×3000 image gets 3000×3000 for 1:1 and 4000×2250 for 16:9. Colors are read premultiplied by alpha, so transparent areas have no energy; floating-point samples are clamped to [0, 1] and must be finite. The time is linear in the number of pixels. A summed-area table of 8 bytes per pixel is charged to the image, with row buffers. The frames are read on the calling thread.
Example
[Fact]
public void SuggestCrop_KeepTheSubject()
{
// A wide photo: a flat sky, with a detailed subject on the right
using var image = new Image<Rgb24>(160, 90, new Rgb24(120, 170, 230));
for (var y = 30; y < 80; y++)
{
for (var x = 110; x < 150; x++)
{
image.Frames[0][x, y] = (x + y) % 3 == 0 ? new Rgb24(40, 30, 20) : new Rgb24(200, 180, 90);
}
}
// The square crop keeps the subject instead of the middle of the sky
var crop = image.SuggestCrop(1, 1);
Assert.Equal(new Size(90, 90), crop.Size);
Assert.True(crop.X <= 110 && crop.Right >= 150, $"The crop {crop} cuts the subject");
image.Crop(crop);
Assert.Equal(new Size(90, 90), image.Size);
}SuggestCrop(ImageFrame, int, int, CropSuggestionOptions?, CancellationToken)
ImageProcessingExtensions.CropSuggestion.csSuggests where to crop one frame to an aspect ratio while keeping its content. See ImageProcessingExtensions.SuggestCrop.
public static Rectangle SuggestCrop(this ImageFrame frame, int aspectWidth, int aspectHeight, CropSuggestionOptions? options = null, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame.
aspectWidthint- The width of the aspect ratio, such as 16 for 16:9. Must be positive.
aspectHeightint- The height of the aspect ratio, such as 9 for 16:9. Must be positive.
optionsCropSuggestionOptions?- The energy and the scale of the crop, or
nullfor the largest crop that keeps the most detail. cancellationTokenCancellationToken- The token checked between rows.
Returns
Rectangle The suggested rectangle, inside the frame.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentOutOfRangeExceptionaspectWidthoraspectHeightis not positive.ImageResourceLimitException- The table or the buffers exceed a limit.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
UnsupportedImageFeatureException- A floating-point sample is not finite.
Threshold overloads
Threshold(Image, ThresholdOptions?, CancellationToken)
ImageProcessingExtensions.csBinarizes every frame of the image (including the poster frame) in place: each pixel becomes ThresholdOptions.UpperColor (white by default) when its luminance is greater than its threshold, and ThresholdOptions.LowerColor (black by default) otherwise. The pixel format is kept.
public static void Threshold(this Image image, ThresholdOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
optionsThresholdOptions?- The options, or
nullforThresholdOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentException- The pixel format cannot store
ThresholdOptions.UpperColororThresholdOptions.LowerColorexactly. Nothing is changed. UnsupportedImageFeatureException- The pixel format is a floating-point one. Nothing is changed.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
See ThresholdMethod for how the thresholds are chosen: one level for the whole frame, given or chosen by Otsu's method, or a level per pixel from its neighborhood (ThresholdMethod.Mean, ThresholdMethod.Sauvola) for uneven lighting. The luminance is the Rec. 709 luma of the stored (encoded) samples at the storage precision, which ImageProcessingExtensions.Grayscale stores; alpha is ignored. No color profile is applied. Floating-point pixel formats have no discrete levels: convert the image to Rgba64 with Image.CloneAs first.
Every pixel gets one of the two colors, alpha included, so the frames hold exactly two colors. With the default colors, the result can be saved as a bilevel page (TiffPixelLayout.Bilevel, the layout of the CCITT compressions) or as a portable bitmap (PnmPixelLayout.Bitmap), which store exactly black and white pixels. The pixel format must store both colors exactly: an opaque color without alpha, a gray color for a gray format, samples that are multiples of 257 for an 8-bit format. To dither to black and white instead, use ImageProcessingExtensions.Quantize with a palette of the two colors.
The working memory (one row, and for the adaptive methods 2 bytes per pixel of a frame and 16 bytes per column) is charged to the image and rented before a pixel changes. On failure or cancellation, some frames or rows may already be binarized.
Example
[Fact]
public void Threshold_Sauvola()
{
// A page lit unevenly: the paper goes from 120 (left) to 250 (right), and the dark strokes are 80 levels darker
using var page = new Image<Gray8>(96, 32);
page.Frames[0].ProcessPixelRows(pixels =>
{
for (var y = 0; y < pixels.Height; y++)
{
var row = pixels.GetRowSpan(y);
for (var x = 0; x < row.Length; x++)
{
var paper = 120 + (x * 130 / 95);
var stroke = x % 8 < 2 && y is >= 8 and < 24;
row[x] = new Gray8((byte)(stroke ? paper - 80 : paper));
}
}
});
// No single level separates the strokes from the paper: the strokes on the right are lighter than the paper on the left
Assert.True(page.Frames[0][88, 16].Value > page.Frames[0][4, 4].Value);
// Sauvola's threshold follows the lighting: the strokes become black, the paper white
page.Threshold(new ThresholdOptions { Method = ThresholdMethod.Sauvola, WindowSize = 25 });
Assert.Equal(0, page.Frames[0][88, 16].Value);
Assert.Equal(255, page.Frames[0][4, 4].Value);
Assert.Equal(255, page.Frames[0][92, 16].Value);
}Threshold(ImageFrame, ThresholdOptions?, CancellationToken)
ImageProcessingExtensions.csBinarizes one frame in place. See ImageProcessingExtensions.Threshold.
public static void Threshold(this ImageFrame frame, ThresholdOptions? options = null, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
optionsThresholdOptions?- The options, or
nullforThresholdOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be binarized.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentException- The pixel format cannot store
ThresholdOptions.UpperColororThresholdOptions.LowerColorexactly. Nothing is changed. UnsupportedImageFeatureException- The pixel format is a floating-point one. Nothing is changed.
InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working memory would exceed the allocation limit. Nothing is changed.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
TopHat overloads
TopHat(Image, StructuringElement, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csReplaces the colors of every displayed frame and the poster frame by their white top-hat transform, in place: the difference between the frame and its opening, which keeps only the bright details smaller than the element, on black. It extracts small bright features from an uneven background (text on a page lit unevenly, stars, cells). Alpha is kept. The EXIF thumbnail, now stale, is removed.
public static void TopHat(this Image image, StructuringElement element, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
elementStructuringElement- The neighborhood of each pixel: larger than the details to keep.
edgeModeConvolutionEdgeMode- The pixels the filters read beyond the edges of the image.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some frames or rows may already be changed.
Exceptions
ArgumentNullExceptionimageorelementisnull.ArgumentOutOfRangeExceptionedgeModeis not a defined value.NotSupportedException- The pixel format is
A8, which has no color. Nothing is changed. ImageResourceLimitException- The scratch storage would exceed the allocation limit. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
Every color sample becomes sample - opening, where the opening is the one of ImageProcessingExtensions.MorphologicalOpen: the result of OpenCV's cv2.morphologyEx(MORPH_TOPHAT) for the colors. Integer differences are never negative (they are clamped to 0), and floating-point differences are rounded to the sample type. Alpha is not transformed (the transform of an opaque alpha would be fully transparent), so an alpha mask (A8), which has no color, is rejected.
The scratch storage of the opening and a copy of the frame are charged to the image and rented before any pixel changes.
TopHat(ImageFrame, StructuringElement, ConvolutionEdgeMode, CancellationToken)
ImageProcessingExtensions.Morphology.csReplaces the colors of one frame by their white top-hat transform, in place. The EXIF thumbnail of the image, now stale, is removed. See ImageProcessingExtensions.TopHat.
public static void TopHat(this ImageFrame frame, StructuringElement element, ConvolutionEdgeMode edgeMode = ConvolutionEdgeMode.Clamp, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
elementStructuringElement- The neighborhood of each pixel: larger than the details to keep.
edgeModeConvolutionEdgeMode- The pixels the filters read beyond the edges of the frame.
cancellationTokenCancellationToken- The token to monitor for cancellation requests. On cancellation, some rows may already be changed.
Exceptions
ArgumentNullExceptionframeorelementisnull.ArgumentOutOfRangeExceptionedgeModeis not a defined value.NotSupportedException- The pixel format is
A8, which has no color. Nothing is changed. ImageResourceLimitException- The scratch storage would exceed the allocation limit. The frame is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.
Transform overloads
Transform(Image, AffineTransform, TransformOptions?, CancellationToken)
ImageProcessingExtensions.csTransforms every frame of the image with an affine transformation: any combination of translations, scalings, rotations and skews.
public static void Transform(this Image image, AffineTransform transform, TransformOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
transformAffineTransform- The transformation, in stored-pixel coordinates: the image covers
[0, width] x [0, height]. optionsTransformOptions?- The options, or
nullforTransformOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentExceptiontransformflattens the image to a line or a point, orTransformOptions.CanvasModeisTransformCanvasMode.ExplicitandTransformOptions.CanvasSizeis empty.UnsupportedImageFeatureException- The pixel format has no alpha, the result shows the background and
TransformOptions.BackgroundColoris not opaque;ResizeWorkingSpace.LinearSrgbis requested for an image it cannot decode; or the cursor hotspot of a frame leaves the canvas. The image is unchanged. ImageResourceLimitException- The canvas exceeds
ImageResourceLimits.MaxWidth,ImageResourceLimits.MaxHeightorImageResourceLimits.MaxFramePixels, or the replacement buffers would exceed the allocation limit. The image is unchanged. OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
See ImageProcessingExtensions.Transform. An affine transformation shrinks the image by the same factors everywhere, and its kernels are widened by those factors without limit, as a resize does.
Transform(Image, ProjectiveTransform, TransformOptions?, CancellationToken)
ImageProcessingExtensions.csTransforms every frame of the image with a projective transformation: the image seen in perspective.
public static void Transform(this Image image, ProjectiveTransform transform, TransformOptions? options = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
transformProjectiveTransform- The transformation, in stored-pixel coordinates: the image covers
[0, width] x [0, height]. optionsTransformOptions?- The options, or
nullforTransformOptions.Default. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentExceptiontransformflattens the image to a line or a point; or puts part of the image on or behind its horizon withTransformCanvasMode.Expand; orTransformOptions.CanvasModeisTransformCanvasMode.ExplicitandTransformOptions.CanvasSizeis empty.UnsupportedImageFeatureException- The pixel format has no alpha and
TransformOptions.BackgroundColoris not opaque;ResizeWorkingSpace.LinearSrgbis requested for an image it cannot decode; or the cursor hotspot of a frame leaves the canvas. The image is unchanged. ImageResourceLimitException- The canvas exceeds
ImageResourceLimits.MaxWidth,ImageResourceLimits.MaxHeightorImageResourceLimits.MaxFramePixels, or the replacement buffers would exceed the allocation limit. The image is unchanged. OperationCanceledException- The operation was canceled. The image is unchanged.
InvalidOperationException- A pixel lease is active.
ObjectDisposedException- The image is disposed.
Remarks
Geometry. The image covers [0, width] x [0, height] in stored-pixel coordinates (pixel (i, j) is the unit square centered at (i + 1/2, j + 1/2)), and transform moves it to the plane of the result. With TransformCanvasMode.Expand (the default), the canvas is the smallest one that holds the bounds of the transformed image (a size within 1e-6 of an integer is that integer), and the bounds are centered in it: the translation of the transformation does not matter, and every corner of the image must be in front of the viewer (W positive). With TransformCanvasMode.Keep and TransformCanvasMode.Explicit, the canvas has the size of the image or TransformOptions.CanvasSize, and the coordinates of the plane are those of the canvas: what lands outside of it is cut. A transformation that moves every pixel onto a pixel of a canvas it fills exactly (a quarter turn, a mirror) is an exact pixel permutation, as ImageProcessingExtensions.Rotate and ImageProcessingExtensions.Flip are; one that moves nothing leaves the image unchanged.
Sampling. Every output pixel takes the value of the source at the point its center comes from, filtered with TransformOptions.Filter, the kernels of ImageProcessingExtensions.Resize. Where the transformation shrinks the source along one of its axes, the kernel of that axis is widened by the same factor, as a resize does (a rotation or a skew widens nothing); a projective transformation, whose factors grow without bound toward its horizon, widens them by 16 at most. The weights are those of the kernel at the distance of each source pixel center, normalized by their sum. Colors are filtered premultiplied by alpha, in double precision, in the working space of TransformOptions.WorkingSpace, and rounded once to the storage precision as a resize rounds them (a pixel whose alpha is zero is transparent black); floating-point samples follow the rules of ImageProcessingExtensions.Resize. Nearest neighbor copies the source pixel that contains the point, exactly. The box filter averages the source pixels whose centers lie in (p - f/2, p + f/2] on each axis, where p is the point and f the widening of the axis: without widening, the pixel that contains the point.
Background. The pixels beyond the edges of the source are TransformOptions.BackgroundColor (transparent black by default), converted to the pixel format and filtered like the others: the edges of the image blend into the background, and the canvas the image does not reach is the background. A pixel format without alpha needs an opaque background, unless no output pixel reads beyond the edges of the source (a projective transformation always may).
Frames. The operation is transactional across every frame and the poster, like ImageProcessingExtensions.Resize. A cursor hotspot moves to the pixel that contains the image of its pixel center; when that pixel is not on the canvas, the operation throws and the image is unchanged. ImageMetadata.PixelAspectRatio is kept, except by the permutations that swap the axes. When the image configuration allows several workers (ImageConfiguration.MaxDegreeOfParallelism), the output rows of a large frame are split into bands transformed concurrently; the result is identical to the single-worker result.
Vignette overloads
Vignette(Image, Rgba64, double, double, Rectangle?, CancellationToken)
ImageProcessingExtensions.Effects.csDarkens (or tints) the edges of every frame of the image (including the poster frame) toward a color, in place: the corners of an old lens. The pixel format and the alpha of the pixels are kept.
public static void Vignette(this Image image, Rgba64 color, double radiusX, double radiusY, Rectangle? rectangle = null, CancellationToken cancellationToken = default)Parameters
imageImage- The image to modify.
colorRgba64- The color of the edges, with straight alpha. An
Rgba32converts implicitly. radiusXdouble- The horizontal half-axis of the ellipse where the color is reached, in pixels. Must be positive.
radiusYdouble- The vertical half-axis of the ellipse where the color is reached, in pixels. Must be positive.
rectangleRectangle?- The pixels the effect applies to, centered on it, or
null(the default) for the whole canvas. It may extend beyond the canvas. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionimageisnull.ArgumentOutOfRangeException- A radius is not positive, is not a finite number or exceeds 16777216, or
rectangleis empty. InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working storage would exceed the allocation limit.
ObjectDisposedException- The image is disposed.
OperationCanceledException- The operation was canceled.
Remarks
The effect is a radial gradient (RadialGradientBrush) centered on rectangle, drawn on the pixels of the rectangle with CompositeMode.SourceAtop: transparent at the center, it reaches color on the ellipse of half-axes radiusX and radiusY, and is color beyond it. At a pixel whose distance to the center is the fraction t of the ellipse in its direction, the color is composited with t times its alpha. The alpha of every pixel is kept: a transparent pixel stays transparent. The arithmetic is the one of the drawings (see DrawingCanvas): exact integer compositing of the 16-bit gradient, on the encoded samples.
With the half-diagonal of the rectangle as both radii, the corners get the whole color and the center nothing; with half its width and half its height, the ellipse touches its sides. A color that is not opaque gives a lighter vignette. On failure or cancellation, some frames or rows may already be changed.
Vignette(ImageFrame, Rgba64, double, double, Rectangle?, CancellationToken)
ImageProcessingExtensions.Effects.csDarkens (or tints) the edges of one frame toward a color, in place. See ImageProcessingExtensions.Vignette.
public static void Vignette(this ImageFrame frame, Rgba64 color, double radiusX, double radiusY, Rectangle? rectangle = null, CancellationToken cancellationToken = default)Parameters
frameImageFrame- The frame to modify.
colorRgba64- The color of the edges, with straight alpha. An
Rgba32converts implicitly. radiusXdouble- The horizontal half-axis of the ellipse where the color is reached, in pixels. Must be positive.
radiusYdouble- The vertical half-axis of the ellipse where the color is reached, in pixels. Must be positive.
rectangleRectangle?- The pixels the effect applies to, centered on it, or
null(the default) for the whole canvas. It may extend beyond the canvas. cancellationTokenCancellationToken- The token to monitor for cancellation requests.
Exceptions
ArgumentNullExceptionframeisnull.ArgumentOutOfRangeException- A radius is not positive, is not a finite number or exceeds 16777216, or
rectangleis empty. InvalidOperationException- A pixel lease is active.
ImageResourceLimitException- The working storage would exceed the allocation limit.
ObjectDisposedException- The frame is no longer attached to a live image.
OperationCanceledException- The operation was canceled.