FrameworkExtensions.System.Drawing 1.0.0.134

dotnet add package FrameworkExtensions.System.Drawing --version 1.0.0.134
                    
NuGet\Install-Package FrameworkExtensions.System.Drawing -Version 1.0.0.134
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FrameworkExtensions.System.Drawing" Version="1.0.0.134" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FrameworkExtensions.System.Drawing" Version="1.0.0.134" />
                    
Directory.Packages.props
<PackageReference Include="FrameworkExtensions.System.Drawing" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FrameworkExtensions.System.Drawing --version 1.0.0.134
                    
#r "nuget: FrameworkExtensions.System.Drawing, 1.0.0.134"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FrameworkExtensions.System.Drawing@1.0.0.134
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FrameworkExtensions.System.Drawing&version=1.0.0.134
                    
Install as a Cake Addin
#tool nuget:?package=FrameworkExtensions.System.Drawing&version=1.0.0.134
                    
Install as a Cake Tool

Extensions to System.Drawing

Build Tests

Last Commit NuGet Version License

Extension methods for System.Drawing types (bitmaps, images, colors, graphics) with a comprehensive image processing pipeline including pixel art scalers, resamplers, ditherers, quantizers, and color spaces.


Extension Methods

Bitmap Extensions (Bitmap)

Bitmap Locking
  • Lock(...) - Lock bitmap for direct pixel access (8 overloads for different combinations)
    • Lock() - Lock entire bitmap with ReadWrite mode
    • Lock(Rectangle) - Lock region
    • Lock(ImageLockMode) - Lock with specific mode
    • Lock(PixelFormat) - Lock with specific format
    • Lock(Rectangle, ImageLockMode)
    • Lock(Rectangle, PixelFormat)
    • Lock(ImageLockMode, PixelFormat)
    • Lock(Rectangle, ImageLockMode, PixelFormat) - Full control
    • Returns format-specific IBitmapLocker implementation
Transformations
  • ConvertPixelFormat(PixelFormat) - Convert bitmap to different pixel format
  • Crop(Rectangle, PixelFormat = DontCare) - Extract region from bitmap
  • Resize(int width, int height, InterpolationMode = Bicubic) - Resize bitmap
  • Rotated(float angle, Point? center = null) - Create rotated copy of bitmap
  • RotateInplace(float angle, Point? center = null) - Rotate bitmap in-place
  • RotateTo(Bitmap target, float angle, Point? center = null) - Rotate to target bitmap
  • FlipHorizontal() - Mirror left-to-right, returns new bitmap
  • FlipVertical() - Mirror top-to-bottom, returns new bitmap
  • MirrorAlongAxis(PointF p1, PointF p2) - Mirror pixels across an arbitrary line defined by two points (bilinear interpolation)
  • ZoomToPoint(PointF center, float factor) - Crop/zoom centered on a specific point with given magnification factor
  • Straighten(float angle) - Deskew by rotating then cropping to the largest inscribed axis-aligned rectangle
  • Skew(float angleX, float angleY) - Shear/skew transformation with horizontal and vertical shear angles
  • AutoRotate() - Read EXIF orientation tag (0x0112) and apply the correct rotation/flip to normalize the image
Color Quantization & Dithering
  • ReduceColors<TQuantizer, TDitherer>(quantizer, ditherer, colorCount, isHighQuality) - Reduce image to indexed palette
    • Returns indexed bitmap (1bpp for 2 colors, 4bpp for ≤16, 8bpp for ≤256)
    • isHighQuality: true uses OkLab perceptual color space (slower, better gradients)
    • isHighQuality: false uses linear RGB with Euclidean distance (faster)
using var original = new Bitmap("photo.png");

// High quality: OkLab color space, Floyd-Steinberg dithering
using var indexed = original.ReduceColors(
    new WuQuantizer(),
    ErrorDiffusion.FloydSteinberg,
    16,
    isHighQuality: true);

// Fast: Linear RGB, serpentine dithering
using var fast = original.ReduceColors(
    new OctreeQuantizer(),
    ErrorDiffusion.Atkinson.Serpentine,
    256,
    isHighQuality: false);

indexed.Save("indexed.gif");
Pixel Art Scaling
  • Upscale(IPixelScaler) - Scale bitmap using a fixed-factor pixel art scaler
using var source = new Bitmap("sprite.png");
using var scaled2x = source.Upscale(Eagle.X2);
using var hq4x = source.Upscale(Hqnx.X4);
Resampling
  • Resample<TResampler>(width, height) - Resample bitmap to arbitrary size using a resampler
  • Resample(IResampler, width, height) - Resample with parameterized resampler instance
using var photo = bitmap.Resample<Lanczos3>(newWidth, newHeight);
using var sharp = bitmap.Resample(new Bicubic(-0.75f), newWidth, newHeight);

Image Extensions (Image)

Multi-Page Support
  • GetPageAt(int page) - Get specific page from multi-page image (e.g., TIFF)
  • GetPageCount() - Get total number of pages in image
Save Operations
  • SaveToPng(FileInfo/string) - Save image as PNG
  • SaveToTiff(string) - Save image as TIFF
  • SaveToJpeg(string/Stream, double quality = 1) - Save as JPEG with quality (0.0-1.0)
Conversions
  • ToIcon(int targetRes = 0) - Convert image to Icon
  • ToBase64DataUri() - Convert to Base64 data URI string
  • FromBase64DataUri(string) (static-like extension on string) - Create image from Base64 data URI
Image Processing
  • MakeGrayscale() - Convert image to grayscale
  • Threshold(byte threshold = 127) - Apply threshold filter (black/white)
  • ApplyPixelProcessor(Func<Color, Color> processor) - Apply custom pixel transformation function
  • MirrorAlongX() - Mirror horizontally
  • MirrorAlongY() - Mirror vertically
  • Resize(int longSide) - Resize to fit within square, keep aspect
  • Resize(int longSide, Color fillColor) - Resize with fill color
  • Resize(int width, int height, bool keepAspect = true, Color? fillColor = null) - Resize with options
  • Resize(int width = -1, int height = -1, InterpolationMode = Default) - Resize with interpolation
  • Rotate(float angle) - Rotate image by angle
  • GetRectangle(Rectangle) - Extract rectangular region
  • ReplaceColorWithTransparency(Color) - Replace specific color with transparency

Color Extensions (Color)

Color Space Conversion
  • Rgb / RgbNormalized - Convert to RGB color space
  • Hsl / HslNormalized - Convert to HSL (Hue, Saturation, Lightness)
  • Hsv / HsvNormalized - Convert to HSV (Hue, Saturation, Value)
  • Hwb / HwbNormalized - Convert to HWB (Hue, Whiteness, Blackness)
  • Cmyk / CmykNormalized - Convert to CMYK (Cyan, Magenta, Yellow, Key)
  • Xyz / XyzNormalized - Convert to CIE XYZ tristimulus values
  • Lab / LabNormalized - Convert to CIE L*a*b* perceptual color space
  • Yuv / YuvNormalized - Convert to YUV (Luma + chrominance)
  • YCbCr / YCbCrNormalized - Convert to YCbCr digital video encoding
  • Din99 / Din99Normalized - Convert to DIN99 (DIN 6176) perceptual space
Color Comparison
  • IsLike(Color other, byte luminanceDelta = 24, byte chromaUDelta = 7, byte chromaVDelta = 6) - Compare colors in YUV space with tolerance
  • IsLikeNaive(Color other, int tolerance = 2) - Simple RGB comparison with tolerance
Color Blending
  • BlendWith(Color other, float current, float max) - Interpolate between two colors

Graphics Extensions (Graphics)

  • DrawString(float x, float y, string text, Font font, Brush brush, ContentAlignment anchor) - Draw text with anchor positioning
  • DrawCross(float/int x, float/int y, float/int size, Pen pen) - Draw cross marker (4 overloads including Point/PointF)
  • DrawCircle(Pen pen, float centerX, float centerY, float radius) - Draw circle outline
  • FillCircle(Brush brush, float centerX, float centerY, float radius) - Draw filled circle

Rectangle Extensions (Rectangle)

  • MultiplyBy(int factor) - Scale rectangle uniformly
  • MultiplyBy(int xfactor, int yfactor) - Scale rectangle with different X/Y factors
  • CollidesWith(Rectangle/RectangleF) - Check rectangle collision
  • CollidesWith(Point/PointF) - Check if point is inside
  • CollidesWith(int x, int y) / CollidesWith(float x, float y) - Check if coordinates are inside
  • Center() - Get center point
  • SetLeft/SetRight/SetTop/SetBottom(int) - Create new rectangle with modified edge

RectangleF Extensions (RectangleF)

(Similar methods to Rectangle, for floating-point rectangles)


Size Extensions (Size)

  • Center() - Get center point

Point Extensions (Point)

(Generated from T4 template - numeric operations on points)


FileInfo Extensions (FileInfo)

  • GetIcon(bool smallIcon = false, bool linkOverlay = false) - Get Windows shell icon for file
    • Uses native SHGetFileInfo API

Custom Types

IBitmapLocker Interface

Format-specific bitmap pixel access implementations providing optimized read/write access to bitmap data. The correct locker is automatically selected based on the bitmap's pixel format when calling Lock().

Locker Pixel Format Bits Description
Argb16161616BitmapLocker Format64bppArgb 64 High dynamic range ARGB (16 bits/channel)
Argb1555BitmapLocker Format16bppArgb1555 16 1-bit alpha + 5 bits RGB
Argb8888BitmapLocker Format32bppArgb 32 Standard 32-bit ARGB (8 bits/channel)
Gray16BitmapLocker Format16bppGrayScale 16 16-bit grayscale
Indexed1BitmapLocker Format1bppIndexed 1 Monochrome indexed (2 colors)
Indexed4BitmapLocker Format4bppIndexed 4 16-color indexed
Indexed8BitmapLocker Format8bppIndexed 8 256-color indexed
PArgb16161616BitmapLocker Format64bppPArgb 64 Premultiplied alpha 64-bit
PArgb8888BitmapLocker Format32bppPArgb 32 Premultiplied alpha 32-bit
Rgb161616BitmapLocker Format48bppRgb 48 High dynamic range RGB (16 bits/channel)
Rgb555BitmapLocker Format16bppRgb555 16 5 bits per RGB channel
Rgb565BitmapLocker Format16bppRgb565 16 5-6-5 bits RGB
Rgb888BitmapLocker Format24bppRgb 24 Standard 24-bit RGB
Rgb888XBitmapLocker Format32bppRgb 32 24-bit RGB with padding byte
SubRegionBitmapLocker Any - Wraps another locker for sub-region access
UnsupportedDrawingBitmapLocker Other - Fallback using GetPixel/SetPixel

