CoreJ2K provides a comprehensive, fluent API for configuring JPEG 2000 quantization parameters. This modern interface offers fine-grained control over quantization with type-safe configuration, built-in presets, and validation.
- Quick Start
- Understanding Quantization
- Basic Usage
- Quantization Types
- Configuration Options
- Presets
- Advanced Features
- Complete Examples
- API Reference
using CoreJ2K.Configuration;
// Use a preset for common scenarios
var config = QuantizationPresets.HighQuality;
// Or build custom configuration
var custom = new QuantizationConfigurationBuilder()
.UseExpounded()
.WithBaseStepSize(0.01f)
.WithGuardBits(2);
// Apply to encoder configuration
var encoderConfig = new J2KEncoderConfiguration()
.WithQuantization(q => q.UseExpounded().WithBaseStepSize(0.01f));Quantization controls the trade-off between image quality and file size:
- Smaller step sizes = Higher quality, larger files
- Larger step sizes = Lower quality, smaller files
| Type | Description | Use Case |
|---|---|---|
| Reversible | Perfect reconstruction (lossless) | Medical, archival, no loss allowed |
| Derived | All subbands use same relative scaling | Simple lossy compression |
| Expounded | Independent control per subband | Advanced lossy, fine-tuning |
- Base Step Size: Primary control for quality/size trade-off
- Guard Bits: Protection against quantization overflow
- Subband Steps: Fine-tune individual frequency subbands (expounded only)
// Lossless (reversible)
var lossless = QuantizationPresets.Lossless;
// High quality lossy
var highQuality = QuantizationPresets.HighQuality;
// Balanced quality/size
var balanced = QuantizationPresets.Balanced;
// High compression
var compressed = QuantizationPresets.HighCompression;var config = new QuantizationConfigurationBuilder()
.UseExpounded()
.WithBaseStepSize(0.01f) // Quality control
.WithGuardBits(2); // Overflow protectionvar encoderConfig = new J2KEncoderConfiguration()
.WithQuality(0.8)
.WithQuantization(q => q
.UseExpounded()
.WithBaseStepSize(0.008f)
.WithGuardBits(2));
byte[] jp2Data = J2kImage.ToBytes(image, encoderConfig);Perfect reconstruction - no information loss.
var config = new QuantizationConfigurationBuilder()
.UseReversible();
// Or use preset
var lossless = QuantizationPresets.Lossless;Characteristics:
- ? Exact reconstruction
- ? No quality loss
- ? Larger file sizes
- Use for: Medical imaging, archival, legal documents
Simple lossy with uniform scaling.
var config = new QuantizationConfigurationBuilder()
.UseDerived()
.WithBaseStepSize(0.01f);Characteristics:
- ? Simple configuration
- ? Consistent across subbands
- ? Less flexible than expounded
- Use for: General-purpose lossy compression
Advanced lossy with per-subband control.
var config = new QuantizationConfigurationBuilder()
.UseExpounded()
.WithBaseStepSize(0.01f)
.WithSubbandStep(0, "LL", 0.008f) // Fine-tune low frequencies
.WithSubbandStep(0, "HH", 0.015f); // Coarser for high frequenciesCharacteristics:
- ? Maximum flexibility
- ? Per-subband optimization
- ? Best quality/size trade-offs
- Use for: Professional imaging, custom optimization
Controls overall quantization strength.
// Very high quality (near-lossless)
.WithBaseStepSize(0.001f)
// High quality
.WithBaseStepSize(0.002f)
// Balanced
.WithBaseStepSize(0.0078125f)
// High compression
.WithBaseStepSize(0.02f)
// Maximum compression
.WithBaseStepSize(0.05f)Guidelines:
0.001 - 0.002: Near-lossless, archival quality0.002 - 0.01: High quality, professional use0.01 - 0.03: Balanced, general purpose0.03 - 0.1: High compression, acceptable quality
Protects against quantization overflow.
// Minimal protection (smaller files)
.WithGuardBits(0)
// Standard protection (recommended)
.WithGuardBits(1)
// Enhanced protection (high bit-depth)
.WithGuardBits(2)
// Maximum protection
.WithGuardBits(3)Recommendations:
- 0-1 bits: 8-bit images, standard use
- 2 bits: 12-16 bit images, high dynamic range
- 3+ bits: Very high bit-depth, special cases
Fine-tune individual frequency subbands.
// Single subband
.WithSubbandStep(0, "LL", 0.008f) // Resolution 0, Low-Low
// All subbands at a resolution level
.WithResolutionSteps(
0, // Resolution level
0.008f, // LL (low frequencies)
0.012f, // HL (horizontal edges)
0.012f, // LH (vertical edges)
0.015f) // HH (diagonal, high frequencies)Subband Types:
- LL (Low-Low): Coarse approximation, most important
- HL (High-Low): Horizontal detail
- LH (Low-High): Vertical detail
- HH (High-High): Diagonal detail, can use larger steps
Perfect reconstruction, no quality loss.
var config = QuantizationPresets.Lossless;
// Type: Reversible
// Use: Medical, archival, legalVisually indistinguishable, very high quality.
var config = QuantizationPresets.NearLossless;
// BaseStep: 0.001
// GuardBits: 2
// Use: High-end photography, cinemaExcellent visual quality, good compression.
var config = QuantizationPresets.HighQuality;
// BaseStep: 0.002
// GuardBits: 2
// Use: Professional photography, printGood quality with moderate compression.
var config = QuantizationPresets.Balanced;
// BaseStep: 0.0078125
// GuardBits: 1
// Use: General purpose, web, storageAcceptable quality, small files.
var config = QuantizationPresets.HighCompression;
// BaseStep: 0.02
// GuardBits: 1
// Use: Bandwidth-limited, previewsLow quality, very small files.
var config = QuantizationPresets.MaximumCompression;
// BaseStep: 0.05
// GuardBits: 1
// Use: Thumbnails, extreme compression// Medical imaging (lossless)
var medical = QuantizationPresets.Medical;
// Archival storage (very high quality)
var archival = QuantizationPresets.Archival;
// Web delivery (balanced)
var web = QuantizationPresets.Web;
// Thumbnail generation (higher compression)
var thumbnail = QuantizationPresets.Thumbnail;Optimize for specific image characteristics.
var config = new QuantizationConfigurationBuilder()
.UseExpounded()
.WithBaseStepSize(0.01f)
// Preserve low frequencies (important detail)
.WithResolutionSteps(0, 0.008f, 0.012f, 0.012f, 0.015f)
// Allow more loss in high frequencies
.WithResolutionSteps(1, 0.010f, 0.015f, 0.015f, 0.020f);Different quantization for different resolution levels.
var config = new QuantizationConfigurationBuilder()
.UseExpounded()
.WithBaseStepSize(0.01f);
// Fine detail at level 0 (highest resolution)
config.WithResolutionSteps(0, 0.008f, 0.010f, 0.010f, 0.012f);
// Moderate at level 1
config.WithResolutionSteps(1, 0.012f, 0.015f, 0.015f, 0.018f);
// Coarser at level 2
config.WithResolutionSteps(2, 0.015f, 0.020f, 0.020f, 0.025f);var config = new QuantizationConfigurationBuilder()
.UseReversible()
.WithSubbandStep(0, "LL", 0.01f); // Error: can't combine!
if (!config.IsValid)
{
var errors = config.Validate();
foreach (var error in errors)
Console.WriteLine($"Error: {error}");
}
// Output: "Custom subband steps are not applicable for reversible quantization"var base Config = QuantizationPresets.HighQuality;
var customized = baseConfig.Clone();
customized.WithBaseStepSize(0.003f);
// baseConfig unchanged, customized modifiedvar config = new QuantizationConfigurationBuilder()
.UseReversible();
var encoderConfig = new J2KEncoderConfiguration()
.WithLossless()
.WithQuantization(q => q.UseReversible())
.WithTiles(t => t.SetSize(512, 512));
byte[] dicomData = J2kImage.ToBytes(medicalImage, encoderConfig);var config = new QuantizationConfigurationBuilder()
.UseExpounded()
.WithBaseStepSize(0.002f)
.WithGuardBits(2);
var encoderConfig = new J2KEncoderConfiguration()
.WithQuality(0.95)
.WithQuantization(q => q
.UseExpounded()
.WithBaseStepSize(0.002f)
.WithGuardBits(2))
.WithFileFormat(true);
byte[] photoData = J2kImage.ToBytes(photo, encoderConfig);var config = QuantizationPresets.Web;
var encoderConfig = new J2KEncoderConfiguration()
.WithQuality(0.75)
.WithQuantization(q => q
.UseExpounded()
.WithBaseStepSize(0.01f)
.WithGuardBits(1))
.WithTiles(t => t.SetSize(512, 512));
byte[] webData = J2kImage.ToBytes(webImage, encoderConfig);var config = new QuantizationConfigurationBuilder()
.UseExpounded()
.WithBaseStepSize(0.0015f)
.WithGuardBits(2);
var encoderConfig = new J2KEncoderConfiguration()
.WithQuality(0.99)
.WithQuantization(q => q
.UseExpounded()
.WithBaseStepSize(0.0015f)
.WithGuardBits(2))
.WithTiles(t => t.SetSize(1024, 1024))
.WithErrorResilience(er => er.EnableAll());
byte[] archiveData = J2kImage.ToBytes(archiveImage, encoderConfig);var config = new QuantizationConfigurationBuilder()
.UseExpounded()
.WithBaseStepSize(0.01f)
// Prioritize low frequencies (important visual content)
.WithSubbandStep(0, "LL", 0.007f)
.WithSubbandStep(0, "HL", 0.011f)
.WithSubbandStep(0, "LH", 0.011f)
.WithSubbandStep(0, "HH", 0.015f)
// Allow more loss in higher resolution levels
.WithResolutionSteps(1, 0.012f, 0.016f, 0.016f, 0.020f);
var encoderConfig = new J2KEncoderConfiguration()
.WithBitrate(2.0f)
.WithQuantization(q => config);
byte[] optimizedData = J2kImage.ToBytes(image, encoderConfig);// Base quality for all users
var baseConfig = new QuantizationConfigurationBuilder()
.ForBalanced();
// Premium quality for subscribers
var premiumConfig = new QuantizationConfigurationBuilder()
.ForHighQuality();
// Use based on user tier
var config = isPremiumUser ? premiumConfig : baseConfig;
var encoderConfig = new J2KEncoderConfiguration()
.WithQuantization(q => config);
byte[] data = J2kImage.ToBytes(image, encoderConfig);var config = QuantizationPresets.Thumbnail;
var encoderConfig = new J2KEncoderConfiguration()
.WithBitrate(0.5f)
.WithQuantization(q => q
.UseExpounded()
.WithBaseStepSize(0.03f))
.WithTiles(t => t.SetSize(256, 256))
.WithWavelet(w => w.WithDecompositionLevels(3));
byte[] thumbData = J2kImage.ToBytes(thumbnail, encoderConfig);Main quantization configuration class.
Methods:
UseReversible()- Enable lossless quantizationUseDerived()- Enable scalar derived quantizationUseExpounded()- Enable scalar expounded quantizationWithBaseStepSize(float)- Set base quantization stepWithGuardBits(int)- Set guard bits (0-7)WithSubbandStep(int, string, float)- Set step for specific subbandWithResolutionSteps(int, float, float, float, float)- Set all subbands at levelUseDefaultSubbandSteps()- Clear custom subband stepsForHighQuality()- Configure for high qualityForBalanced()- Configure for balanced quality/sizeForHighCompression()- Configure for high compressionClone()- Create independent copyValidate()- Get validation errorsToString()- Get string representation
Properties:
Type- Quantization typeBaseStepSize- Base step sizeGuardBits- Number of guard bitsUseDefaultSteps- Whether using default subband stepsIsValid- Whether configuration is valid
Static presets for common scenarios.
Available Presets:
Lossless- Reversible (perfect reconstruction)NearLossless- Visually indistinguishable (0.001 step)HighQuality- Excellent quality (0.002 step)Balanced- Good quality/size (0.0078125 step)HighCompression- Acceptable quality (0.02 step)MaximumCompression- Low quality (0.05 step)Medical- Medical imaging (lossless)Archival- Archival storage (0.0015 step)Web- Web delivery (0.01 step)Thumbnail- Thumbnail generation (0.03 step)
// Start with a preset
var config = QuantizationPresets.HighQuality;
// Customize if needed
config.WithBaseStepSize(0.0025f);| Use Case | Recommended Preset/Config |
|---|---|
| Medical/Legal | Lossless |
| Photography | HighQuality or NearLossless |
| Archival | Archival |
| Web Display | Web or Balanced |
| Mobile/Low Bandwidth | HighCompression |
| Thumbnails | Thumbnail or MaximumCompression |
if (!config.IsValid)
{
throw new InvalidOperationException(
string.Join("\n", config.Validate()));
}// 8-bit images
.WithGuardBits(1)
// 12-16 bit images
.WithGuardBits(2)
// Higher bit depths
.WithGuardBits(3)var configs = new[]
{
(0.005f, "Very High"),
(0.01f, "High"),
(0.02f, "Medium"),
(0.03f, "Low")
};
foreach (var (stepSize, label) in configs)
{
var config = new QuantizationConfigurationBuilder()
.WithBaseStepSize(stepSize);
var data = J2kImage.ToBytes(image, config);
Console.WriteLine($"{label}: {data.Length} bytes");
}Note: Quantization configuration can be used standalone or integrated with the encoder configuration API for streamlined workflow.