Each locker provides:

  • Direct pointer access to pixel data via BitmapData
  • Indexed pixel access via this[x, y]
  • Fast GetPixelBgra8888() and SetPixelBgra8888() methods
  • Drawing primitives: lines, rectangles, circles, ellipses, crosses
  • CopyFrom/BlendWith operations for bitmap compositing
  • Grid-based tile copying for sprite sheets and tile maps
  • Automatic disposal via IDisposable

Color Spaces

A comprehensive color space conversion and comparison library with zero-cost generic abstractions.

Standard Color Space Types

Type Components Category Description
Cmyk / CmykNormalized C, M, Y, K Subtractive Subtractive printing model
Din99 / Din99Normalized L, a, b Perceptual DIN 6176 perceptual space
Hsl / HslNormalized H, S, L Cylindrical Hue, Saturation, Lightness
Hsv / HsvNormalized H, S, V Cylindrical Hue, Saturation, Value
Hwb / HwbNormalized H, W, B Cylindrical Hue, Whiteness, Blackness
Lab / LabNormalized L, a, b Perceptual CIE L*a*b* perceptual color space
Rgb / RgbNormalized R, G, B Standard Standard RGB color model
Xyz / XyzNormalized X, Y, Z HDR CIE XYZ tristimulus values
YCbCr / YCbCrNormalized Y, Cb, Cr YUV Digital video color encoding
Yuv / YuvNormalized Y, U, V YUV Luma + chrominance (PAL/NTSC)

Extended Color Space Types

Internal processing color spaces used in the generic color pipeline:

Type Components Category Description
LchF L, C, h Cylindrical CIE LCh (cylindrical Lab) with hue angle
OklabF L, a, b Perceptual Oklab perceptually uniform color space
OklchF L, C, h Perceptual OkLCh cylindrical form of Oklab
HunterLabF L, a, b Perceptual Hunter Lab color space
LuvF L, u, v Perceptual CIE L*u*v* color space
ICtCpF I, Ct, Cp HDR ICtCp perceptual HDR color space
JzAzBzF Jz, Az, Bz HDR JzAzBz perceptual HDR color space
JzCzhzF Jz, Cz, hz HDR JzCzhz cylindrical form of JzAzBz
AcesCgF R, G, B Wide Gamut ACEScg linear working space for VFX/animation
AdobeRgbF R, G, B Wide Gamut Adobe RGB (1998) wide gamut for print (50% coverage)
DisplayP3F R, G, B Wide Gamut Display P3 (Apple devices, wider than sRGB)
ProPhotoRgbF R, G, B Wide Gamut ProPhoto RGB ultra-wide gamut for photography

Working Color Spaces

Internal processing types used by the quantization and dithering pipeline:

Type Components Description
LinearRgbaF R, G, B, A Linear RGB with alpha (float, non-premultiplied)
LinearRgbF R, G, B Linear RGB without alpha (float)
CmykaF C, M, Y, K, A CMYK with alpha (float)
OklabaF L, a, b, A OkLab with alpha for perceptually uniform operations

Distance Calculators (Hawkynt.ColorProcessing.Metrics)

Color metrics implementing IColorMetric<T> for palette lookups, quantization, and color comparison.

Generic Metrics
Calculator Color Space Squared Variant Description
Euclidean3F<TKey> Any 3-component float EuclideanSquared3F<TKey> $\sqrt{\Delta c_1^2 + \Delta c_2^2 + \Delta c_3^2}$
Euclidean4F<TKey> Any 4-component float EuclideanSquared4F<TKey> $\sqrt{\Delta c_1^2 + \Delta c_2^2 + \Delta c_3^2 + \Delta c_4^2}$
Euclidean3B<TKey> Any 3-component byte EuclideanSquared3B<TKey> Byte version (0-255 per channel)
Euclidean4B<TKey> Any 4-component byte EuclideanSquared4B<TKey> Byte version with alpha
Chebyshev3F<TKey> Any 3-component float - $\max(\lvert\Delta c_1\rvert, \lvert\Delta c_2\rvert, \lvert\Delta c_3\rvert)$
Chebyshev4F<TKey> Any 4-component float - $\max(\lvert\Delta c_1\rvert, \lvert\Delta c_2\rvert, \lvert\Delta c_3\rvert, \lvert\Delta c_4\rvert)$
Chebyshev3B<TKey> Any 3-component byte - Byte version
Chebyshev4B<TKey> Any 4-component byte - Byte version with alpha
Manhattan3F<TKey> Any 3-component float - $\lvert\Delta c_1\rvert + \lvert\Delta c_2\rvert + \lvert\Delta c_3\rvert$
Manhattan4F<TKey> Any 4-component float - $\lvert\Delta c_1\rvert + \lvert\Delta c_2\rvert + \lvert\Delta c_3\rvert + \lvert\Delta c_4\rvert$
Weighted Metrics
Calculator Squared Variant Description
WeightedEuclidean3F<TKey> WeightedEuclideanSquared3F<TKey> $\sqrt{w_1 \Delta c_1^2 + w_2 \Delta c_2^2 + w_3 \Delta c_3^2}$
WeightedEuclidean4F<TKey> WeightedEuclideanSquared4F<TKey> $\sqrt{w_1 \Delta c_1^2 + w_2 \Delta c_2^2 + w_3 \Delta c_3^2 + w_4 \Delta c_4^2}$
WeightedChebyshev3F<TKey> - $\max(w_1\lvert\Delta c_1\rvert, w_2\lvert\Delta c_2\rvert, w_3\lvert\Delta c_3\rvert)$
WeightedManhattan3F<TKey> - $w_1\lvert\Delta c_1\rvert + w_2\lvert\Delta c_2\rvert + w_3\lvert\Delta c_3\rvert$
Perceptual Lab Metrics (Hawkynt.ColorProcessing.Metrics.Lab)
Calculator Squared Variant Reference Description
CIE76 CIE76Squared CIE 1976 $\Delta E^*_{ab}$ - Euclidean in Lab space
CIE94 CIE94Squared CIE 1994 Improved perceptual formula with weighting
CIEDE2000 CIEDE2000Squared CIE 2000 Most accurate perceptual $\Delta E$
CMC - BS 6923 Textile industry (l=1, c=1)
DIN99Distance - DIN 6176 German industrial standard
RGB-Specific Metrics (Hawkynt.ColorProcessing.Metrics.Rgb)
Calculator Squared Variant Reference Description
CompuPhase CompuPhaseSquared Redmean Weighted RGB approximation using mean red
PngQuant PngQuantSquared pngquant Considers blending on black/white backgrounds
Equality Comparators
Comparator Description
ExactEquality<TKey> Exact bit-level match only
ThresholdEquality<TKey> Match within configurable tolerance

Note: Squared variants are faster (no sqrt) when only relative comparison is needed.

Palette Lookup

The PaletteLookup<TWork, TMetric> struct provides efficient nearest-neighbor color matching with automatic caching.

Members
Member Type Description
Count int Number of colors in the palette
this[int index] TWork Get palette color at index
FindNearest(in TWork color) int Find index of nearest palette color
FindNearestColor(in TWork color) TWork Find nearest palette color directly
FindNearest(in TWork color, out TWork nearest) int Get both index and nearest color
Usage
using Hawkynt.ColorProcessing;
using Hawkynt.ColorProcessing.Metrics;
using Hawkynt.ColorProcessing.Working;

// Create palette lookup with a metric
var lookup = new PaletteLookup<LinearRgbaF, EuclideanSquared4F<LinearRgbaF>>(
    workPalette,
    default);

// Get palette size
int paletteSize = lookup.Count;

// Access palette colors directly
LinearRgbaF firstColor = lookup[0];

// Find nearest by index
int index = lookup.FindNearest(targetColor);

// Find nearest color directly
LinearRgbaF nearest = lookup.FindNearestColor(targetColor);

// Get both index and color in one call
int idx = lookup.FindNearest(targetColor, out LinearRgbaF nearestColor);

// Efficient batch processing - results are cached automatically
foreach (var pixel in imagePixels) {
  var paletteIndex = lookup.FindNearest(pixel);  // O(1) for repeated colors
}

// Using different metrics
var labLookup = new PaletteLookup<LabF, CIEDE2000>(labPalette, default);
var rgbLookup = new PaletteLookup<LinearRgbF, CompuPhaseSquared>(rgbPalette, default);

Color Interpolation (System.Drawing.ColorSpaces.Interpolation)

Type Description
CircularHueLerp<T> Hue-aware interpolation for HSL/HSV/HWB
ColorGradient<T> Multi-stop gradient with configurable interpolation
ColorLerp<T> Linear interpolation in any 3-component color space
ColorLerp4<T> Linear interpolation in 4-component spaces (CMYK)
using System.Drawing.ColorSpaces.Interpolation;

// Interpolate in perceptual Lab space
var lerp = new ColorLerp<Lab>();
var midpoint = lerp.Lerp(color1, color2, 0.5f);

// Create smooth gradients
var gradient = new ColorGradient<Hsl>(Color.Red, Color.Blue);
var colors = gradient.GetColors(10);  // 10 evenly-spaced colors

Color Quantization

Quantizers reduce the number of colors in an image to generate optimized palettes. They analyze color distribution and select representative colors that best preserve visual quality.

Adaptive Quantizers

Adaptive quantizers analyze the image to generate an optimal palette for each specific image.

Quantizer Author Year Type Reference
PngQuantQuantizer Kornel Lesinski 2009 Hybrid pngquant algorithm
WuQuantizer Xiaolin Wu 1991 Variance Graphics Gems II
MedianCutQuantizer Paul Heckbert 1982 Splitting SIGGRAPH '82
OctreeQuantizer Gervautz, Purgathofer 1988 Tree Graphics Gems
NeuquantQuantizer Anthony Dekker 1994 Neural Network: Computing
KMeansQuantizer J. MacQueen 1967 Clustering K-means++
BisectingKMeansQuantizer M. Steinbach et al. 2000 Clustering Bisecting K-Means
IncrementalKMeansQuantizer - - Clustering Online K-Means
GaussianMixtureQuantizer Various 1977 Clustering EM Algorithm
ColorQuantizationNetworkQuantizer Various 1992 Neural LVQ
AduQuantizer - - Clustering Competitive learning
VarianceBasedQuantizer - - Variance Weighted variance optimization
VarianceCutQuantizer - - Variance Maximum variance splitting
BinarySplittingQuantizer - - Splitting Principal axis splitting
SpatialColorQuantizer - - Spatial Simulated annealing
FuzzyCMeansQuantizer J.C. Bezdek 1981 Clustering Pattern Recognition. Ref
PopularityQuantizer - - Histogram Most frequent colors
UniformQuantizer - - Fixed Uniform RGB grid
HierarchicalCompetitiveLearningQuantizer P. Scheunders 1997 Clustering Hierarchical CL - initialization-independent progressive splitting
GeneticCMeansQuantizer P. Scheunders 1997 Clustering Genetic Algorithm + C-Means - global optimization avoids local optima
EnhancedOctreeQuantizer D.S. Bloomberg 2008 Tree Enhanced Octree - variance tracking, adaptive thresholds
OctreeSomQuantizer Park, Kim, Cha 2015 Neural Octree-SOM - two-rate learning reduces color loss
HuffmanQuantizer - - Clustering Huffman-inspired bottom-up merging - preserves dominant colors exactly
Quantizer Parameters
Quantizer Parameter Type Default Range Description
PngQuantQuantizer MedianCutIterations int 3 1-10 Median Cut passes with weight adjustment
KMeansIterations int 10 1-100 K-means/Voronoi refinement iterations
ConvergenceThreshold float 0.0001f 0.00001-0.01 K-means convergence threshold
ErrorBoostFactor float 2.0f 1-5 Weight boost for underrepresented colors
KMeansQuantizer MaxIterations int 100 10-1000 Maximum clustering iterations
ConvergenceThreshold float 0.001f 0.0001-0.1 Stop when centroids move less than this
BisectingKMeansQuantizer MaxIterationsPerSplit int 10 1-50 K-means iterations per bisection
BisectionTrials int 3 1-10 Trials per split (keeps best result)
ConvergenceThreshold float 0.001f 0.0001-0.1 Stop when centroids move less than this
IncrementalKMeansQuantizer RefinementPasses int 3 0-10 Additional refinement passes after initial
GaussianMixtureQuantizer MaxIterations int 50 10-500 Maximum EM iterations
ConvergenceThreshold float 0.0001f 0.00001-0.01 Log-likelihood convergence threshold
MinVariance float 0.0001f 0.00001-0.01 Minimum variance (prevents singular matrices)
MaxSampleSize int 10000 1000-100000 Maximum histogram entries to process
ColorQuantizationNetworkQuantizer MaxEpochs int 100 10-500 Training epochs
InitialLearningRate float 0.3f 0.01-1.0 Initial learning rate
ConscienceFactor float 0.1f 0-1 Balanced neuron usage factor
UseFrequencySensitive bool true - Enable frequency-sensitive learning
MaxSampleSize int 10000 1000-100000 Maximum histogram entries to process
AduQuantizer IterationCount int 10 1-100 Competitive learning iterations
NeuquantQuantizer MaxIterations int 100 1-1000 Network training iterations
InitialAlpha float 0.1f 0.01-1.0 Initial learning rate
SpatialColorQuantizer MaxIterations int 100 10-500 Annealing iterations
SpatialWeight float 0.5f 0-1 Weight for spatial coherence
InitialTemperature float 1.0f 0.1-10 Starting annealing temperature
FuzzyCMeansQuantizer MaxIterations int 100 10-500 Clustering iterations
Fuzziness float 2.0f 1.1-5 Cluster overlap (higher = softer)
MaxSampleSize int 10000 1000-100000 Maximum histogram entries to process
HierarchicalCompetitiveLearningQuantizer EpochsPerSplit int 5 1-20 CL training epochs after each cluster split
InitialLearningRate float 0.1f 0.01-0.5 Initial learning rate for CL
MaxSampleSize int 8192 1000-100000 Maximum histogram entries to process
GeneticCMeansQuantizer PopulationSize int 20 10-100 Number of candidate palettes
Generations int 50 10-500 Number of generations to evolve
TournamentSize int 3 2-10 Tournament selection size
MutationSigma float 10.0f 1-50 Gaussian mutation standard deviation
EliteCount int 2 0-10 Elite individuals preserved each generation
CMeansIterationsPerOffspring int 3 1-10 C-Means iterations per offspring
MaxSampleSize int 10000 1000-100000 Maximum histogram entries to process
EnhancedOctreeQuantizer MaxLevel int 5 3-7 Tree depth (2^level max leaves)
ReservedLevel2Colors int 64 0-128 Colors reserved at level 2 for coverage
OctreeSomQuantizer MaxEpochs int 50 10-200 SOM training epochs
WinnerLearningRate float 0.1f 0.01-0.5 Learning rate for BMU
NeighborLearningRate float 0.001f 0.0001-0.01 Learning rate for neighbors (1% of winner)
MaxSampleSize int 8192 1000-100000 Maximum histogram entries to process
HuffmanQuantizer CandidatesToExamine int 20 5-100 Top candidates for merge selection
SimilarityWeight float 10000.0f 100-100000 Balance frequency vs. similarity in merge

Quantizer Wrappers

Wrappers that enhance other quantizers by applying additional preprocessing or post-processing. Wrappers can be chained for combined effects.

Preprocessing Wrappers
Wrapper Description
PcaQuantizerWrapper Transforms colors to PCA-aligned space before quantization. Ref
BitReductionWrapper Reduces color precision by masking off LSBs, creating posterized/retro effects and faster quantization
Postprocessing Wrappers
Wrapper Description
KMeansRefinementWrapper Refines any quantizer's output using iterative K-means-style clustering. Ref
AcoRefinementWrapper Refines palette using Ant Colony Optimization for escaping local optima. Ref
Wrapper Parameters
Wrapper Parameter Type Default Range Description
BitReductionWrapper bitsToRemove int 1 1-7 LSBs to mask off per component (1=128 levels)
KMeansRefinementWrapper iterations int 10 1-100 K-means refinement iterations
AcoRefinementWrapper antCount int 20 1-100 Number of ants exploring solutions
iterations int 50 1-500 ACO iterations
evaporationRate double 0.1 0.0-1.0 Pheromone evaporation rate
seed int? null - Random seed for reproducibility
// Wrap a quantizer with PCA preprocessing
var pcaEnhanced = new PcaQuantizerWrapper<WuQuantizer>(new WuQuantizer());

// Add K-means refinement to any quantizer
var refined = new KMeansRefinementWrapper<MedianCutQuantizer>(new MedianCutQuantizer(), iterations: 10);

// Use ACO for complex color distributions (slower but may escape local optima)
var acoRefined = new AcoRefinementWrapper<OctreeQuantizer>(
  new OctreeQuantizer(),
  antCount: 20,
  iterations: 50,
  seed: 42  // for reproducible results
);

// Reduce color precision for retro/posterized effects (4 bits removed = 16 levels per channel)
var posterized = new BitReductionWrapper<MedianCutQuantizer>(new MedianCutQuantizer(), bitsToRemove: 4);

// Chain wrappers for combined effects: BitReduction -> KMeans -> PCA -> Octree
var chained = new BitReductionWrapper<KMeansRefinementWrapper<PcaQuantizerWrapper<OctreeQuantizer>>>(
  new KMeansRefinementWrapper<PcaQuantizerWrapper<OctreeQuantizer>>(
    new PcaQuantizerWrapper<OctreeQuantizer>(new OctreeQuantizer()),
    iterations: 5),
  bitsToRemove: 2
);

Fixed Palette Quantizers

Fixed palette quantizers use predefined color palettes for specific platforms or standards.

Quantizer Colors Use Case Description
WebSafeQuantizer 216 Web graphics Browser-safe web palette
Ega16Quantizer 16 Retro DOS IBM EGA 16-color palette
Vga256Quantizer 256 Retro DOS VGA default 256-color palette
Cga4Quantizer 4 Retro DOS 6 CGA palettes: Palette0 (Green/Red/Brown), Palette1 (Cyan/Magenta/White), Mode5 (Cyan/Red/White) - each with Low/High intensity
Mac8BitQuantizer 256 Retro Mac Classic Macintosh system palette
MonochromeQuantizer 2 B&W Black and white only
GrayscaleQuantizer 2-256 Grayscale Grayscale ramp
CustomPaletteQuantizer Any Custom User-defined palette

Quantizer Usage

using Hawkynt.ColorProcessing.Quantization;

// Generate palette from colors
var quantizer = new WuQuantizer();
Bgra8888[] palette = quantizer.GeneratePalette(colors, 16);

// Generate from histogram (weighted by frequency)
var histogram = new List<(Bgra8888 color, uint count)> { ... };
Bgra8888[] palette = quantizer.GeneratePalette(histogram, 256);

// Fixed palette
var egaPalette = new Ega16Quantizer().GetPalette();

// Reduce colors with quantization
using var reduced = bitmap.ReduceColors(new WuQuantizer(), ErrorDiffusion.FloydSteinberg, 16);

// High-quality PngQuant-style quantization (variance median cut + K-means refinement)
var pngQuant = new PngQuantQuantizer {
  MedianCutIterations = 3,    // Iterations with weight adjustment for underrepresented colors
  KMeansIterations = 10,      // Voronoi/K-means refinement passes
  ErrorBoostFactor = 2.0f     // Boost for poorly quantized colors
};
using var pngResult = bitmap.ReduceColors(pngQuant, ErrorDiffusion.FloydSteinberg, 256);

K-Means Color Metrics

The KMeansQuantizer supports any IColorMetric<Bgra8888> for clustering. See Color Metrics for all available metrics.

// Default K-Means (squared Euclidean - fastest)
var kmeans = new KMeansQuantizer();

// With perceptual Lab-based distance
var perceptual = new KMeansQuantizer<CIEDE2000>();

// With weighted RGB perception
var weighted = new KMeansQuantizer<PngQuantDistance>(default);

// With custom iterations
var custom = new KMeansQuantizer { MaxIterations = 200, ConvergenceThreshold = 0.0001f };

Dithering

Error diffusion dithering distributes quantization error to neighboring pixels for smoother gradients.

Error-Diffusion Ditherers

Ditherer Author Year Neighbors Reference
Atkinson Bill Atkinson 1984 6 Apple MacPaint, 75% error diffusion. Ref
JarvisJudiceNinke J.F. Jarvis, C.N. Judice, W.H. Ninke 1976 12 CGIP vol. 5. Ref
Pigeon Steven Pigeon 2013 7 Blog post with analysis. Ref
ShiauFan J.N. Shiau, Z. Fan 1993 4 US Patent 5,353,127. Ref
ShiauFan2 J.N. Shiau, Z. Fan 1993 5 US Patent 5,353,127. Ref
StevensonArce R.L. Stevenson, G.R. Arce 1985 12 JOSA A vol. 2. Ref
Stucki P. Stucki 1981 12 IBM Research RZ1060. Ref
Burkes D. Burkes 1988 7 CIS Graphics Support Forum, LIB 15. Ref
Diagonal - - 1 Single diagonal neighbor
Diamond - - 8 Symmetric diamond pattern
DoubleDown - - 3 Two rows down
Down - - 1 Single pixel below
EqualFloydSteinberg - - 4 Equal weight distribution variant
FalseFloydSteinberg - - 3 Simplified 3-neighbor variant
Fan93 Z. Fan 1992 4 SPIE'92, "A Simple Modification of Error Diffusion Weights"
FloydSteinberg R.W. Floyd, L. Steinberg 1976 4 Proc. SID vol. 17, "An Adaptive Algorithm for Spatial Greyscale"
HorizontalDiamond - - 6 Diamond with horizontal bias
Sierra Frankie Sierra 1989 10 Three-line filter, King's Quest era
SierraLite Frankie Sierra 1990 3 Filter Lite - minimal variant
Simple - - 1 Single neighbor diffusion
TwoD - - 2 Simple 2-neighbor
TwoRowSierra Frankie Sierra 1990 7 Two-row variant
VerticalDiamond - - 8 Diamond with vertical bias

Ordered Dithering

Ordered dithering uses threshold matrices to determine pixel output. Unlike error diffusion, pixels can be processed independently (parallelizable).

Ditherer Author Year Size Description
Bayer2x2 Bryce Bayer 1973 2x2 Smallest Bayer threshold matrix
Bayer4x4 Bryce Bayer 1973 4x4 Standard Bayer threshold matrix
Bayer8x8 Bryce Bayer 1973 8x8 Large Bayer matrix (256 levels)
Bayer16x16 Bryce Bayer 1973 16x16 Very large Bayer matrix
ClusterDot4x4 - - 4x4 Clustered dot pattern for smoother appearance
ClusterDot8x8 - - 8x8 Larger cluster dot pattern
Diagonal4x4 - - 4x4 Diagonal line pattern
Halftone4x4 - - 4x4 Simulates halftone printing
Halftone8x8 - - 8x8 Larger halftone pattern
// Ordered dithering with Bayer matrix
var ditherer = OrderedDitherer.Bayer8x8;

// Adjust strength (0.0 - 1.0)
var reduced = OrderedDitherer.Bayer4x4.WithStrength(0.5f);

Noise Dithering

Noise dithering adds random or pseudo-random thresholds before quantization. Can be processed in parallel.

Ditherer Description
WhiteNoise Uniform random threshold with equal energy at all frequencies
BlueNoise Spatially-filtered noise with reduced low-frequency content
PinkNoise 1/f noise, equal energy per octave, more natural-looking
BrownNoise 1/f^2 noise (Brownian motion), strong low-frequency, smooth organic
VioletNoise f noise, high-frequency emphasis, sharp textured appearance
GreyNoise Perceptually uniform noise adjusted for human vision response
InterleavedGradientNoise Deterministic pseudo-random noise for temporal AA. Ref
// Noise dithering
var ditherer = NoiseDitherer.BlueNoise;

// Other noise types
var pink = NoiseDitherer.PinkNoise;     // More natural than white
var brown = NoiseDitherer.BrownNoise;   // Smooth, organic appearance
var violet = NoiseDitherer.VioletNoise; // Sharp, textured
var grey = NoiseDitherer.GreyNoise;     // Perceptually uniform

// Adjust strength and seed
var custom = NoiseDitherer.WhiteNoise.WithStrength(0.8f).WithSeed(12345);

Advanced Ditherers

High-quality ditherers for specialized applications with superior visual quality.

Ditherer Author Year Type Description
Yliluoma1 Joel Yliluoma 2011 Pattern Position-dependent mixing patterns; ref impl
Yliluoma2 Joel Yliluoma 2011 Pattern Improved Yliluoma with candidate counting; ref impl
Yliluoma3 Joel Yliluoma 2011 Pattern Threshold-based mixing; ref impl
Yliluoma4 Joel Yliluoma 2011 Pattern Balanced mixing strategy; ref impl
DbsDitherer Mitchel et al. 1987 Iterative Direct Binary Search optimization
Riemersma Thiadmer Riemersma 1998 Space-filling Hilbert/Peano curve error diffusion
Ostromoukhov Victor Ostromoukhov 2001 Adaptive Variable-coefficient error diffusion
Knoll Thomas Knoll 1990s Pattern Adobe Photoshop pattern dithering
NClosestDitherer - - Pattern N-closest palette color mixing
NConvexDitherer - - Pattern Convex combination of palette colors
VoidAndClusterDitherer Robert Ulichney 1993 Ordered Blue noise via void-and-cluster method
BarycentricDitherer - - Ordered Triangle-based 3-color interpolation with Bayer pattern
TinDitherer - - Ordered Tetrahedral 4-color interpolation with Bayer pattern
NaturalNeighbourDitherer - - Ordered Voronoi-based area-weighted color interpolation
AverageDitherer - - Custom Uses local region averages as thresholds
DizzyDitherer - - ErrorDiffusion Spiral-based error distribution reducing directional artifacts

Adaptive Ditherers

Ditherers that analyze local image content to adjust their behavior.

Ditherer Description
SmartDitherer Automatically selects best ditherer based on local content
AdaptiveDitherer Adjusts error diffusion strength based on local contrast
AdaptiveMatrixDitherer Uses content-aware threshold matrices
GradientAwareDitherer Preserves gradients while dithering flat areas
StructureAwareDitherer Maintains structural features
DebandingDitherer Specifically designed to reduce banding artifacts

Ditherer Configuration

Error diffusion ditherers support two scan modes via separate zero-cost types:

  • ErrorDiffusion - Linear left-to-right scanning
  • ErrorDiffusionSerpentine - Alternating direction per row (reduces directional artifacts)
// Basic usage (linear scan)
var ditherer = ErrorDiffusion.FloydSteinberg;

// Serpentine scanning (returns ErrorDiffusionSerpentine type - zero-cost abstraction)
var serpentine = ErrorDiffusion.FloydSteinberg.Serpentine;

// Switch back to linear if needed
var linear = serpentine.Linear;

// Adjust strength (0.0 - 1.0)
var reduced = ErrorDiffusion.Atkinson.WithStrength(0.75f);

// Combine options (serpentine with reduced strength)
var custom = ErrorDiffusion.JarvisJudiceNinke.Serpentine.WithStrength(0.9f);

Riemersma Ditherer (Space-Filling Curves)

The Riemersma ditherer uses space-filling curves to traverse the image, maintaining spatial locality for better error diffusion. Interactive visualization

Curve Type Subdivision Order Range Coverage per Order
Hilbert 2x2 1-7 2ⁿ x 2ⁿ pixels
Peano 3x3 1-5 3ⁿ x 3ⁿ pixels
Linear - - Serpentine scan
// Pre-configured instances
var hilbert = RiemersmaDitherer.Default;   // Hilbert curve, history size 16
var peano = RiemersmaDitherer.Peano;       // Peano curve, history size 16
var linear = RiemersmaDitherer.LinearScan; // Simple serpentine

// Different history sizes (affects error decay)
var small = RiemersmaDitherer.Small;  // History size 8 (faster)
var large = RiemersmaDitherer.Large;  // History size 32 (higher quality)

// Custom configuration with explicit curve type
var customHilbert = new RiemersmaDitherer(16, SpaceFillingCurve.Hilbert);
var customPeano = new RiemersmaDitherer(16, SpaceFillingCurve.Peano);

// Specify exact curve order (auto-calculated if omitted)
var hilbertOrder4 = new RiemersmaDitherer(16, SpaceFillingCurve.Hilbert, 4);  // 16x16 coverage
var peanoOrder3 = new RiemersmaDitherer(16, SpaceFillingCurve.Peano, 3);      // 27x27 coverage

Image Scaling / Pixel Art Rescaling

The library provides a comprehensive collection of image scaling algorithms, from simple interpolation methods to sophisticated pixel art scalers and retro gaming effects.

Upscaling Methods

using var source = new Bitmap("sprite.png");

// Pixel art scalers
using var scaled2x = source.Upscale(Eagle.X2);
using var scaled3x = source.Upscale(SuperEagle.X2);
using var hq4x = source.Upscale(Hqnx.X4);

// Anti-aliased scaling
using var smaa = source.Upscale(Smaa.X2);

// Edge-preserving smoothing
using var bilateral = source.Upscale(Bilateral.X2);

Available Scalers

Anti-Aliasing
Scaler Author Year Scales Description
Smaa Jorge Jimenez et al. 2012 2x, 3x, 4x Subpixel Morphological Anti-Aliasing - detects edges using luma gradients and applies weighted pixel blending. Presets: X2, X3, X4 with .Low, .Medium, .High, .Ultra quality variants.
Fxaa Timothy Lottes/NVIDIA 2009 2x, 3x, 4x Fast Approximate Anti-Aliasing using luma-based edge detection. Ref
Mlaa Alexander Reshetov 2009 2x, 3x, 4x Morphological Anti-Aliasing using pattern detection (L, Z, U shapes). Ref
ReverseAa Christoph Feck / Hyllian 2011 2x Reverse anti-aliasing using gradient-based tilt computation for smooth edges
Edge-Preserving Filters
Scaler Author Year Scales Description
Bilateral Tomasi & Manduchi 1998 2x, 3x, 4x Edge-preserving smoothing filter combining spatial and range weighting. Presets: X2, X3, X4 with .Soft (sigma_s=2.0, sigma_r=0.3) and .Sharp (sigma_s=1.0, sigma_r=0.1) variants.
Edge-Directed Interpolation
Scaler Author Year Scales Description
Nedi Xin Li & M.T. Orchard 2001 2x, 3x, 4x New Edge-Directed Interpolation using local autocorrelation for adaptive edge-aware upscaling. Ref
Nnedi3 tritical 2010 2x, 3x, 4x Neural Network Edge Directed Interpolation using trained weights for high-quality edge-directed scaling
SuperXbr Hyllian 2015 2x Super-Scale2x Refinement with 2-pass edge-directed scaling and anti-ringing
AnimeLineEnhancer - - 2x, 3x Gradient-based edge enhancement for anime/cartoon content with edge-directed sharpening
Pixel Art Scalers
Scaler Author Year Scales Description
Eagle - 1990s 2x, 3x Classic pixel doubling with corner detection
SuperEagle Kreed 2001 2x Enhanced Eagle with better diagonal handling
Super2xSaI Kreed 1999 2x 2x Scale and Interpolation engine
Epx / Scale2x Andrea Mazzoleni 2001 2x, 3x Edge-preserving pixel expansion
Hqnx Maxim Stepin 2003 2x, 3x, 4x High-quality magnification using YUV comparisons
Lqnx - - 2x, 3x, 4x Low-quality simplified variant of HQnx. Ref
Xbr Hyllian 2011 2x, 3x, 4x xBR (scale By Rules) edge-detection scaler
Xbrz Zenju 2012 2x-6x Enhanced xBR with improved edge handling
Sal Kreed 2001 2x Simple Assembly Language scaler with anti-aliasing
Sabr Joshua Street 2012 2x-4x Scalable Bicubic Renderer with multi-angle (45/30/60) edge detection and smoothstep blending. Variants: SabrSharp (more edges), SabrSmooth (softer)
Mmpx Morgan McGuire 2021 2x Modern AI-inspired pixel art scaling
Omniscale libretro 2015 2x-6x Multi-method hybrid scaler
RotSprite Xenowhirl 2007 2x-4x Rotation-aware pixel art scaling
Clean - - 2x, 3x Clean edge pixel art scaler
TriplePoint Hawkynt 2011 2x, 3x 3x scaler using diagonal color analysis
ScaleNxSfx Sp00kyFox 2013 2x, 3x ScaleNx with effects (corner blending)
ScaleNxPlus Hawkynt 2011 2x, 3x Enhanced ScaleNx with better diagonals
ScaleHq Hawkynt 2011 2x, 3x HQ-style pixel art scaler
EpxB SNES9x Team 2003 2x Enhanced EPX with complex edge detection
EpxC - - 2x EPX variant with additional edge cases. Ref
Des FNES Team 2000 1x Diagonal Edge Scaling filter (pre-processing)
Des2 FNES Team 2000 2x DES with 2x scaling using edge-directed scaling
Scl2x FNES Team 2000 2x Simple corner-based line scaling
ScaleFx Sp00kyFox 2014 3x Scale3x with enhanced edge detection
Edge ScummVM Team 2001 2x, 3x, 4x Simple edge enhancement for smoother diagonals
TwoXpm Pablo Medina - 2x High-quality 2x pixel-art scaler with edge morphing
Saa5050 Mullard 1980 2x3 Teletext character smoothing (original hardware IC)
Simple & Utility Scalers
Scaler Author Scales Description
NearestNeighbor - Nx Simple pixel duplication
Bilinear - Nx Linear interpolation
Bicubic - Nx Cubic spline interpolation
Lanczos - Nx Sinc-windowed interpolation
Normal - 2x, 3x, 4x Fixed-factor pixel duplication
Pixellate - Nx Pixelation/mosaic effect
BilinearPlus VBA Team 2x VBA weighted bilinear interpolation (5:2:1 weighting)
SharpBilinear LibRetro 2x, 3x, 4x Integer prescaling + bilinear for crisp pixels
Quilez Inigo Quilez 2x, 3x, 4x Quintic smoothstep interpolation for smooth gradients. Ref
NearestNeighborPlus - 2x, 3x, 4x Enhanced nearest neighbor with edge detection
Soft - 2x, 3x, 4x Soft interpolation with gentle blending
SoftSmart - 2x, 3x, 4x Smart soft interpolation with adaptive blending
Cut - 2x, 3x, 4x Cut-based scaling utility
Ddt Sp00kyFox 2x Diagonal De-interpolation Technique
CatmullRom - 2x, 3x, 4x Catmull-Rom spline interpolation (pixel-art variant)
Aann jimbo1qaz/wareya 2x, 3x Anti-aliased nearest neighbor with gamma-corrected bilinear interpolation
Nis NVIDIA 2x, 3x Edge-adaptive spatial upscaler with directional sharpening
Retro Display Effects
Scaler Author Scales Description
DotMatrix ScummVM 2x, 3x, 4x Dot-matrix display simulation with brightness falloff
LcdGrid - 2x, 3x, 4x LCD subpixel grid simulation
ScanlineHorizontal Hawkynt 2x1 CRT vertical scanline effect
ScanlineVertical Hawkynt 1x2 CRT horizontal scanline effect
Tv2x / Tv3x / Tv4x - 2x, 3x, 4x TV scanline simulation
MameRgb MAME Team 2x, 3x LCD RGB subpixel channel filter simulation
MameAdvInterp MAME Team 2x, 3x MAME advanced interpolation with scanline effect
HawkyntTv Hawkynt 2x, 3x, 4x TV effect with configurable scanline and phosphor patterns
CrtEasymode - 2x, 3x, 4x Lightweight CRT simulation with scanlines and phosphor mask
CrtHyllian Hyllian 2x, 3x, 4x Sharp CRT scanlines with phosphor simulation
CrtLottes Timothy Lottes 2x, 3x, 4x CRT simulation with bloom and phosphor mask
ZfastCrt - 2x, 3x, 4x Performance-optimized CRT simulation
GameBoyShader - 2x, 3x, 4x Game Boy Color LCD simulation with pixel grid
LcdGhosting - 2x, 3x, 4x LCD response time blur simulation
Ntsc blargg 2x NTSC composite video color bleeding simulation
CrtGeom libretro 2x, 3x CRT simulation with shadow mask and scanline darkening
CrtCaligari Caligari 2x, 3x Performance-focused CRT with electron beam spot simulation
CrtRoyale TroggleMonkey 2x, 3x Advanced CRT with phosphor masks, bloom, and halation
Gtu Aliaspider 2x, 3x Gaussian TV upscaler with bandwidth simulation and scanlines

Downscaling

Scaler Scales Description
BoxDownscale 1/2, 1/3, 1/4, 1/5 Box filter downscaling by averaging NxN blocks of source pixels

Scaler Configuration

Many scalers support configuration options:

// SMAA quality levels
using var low = source.Upscale(Smaa.X2.Low);
using var ultra = source.Upscale(Smaa.X2.Ultra);

// Bilateral filter parameters
using var soft = source.Upscale(Bilateral.X2.Soft);    // sigma_s=2.0, sigma_r=0.3
using var sharp = source.Upscale(Bilateral.X2.Sharp);  // sigma_s=1.0, sigma_r=0.1
using var custom = source.Upscale(new Bilateral(3, 1.5f, 0.2f));

// Scanline brightness
using var scanlines = source.Upscale(new ScanlineHorizontal(brightness: 0.3f));

Image Resamplers

High-quality interpolation filters for arbitrary scaling to any resolution. Unlike pixel art scalers that work at fixed integer factors, resamplers use mathematical kernels to compute pixel values at any scale.

Resampling Methods

using Hawkynt.ColorProcessing.Resizing.Resamplers;

// Generic type syntax (parameterless)
using var result = bitmap.Resample<Lanczos3>(newWidth, newHeight);
using var result = bitmap.Resample<MitchellNetravali>(newWidth, newHeight);

// Instance syntax (parameterized)
using var result = bitmap.Resample(new Bicubic(-0.75f), newWidth, newHeight);
using var result = bitmap.Resample(new Gaussian(sigma: 1.0f), newWidth, newHeight);

Basic Filters

Resampler Radius Description
NearestNeighbor 1 Point sampling, fastest. Ref
Bilinear 1 2x2 weighted average. Ref
Box 1+ Simple averaging. Ref
Hermite 1 Smooth cubic polynomial. Ref
Cosine 1 Cosine-weighted interpolation. Ref
Smoothstep 1 Hermite polynomial S-curve interpolation. Ref

Cubic Family

Resampler Author Year Radius Parameters Reference
Bicubic Robert Keys 1981 2 a (-0.5f) Keys coefficient. Ref
MitchellNetravali Mitchell, Netravali 1988 2 b (1/3), c (1/3) Balanced cubic. Ref
CatmullRom Catmull, Rom 1974 2 None Sharp spline (B=0, C=0.5). Ref
Robidoux Nicolas Robidoux 2011 2 None Optimized for photos. Ref
RobidouxSharp Nicolas Robidoux 2011 2 None Sharper variant. Ref
RobidouxSoft Nicolas Robidoux 2011 2 None Smoother variant. Ref

Lanczos Family

Resampler Radius Sharpness Ringing Best For
Lanczos2 2 Good Low General use. Ref
Lanczos3 3 Very good Moderate Photos (recommended). Ref
Lanczos4 4 Excellent Higher Maximum sharpness. Ref
Lanczos5 5 Maximum Significant Special cases. Ref
Jinc 3+ Excellent Moderate 2D (uses Bessel J1). Ref

B-Spline & O-MOMS

Resampler Degree Radius Prefilter Description
BSpline 3 2 Required Cubic B-spline. Ref
BSpline2 2 2 Required Quadratic. Ref
BSpline4 4 3 Required Quartic (Parzen). Ref
BSpline5 5 3 Required Quintic. Ref
BSpline7 7 4 Required Septic. Ref
OMoms3 3 2 Required Optimal cubic. Ref
OMoms5 5 3 Required Optimal quintic. Ref
OMoms7 7 4 Required Optimal septic. Ref

Spline & Window Filters

Resampler Radius Used By Description
Spline16 2 VLC 4-tap spline. Ref
Spline36 3 FFmpeg 6-tap spline. Ref
Spline64 4 ImageMagick 8-tap spline. Ref
Blackman 3+ - Very low sidelobes. Ref
Kaiser 3+ - Adjustable via beta parameter. Ref
Hann 3+ - Raised cosine. Ref
Hamming 3+ - Modified Hann. Ref
Welch 3+ - Parabolic window. Ref
Bartlett 3+ - Triangular window. Ref
Bohman 3+ - Cosine-convolved window. Ref
Nuttal 3+ - 4-term Blackman-Harris variant. Ref
BlackmanNuttal 3+ - Blackman-Nuttal hybrid. Ref
BlackmanHarris 3+ - 4-term Blackman-Harris. Ref
FlatTop 3+ - Very flat passband. Ref
Tukey 3+ - Tapered cosine window. Ref
Poisson 3+ - Exponential decay window. Ref
BartlettHann 3+ - Bartlett-Hann hybrid. Ref
Cauchy 3+ - Cauchy/Lorentz distribution window. Ref
Schaum2 2 - Quadratic Schaum interpolation. Ref
Schaum3 3 - Cubic Schaum interpolation. Ref

Lagrange Polynomial Interpolation

Resampler Degree Radius Description
Lagrange3 3 2 Cubic (4-point). Ref
Lagrange5 5 3 Quintic (6-point). Ref
Lagrange7 7 4 Septic (8-point). Ref

Note: Lagrange interpolation passes exactly through all sample points, making it suitable for applications requiring exact value preservation. No prefiltering is required.

Edge-Directed & Modern Upscalers

Resampler Author Year Radius Parameters Description
Dcci Li, Orchard 2001 2 cubicA, coherenceThreshold Edge-directed interpolation. Ref
Fsr AMD 2021 2 sharpness (0.5f) FidelityFX Super Resolution. Ref
Ravu - 2017 2 sharpness, antiRinging Robust Adaptive Video Upscaling. Ref
Eedi2 tritical 2005 2 - Enhanced Edge-Directed Interp. Ref
KrigBilateral - - 3 sigma, radius Kriging-based bilateral upscaling. Ref
KopfLischinski Kopf, Lischinski 2011 2 - Depixelizing pixel art (SIGGRAPH 2011). Ref
Icbi Li, Orchard 2001 2 coherenceThreshold, correctionFactor Curvature-based interpolation with structure tensor analysis
Bedi - 2010 2 edgeThreshold (30f) Bilinear edge-directed interpolation with Sobel gradient classification
AdvancedAa guest(r) 2006 2 - Edge-weighted anti-aliasing interpolation

Content-Aware Resizers

Resampler Author Year Description
SeamCarving Avidan, Shamir 2007 Content-aware resizing by inserting/removing minimum-energy seams

SeamCarving supports three energy calculation modes via SeamCarvingEnergyMode:

  • Gradient - Simple gradient magnitude using absolute color differences (fastest)
  • Sobel - Sobel operator for gradient magnitude (balanced)
  • Forward - Forward energy considers insertion cost (best quality, slowest)
// Content-aware resize (removes/adds low-energy seams)
using var result = bitmap.Resample(new SeamCarving(SeamCarvingEnergyMode.Sobel), newWidth, newHeight);

Specialized Filters

Resampler Author Radius Parameters Description
Gaussian Gauss 2+ sigma (0.5f), radius Gaussian blur/interpolation. Ref
NoHalo Nicolas Robidoux 3 None Minimizes halo artifacts. Ref
LoHalo Nicolas Robidoux 3 None Low-halo variant. Ref
MagicKernelSharp John Costella 2 sharpness 4-tap max sharpness kernel. Ref

Resampler Parameters

Resampler Parameter Type Default Range Description
Bicubic a float -0.5f -1 to 0 Keys coefficient (-0.5=standard, -0.75=sharper)
MitchellNetravali b float 0.333f 0-1 Blur parameter
c float 0.333f 0-1 Ringing parameter
Kaiser radius int 3 1-10 Filter radius
beta float 8.6f 0-20 Shape parameter
Gaussian sigma float 0.5f 0.1-5 Standard deviation
Fsr sharpness float 0.5f 0-1 Sharpness level
Ravu sharpness float 0.5f 0-1 Sharpness level
antiRinging float 0.5f 0-1 Anti-ringing strength
Dcci cubicA float -0.5f -1 to 0 Cubic coefficient
coherenceThreshold float 0.3f 0-1 Edge detection threshold
Icbi coherenceThreshold float 0.3f 0-1 Edge coherence threshold
correctionFactor float 0.2f 0-1 Curvature correction strength
Bedi edgeThreshold float 30f 0-255 Edge detection threshold (lower = more edges)
SeamCarving energyMode enum Gradient - Energy calculation mode

Resampler Usage Examples

// High-quality photo scaling
using var photo = bitmap.Resample<Lanczos3>(newWidth, newHeight);

// Balanced quality (recommended for most uses)
using var balanced = bitmap.Resample<MitchellNetravali>(newWidth, newHeight);

// Sharp results with custom bicubic
using var sharp = bitmap.Resample(new Bicubic(-0.75f), newWidth, newHeight);

// Edge-preserving upscaling
using var edges = bitmap.Resample(Dcci.Sharp, newWidth, newHeight);

// Modern AI-like upscaling
using var fsr = bitmap.Resample(Fsr.Sharp, newWidth, newHeight);

// Halo-free scaling
using var nohalo = bitmap.Resample<NoHalo>(newWidth, newHeight);

// Smooth Gaussian
using var smooth = bitmap.Resample(new Gaussian(1.0f), newWidth, newHeight);

// Depixelize pixel art
using var depixelized = bitmap.Resample<KopfLischinski>(newWidth, newHeight);

// Content-aware resize
using var contentAware = bitmap.Resample(new SeamCarving(SeamCarvingEnergyMode.Forward), newWidth, newHeight);

Algorithm Coverage

This library provides comprehensive coverage of resampling algorithms from major image processing libraries:

Source Library Algorithms Covered Notes
ImageMagick Point, Box, Triangle, Hermite, Cubic, Catrom, Mitchell, Lanczos, Spline, Gaussian, Kaiser, Blackman, Hann, Hamming, Jinc, Robidoux variants, Parzen (BSpline4), Lagrange, and all window functions Full coverage
FFmpeg libswscale Point, Bilinear, Bicubic, Lanczos, Spline16, Spline36, Gaussian, Sinc, Area Full coverage
GEGL NoHalo, LoHalo Full coverage
bisqwit.iki.fi Yliluoma 1-4, Knoll pattern dithering Full coverage

Runtime Discovery

The library provides registry classes for runtime enumeration of all available algorithms. These are useful for building UIs, benchmarking, or dynamically selecting algorithms.

ScalerRegistry

Discovers all pixel art scalers and resamplers at runtime.

using Hawkynt.ColorProcessing.Resizing;

// List all available scalers
foreach (var scaler in ScalerRegistry.PixelScalers)
  Console.WriteLine($"{scaler.Name} ({scaler.Scale})");

// List all resamplers
foreach (var resampler in ScalerRegistry.Resamplers)
  Console.WriteLine($"{resampler.Name}");

QuantizerRegistry

Discovers all quantization algorithms at runtime.

using Hawkynt.ColorProcessing.Quantization;

// List all available quantizers
foreach (var quantizer in QuantizerRegistry.All)
  Console.WriteLine($"{quantizer.Name} ({quantizer.Type})");

// Find by name
var octree = QuantizerRegistry.FindByName("Octree");

// Create an instance
var instance = QuantizerRegistry.All.First(q => q.Name == "Octree").CreateDefault();

DithererRegistry

Discovers all dithering algorithms and presets at runtime.

using Hawkynt.ColorProcessing.Dithering;

// List all available ditherers
foreach (var ditherer in DithererRegistry.All)
  Console.WriteLine($"{ditherer.Name} ({ditherer.Type})");

// Find specific ditherer
var floydSteinberg = DithererRegistry.FindByName("ErrorDiffusion_FloydSteinberg");

// Filter by type
var errorDiffusion = DithererRegistry.GetByType(DitheringType.ErrorDiffusion);

Image Filters

The library provides a pixel filter infrastructure for 1:1 image transformations that don't change dimensions. Filters use the same high-performance kernel pipeline as scalers but produce same-size output.

Filter Methods

using Hawkynt.ColorProcessing.Filtering.Filters;
using Hawkynt.Drawing;

// Color corrections
using var bright = source.ApplyFilter(new Brightness(0.2f));
using var adjusted = source.ApplyFilter(new BrightnessContrast(0.1f, 0.3f));
using var warm = source.ApplyFilter(new ColorTemperature(0.5f));
using var corrected = source.ApplyFilter(new Gamma(2.2f));
using var inverted = source.ApplyFilter(Invert.Default);
using var vintage = source.ApplyFilter(new Sepia(0.8f));
using var poster = source.ApplyFilter(new Posterize(4));

// HSL adjustments
using var saturated = source.ApplyFilter(new HueSaturation(0f, 0.3f, 0f));
using var vibrant = source.ApplyFilter(new Vibrance(0.5f));

// Enhancement
using var sharp = source.ApplyFilter(Sharpen.Default);
using var blurred = source.ApplyFilter(GaussianBlur.Default);
using var blurred5x5 = source.ApplyFilter(new GaussianBlur(2, 2));
using var blurredLarge = source.ApplyFilter(new GaussianBlur(10, 10));
using var denoised = source.ApplyFilter(MedianFilter.Default);
using var denoisedLarge = source.ApplyFilter(new MedianFilter(5));
using var sharpened = source.ApplyFilter(new UnsharpMask(1.5f, 0.05f));
using var sharpenedLarge = source.ApplyFilter(new UnsharpMask(1.5f, 0.05f, 5, 5));
using var smoothed = source.ApplyFilter(new BilateralFilter(3, 3f, 0.1f));
using var dilated = source.ApplyFilter(new Dilate(3));
using var eroded = source.ApplyFilter(new Erode(3));

// Edge detection & analysis
using var edges = source.ApplyFilter(SobelEdge.Default);
using var binary = source.ApplyFilter(new Threshold(0.5f));
using var red = source.ApplyFilter(new ChannelExtraction(ColorChannel.Red));
using var morphEdges = source.ApplyFilter(new MorphologicalGradient(2));

// Artistic
using var duo = source.ApplyFilter(Duotone.Default);
using var falseCol = source.ApplyFilter(FalseColor.Default);
using var boxBlurred = source.ApplyFilter(new BoxBlur(5, 5));
using var painterly = source.ApplyFilter(new Kuwahara(3));
using var vignetted = source.ApplyFilter(new Vignette(0.5f, 0.75f));
using var chromatic = source.ApplyFilter(new ChromaticAberration(2f));
using var nightVis = source.ApplyFilter(NightVision.Default);
using var thermal = source.ApplyFilter(new Thermal(0.8f));
using var oilPaint = source.ApplyFilter(new OilPainting(3, 20));
using var sketch = source.ApplyFilter(new PencilSketch(0.8f, 1));
using var waterCol = source.ApplyFilter(new Watercolor(2, 6));
using var pixelated = source.ApplyFilter(new Pixelate(8));
using var halftoned = source.ApplyFilter(new Halftone(6, 45f));
using var selective = source.ApplyFilter(new SelectiveDesaturation(0f, 30f, 1f));
using var bloomed = source.ApplyFilter(new Bloom(0.7f, 1f, 3));
using var glowing = source.ApplyFilter(new GlowingEdges(0.8f, 2f));
using var cartoon = source.ApplyFilter(new Cartoon(6, 0.1f, 1));
using var neon = source.ApplyFilter(new Neon(1f, 2f));

// Distortion
using var twirled = source.ApplyFilter(new Twirl(45f, 0.5f));
using var rippled = source.ApplyFilter(new Ripple(5f, 20f, 0f));
using var spherized = source.ApplyFilter(new Spherize(0.5f));
using var frosted = source.ApplyFilter(FrostedGlass.Default);
using var waved = source.ApplyFilter(new Wave(5f, 30f, 5f, 30f));

// Noise
using var noisy = source.ApplyFilter(new AddNoise(0.1f));
using var despeckled = source.ApplyFilter(Despeckle.Default);
using var denoised2 = source.ApplyFilter(new ReduceNoise(0.5f, 2));

// High-quality mode uses OkLab perceptual color space
using var hqSharp = source.ApplyFilter(Sharpen.Default, ScalerQuality.HighQuality);

Available Filters

Color Correction
Filter Description
BleachBypass Film look: desaturated, high-contrast, muted colors simulating skipped bleach step
Brightness Adjust brightness by adding offset to RGB channels
BrightnessContrast Combined brightness and contrast adjustment
ChannelMixer Recombine R/G/B channels with arbitrary 3x3 coefficient matrix
ColorBalance Adjust color balance independently in shadows, midtones, and highlights (9 parameters)
ColorTemperature Adjust color temperature (warm/cool shift)
ColorTint Adjust green-magenta color tint
Contrast Adjust contrast by scaling around midpoint
CrossProcess Simulates cross-processed film (E6 in C41 chemistry) with shifted curves and boosted saturation
Exposure Adjust exposure in stops (power-of-two scaling)
Gamma Apply gamma correction curve
Grayscale Convert to grayscale via luminance
HDRToneMap Reinhard tone mapping operator for compressing high dynamic range
HueSaturation Adjust hue, saturation, and lightness in HSL space
Invert Invert all color channels
Levels Input/output level remapping with midtone gamma
Posterize Reduce color levels per channel
SelectiveDesaturation Desaturates all colors except a chosen hue range (grayscale with conditional coloring)
Sepia Apply sepia tone using standard color matrix
Solarize Invert channels above threshold
Vibrance Smart saturation boost targeting desaturated pixels
VonKries Chromatic adaptation via Bradford transform (white point correction)
AutoLevels Local auto-levels contrast stretching based on neighborhood min/max (always uses frame access)
Equalize Local histogram equalization mapping via CDF in neighborhood (always uses frame access)
SigmoidContrast S-curve sigmoid contrast adjustment per channel (always uses frame access)
Enhancement
Filter Description
BilateralFilter Edge-preserving bilateral smoothing (spatial + range Gaussian weighting; always uses frame access)
Blur 3x3 weighted blur
Clarity Local contrast enhancement targeting midtones (always uses frame access)
Dehaze Remove atmospheric haze by estimating and subtracting minimum channel (always uses frame access)
Dilate Morphological dilation (max luminance) with configurable radius (uses frame access for radius > 2)
Emboss 3x3 emboss convolution with gray bias
Erode Morphological erosion (min luminance) with configurable radius (uses frame access for radius > 2)
GaussianBlur Gaussian blur with arbitrary kernel size (radiusX/radiusY; uses frame access for radius > 2)
HighPass High-pass filter with arbitrary blur radius (original minus low-pass + 0.5 bias; uses frame access for radius > 2)
MedianFilter Median filter for noise reduction with configurable radius (uses frame access for radius > 2)
MotionBlur Directional motion blur along a configurable angle and length (always uses frame access)
RadialBlur Radial blur emanating from a configurable center point (always uses frame access)
Sharpen 3x3 unsharp mask sharpening
SpinBlur Circular/rotational blur around a configurable center point (always uses frame access)
SurfaceBlur Edge-preserving blur that only averages neighbors within a color threshold (always uses frame access)
UnsharpMask Unsharp mask sharpening with threshold and arbitrary blur radius (uses frame access for radius > 2)
ZoomBlur Zoom/radial blur along the direction from center through each pixel (always uses frame access)
BokehBlur Polygonal disc-shaped blur with bright spot emphasis (always uses frame access)
SmartBlur Edge-preserving blur with hard color difference threshold (always uses frame access)
SmartSharpen Deconvolution-style sharpening with edge magnitude threshold (always uses frame access)
Analysis
Filter Description
AccentedEdges Sobel edges with brightness and smoothness modulation (always uses frame access)
Channel Extraction Extract single color channel as grayscale
LaplacianEdge Laplacian edge detection
MorphologicalGradient Edge detection via morphological gradient (dilate - erode; uses frame access for radius > 2)
PrewittEdge Prewitt edge detection (equal-weight gradient)
SobelEdge Sobel edge detection (gradient magnitude)
Threshold Binary threshold based on luminance
TraceContour Contour tracing that outputs white where gradient crosses a threshold (always uses frame access)
CannyEdge Canny edge detection with double threshold hysteresis (always uses frame access)
FindEdges Simple Sobel edge detection showing white edges on black background (always uses frame access)
Artistic
Filter Description
Bloom Glow around bright areas with threshold and radial glow (always uses frame access)
BoxBlur Uniform box blur with configurable kernel size (radiusX/radiusY; uses frame access for radius > 2)
Cartoon Color quantization with edge darkening for cartoon/cel-shaded appearance (always uses frame access)
ChromaticAberration Simulates lens chromatic aberration with radial RGB channel shifting (always uses frame access)
ColoredPencil Colored pencil sketch preserving hue via HSL edge modulation (always uses frame access)
ColorHalftone Per-CMYK-channel halftone dots at different screen angles (always uses frame access)
Crosshatch Multi-angle line hatching where line density varies with luminance (always uses frame access)
Crystallize Grid-based Voronoi cell tessellation with seed-point coloring (always uses frame access)
Cutout Simplified paper-cutout effect via smoothing and posterization (always uses frame access)
DiffuseGlow Bright area glow with optional grain for dreamy effect (always uses frame access)
DryBrush Simplified oil-painting with configurable brush size and levels (always uses frame access)
Duotone Map luminance to shadow/highlight color gradient
Engrave Engraving-style line density that varies with luminance (always uses frame access)
FalseColor Map luminance to three-stop color gradient
Fragment Average of multiple rotated/offset copies for ghosting effect (always uses frame access)
GlowingEdges Neon-colored edges on dark background (always uses frame access)
Grain Deterministic photographic film grain based on position hash (always uses frame access)
Halftone Print-style circular dot pattern simulating newspaper printing (always uses frame access)
InkOutlines Multiply original color by edge-darkness factor for ink outline appearance (always uses frame access)
Kuwahara Painterly filter using quadrant variance analysis (always uses frame access)
LensFlare Procedural lens flare with radial glow and ray pattern (always uses frame access)
LightingEffects Phong-like directional shading using luminance as height map (always uses frame access)
Mosaic Tile mosaic with dark grout lines between blocks (always uses frame access)
Neon Neon glow edges with color spread and additive blending (always uses frame access)
NightVision Green monochrome with amplified brightness simulating night-vision goggles
OilPainting Quantized luminance-binned color averaging for painterly effect (always uses frame access)
OldPhoto Combined vintage: sepia tone + reduced contrast + warm color shift
PaletteKnife Directional smoothing following gradient for palette knife strokes (always uses frame access)
PencilSketch Edge detection inverted and blended with grayscale for sketch appearance (always uses frame access)
Pixelate Mosaic effect replacing blocks of pixels with their average color (always uses frame access)
Pointillize Circular dot pattern on paper background simulating pointillism (always uses frame access)
PosterEdges Color posterization combined with edge darkening (always uses frame access)
Relief 3D relief effect with directional light source from luminance heightmap
StainedGlass Voronoi cell tessellation with dark borders between cells (always uses frame access)
Thermal False-color thermal/infrared mapping via 5-stop color ramp
TiltShift Position-dependent selective blur with sharp focus band (always uses frame access)
Vignette Radial vignette darkening effect (always uses frame access)
Watercolor Watercolor painting simulation with color quantization and soft edges (always uses frame access)
AngledStrokes Directional brush strokes at configurable angle (always uses frame access)
BasRelief Bas-relief sculptural shading from directional edges (always uses frame access)
ChalkAndCharcoal Chalk and charcoal sketch effect on gray paper (always uses frame access)
Charcoal Charcoal sketch using edge detection and threshold (always uses frame access)
ConteCrayon Conte crayon with foreground/background color mapping (always uses frame access)
Craquelure Surface crack texture overlay with noise displacement (always uses frame access)
DarkStrokes Dark stroke painting emphasizing shadows (always uses frame access)
Facet Weighted median color by similarity in neighborhood (always uses frame access)
Fresco Fresco painting with textured surface noise (always uses frame access)
GlassTile Glass tile distortion with lens bulge effect per tile (always uses frame access)
GraphicPen Graphic pen with directional edge strokes (always uses frame access)
HalftonePattern Ordered dither halftone pattern (dot/line/cross types) (always uses frame access)
NotePaper Note paper sketch with emboss relief and grain (always uses frame access)
Patchwork Patchwork quilt effect with emboss-style relief edges (always uses frame access)
Photocopy Photocopy effect with adjustable detail and darkness (always uses frame access)
PlasticWrap Plastic wrap effect with specular highlights from edges (always uses frame access)
Reticulation Film grain reticulation modulated by luminance (always uses frame access)
RoughPastels Rough pastel strokes with canvas texture overlay (always uses frame access)
SmudgeStick Smudge stick painting with highlight brightening (always uses frame access)
SoftGlow Soft glow via screen blend of blurred highlights (always uses frame access)
Spatter Paint spatter with hash-based displacement and smoothing (always uses frame access)
Sponge Sponge texture with high-contrast luminance bins (always uses frame access)
Stamp Rubber stamp effect with luminance threshold (always uses frame access)
Texturizer Procedural texture overlay (brick/burlap/canvas/sandstone) with relief (always uses frame access)
Tiles Offset tile blocks with random displacement and dark gaps (always uses frame access)
TornEdges Stamp effect with noisy displaced edges (always uses frame access)
Underpainting Underpainting with large brush oil-painting and texture (always uses frame access)
WaterPaper Water paper texture with directional blur and fiber grain (always uses frame access)
Distortion
Filter Description
FrostedGlass Random pixel displacement via positional hash for frosted glass effect (always uses frame access)
LensDistortion Brown-Conrady barrel/pincushion lens distortion model (always uses frame access)
Pinch Radial compress/expand within configurable radius (always uses frame access)
PolarCoordinates Convert between rectangular and polar coordinate systems (always uses frame access)
Ripple Sinusoidal displacement perpendicular to a configurable angle (always uses frame access)
Spherize Spherical refraction distortion (always uses frame access)
Spread Random neighbor displacement for scatter effect (always uses frame access)
Turbulence Fractal noise displacement using value noise with octave summation (always uses frame access)
Twirl Spiral rotation decreasing from center to edge (always uses frame access)
Wave Independent X/Y sinusoidal displacement with configurable amplitude and wavelength (always uses frame access)
Wind Directional pixel streaks at bright edges simulating wind (always uses frame access)
Bulge Radial bulge/pinch power-law distortion from center (always uses frame access)
Dents Noise-based surface dent displacement distortion (always uses frame access)
OceanRipple Dual-axis sinusoidal ocean ripple distortion (always uses frame access)
Offset Wrap-around pixel offset displacement (always uses frame access)
Shear Linear horizontal or vertical shear displacement (always uses frame access)
ZigZag Radial zigzag sinusoidal displacement from center (always uses frame access)
Noise
Filter Description
AddNoise Deterministic positional hash noise, monochromatic or per-channel (always uses frame access)
Despeckle Hybrid median filter combining horizontal, vertical, and diagonal medians (always uses frame access)
DustAndScratches Replace outlier pixels with neighborhood median (always uses frame access)
Mezzotint Random dot pattern where density matches luminance (always uses frame access)
ReduceNoise Non-local means approximation weighting neighbors by color similarity (always uses frame access)
Diffuse Random positional hash displacement noise (always uses frame access)
Render
Filter Description
Clouds Procedural multi-octave value noise clouds blended with source (always uses frame access)
DifferenceClouds Difference blend of procedural noise with source image (always uses frame access)
Fibers Vertical fiber texture with noise modulation blended with source (always uses frame access)
PlasmaTexture Multi-octave plasma noise with per-channel phase offset (always uses frame access)
Supernova Radial starburst light rays with spoke pattern added to source (always uses frame access)
Morphology
Filter Description
BottomHat Black bottom-hat: closing minus original highlights dark details (always uses frame access)
Closing Morphological closing: dilation then erosion (always uses frame access)
Opening Morphological opening: erosion then dilation (always uses frame access)
TopHat White top-hat: original minus opening highlights bright details (always uses frame access)

Filter Discovery

using Hawkynt.ColorProcessing.Filtering;

// Enumerate all available filters
foreach (var filter in FilterRegistry.All)
  Console.WriteLine($"{filter.Name} ({filter.Category})");

// Find by name or category
var vonKries = FilterRegistry.FindByName("VonKries");
var analysisFilters = FilterRegistry.GetByCategory(FilterCategory.Analysis);

// Apply via descriptor (reflection-based, useful for UI/tooling)
var desc = FilterRegistry.FindByName("Blur");
using var result = desc.Apply(source);

Blend Modes

The library provides 27 blend modes for compositing bitmaps, covering all standard categories from image editing applications. Blend modes operate on normalized [0,1] float channel values and support alpha compositing with adjustable strength.

Usage

using Hawkynt.ColorProcessing.Blending.BlendModes;
using Hawkynt.Drawing;

using var background = new Bitmap("base.png");
using var overlay = new Bitmap("overlay.png");

// Blend with specific mode — returns new bitmap
using var multiplied = background.BlendWith<Multiply>(overlay);
using var screened = background.BlendWith<Screen>(overlay, 0.5f);  // 50% strength

// In-place blending — modifies background directly
background.BlendInto<Overlay>(overlay);

// Blend filter result with adjustable opacity
using var softGlow = source.BlendWith(new GaussianBlur(3, 3), 0.4f);  // Normal blend
using var sharpened = source.BlendWith<Screen, UnsharpMask>(new UnsharpMask(1.5f, 0.05f), 0.7f);

// HSL component modes
using var recolored = background.BlendWith<HueBlend>(overlay);
using var luminosity = background.BlendWith<LuminosityBlend>(overlay);

Available Blend Modes

Normal
Mode Description
Normal Replaces background with foreground
Darken
Mode Description
Multiply Multiplies channels, darkening the image
ColorBurn Darkens by dividing inverted background by foreground
Darken Takes the darker of two channels
LinearBurn Adds channels and subtracts 1, darkening the image
Lighten
Mode Description
Screen Inverts, multiplies, and inverts again, lightening the image
ColorDodge Brightens by dividing background by inverted foreground
Lighten Takes the lighter of two channels
Add Adds channels, clamping at 1
LinearDodge Adds channels, clamping at 1 (alias of Add)
Contrast
Mode Description
Overlay Combines Multiply and Screen based on background luminance
SoftLight Soft contrast adjustment using W3C formula
HardLight Overlay with foreground and background swapped
VividLight Combines Color Burn and Color Dodge based on foreground
LinearLight Combines Linear Burn and Linear Dodge based on foreground
PinLight Replaces dark or light halves based on foreground
HardMix Posterizes to black or white based on channel sum
Inversion
Mode Description
Difference Absolute difference between channels
Exclusion Similar to Difference but with lower contrast
Subtract Subtracts foreground from background, clamping at 0
Divide Divides background by foreground
Component (HSL-based)
Mode Description
HueBlend Takes hue from foreground, saturation and lightness from background
SaturationBlend Takes saturation from foreground, hue and lightness from background
ColorBlend Takes hue and saturation from foreground, lightness from background
LuminosityBlend Takes lightness from foreground, hue and saturation from background
Other
Mode Description
GrainExtract Extracts film grain texture from the image
GrainMerge Merges film grain texture back into the image

Blend Mode Discovery

using Hawkynt.ColorProcessing.Blending;

// Enumerate all available blend modes
foreach (var mode in BlendModeRegistry.All)
  Console.WriteLine($"{mode.Name} ({mode.Category})");

// Find by name or category
var multiply = BlendModeRegistry.FindByName("Multiply");
var darkenModes = BlendModeRegistry.GetByCategory(BlendModeCategory.Darken);

Frequency Domain

The library provides FFT (Fast Fourier Transform) and DCT (Discrete Cosine Transform) operations for frequency-domain image analysis and manipulation.

Types

Type Description
Complex Lightweight complex number (float Real, float Imaginary) with arithmetic operators, magnitude, phase, conjugate, and polar conversion
Fft1D 1D FFT using Cooley-Tukey radix-2 algorithm (in-place, power-of-2 length)
Fft2D 2D FFT via row-wise then column-wise 1D FFT
Dct1D 1D Discrete Cosine Transform (Type-II forward, Type-III inverse)
Dct2D 2D DCT via row-wise then column-wise 1D DCT

Bitmap Extension Methods

using Hawkynt.ColorProcessing.FrequencyDomain;
using Hawkynt.Drawing;

// FFT operations
var spectrum = source.ToFrequencyDomain();           // Bitmap → Complex[,] (grayscale FFT)
using var reconstructed = BitmapFrequencyDomainExtensions
    .FromFrequencyDomain(spectrum, width, height);   // Complex[,] → Bitmap

// Spectrum visualization
using var magnitude = source.GetMagnitudeSpectrum(); // Log-scaled magnitude (zero-freq centered)
using var phase = source.GetPhaseSpectrum();         // Phase spectrum visualization

// DCT operations
var coefficients = source.ToDctDomain();             // Bitmap → float[,] (grayscale DCT)
using var fromDct = BitmapFrequencyDomainExtensions
    .FromDctDomain(coefficients, width, height);     // float[,] → Bitmap

Known Issues

  • Bedi resampler: Produces out-of-range color values on some inputs, causing IndexOutOfRangeException in the sRGB gamma LUT. Tests skip gracefully when this occurs.

Installation

dotnet add package FrameworkExtensions.System.Drawing

Supported Target Frameworks

Framework Version
.NET Framework 3.5, 4.0, 4.5, 4.8
.NET Core 3.1
.NET 6.0, 7.0, 8.0, 9.0 (Windows)

License

LGPL 3.0 or later - See LICENSE for details

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net6.0-windows7.0 is compatible.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net7.0-windows7.0 is compatible.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net8.0-windows7.0 is compatible.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net9.0-windows7.0 is compatible.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.1 is compatible. 
.NET Framework net35 is compatible.  net40 is compatible.  net403 was computed.  net45 is compatible.  net451 was computed.  net452 was computed.  net46 was computed.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 is compatible.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0.134 103 3/2/2026
1.0.0.132 113 2/16/2026
1.0.0.119 104 2/9/2026
1.0.0.112 107 2/2/2026
1.0.0.108 112 1/26/2026
1.0.0.91 110 1/19/2026
1.0.0.79 121 1/5/2026
1.0.0.70 130 12/29/2025
1.0.0.55 211 12/22/2025
1.0.0.49 232 12/15/2025
1.0.0.46 224 9/29/2025
1.0.0.45 216 8/4/2025
1.0.0.37 208 7/7/2025
1.0.0.36 254 2/24/2025
1.0.0.35 329 6/24/2024
1.0.0.33 210 6/17/2024
1.0.0.31 221 6/10/2024
1.0.0.30 204 5/27/2024
1.0.0.29 217 5/6/2024
1.0.0.27 215 4/29/2024
Loading failed