pub struct Decoder<'a> { /* private fields */ }Expand description
JPEG decoder. Orchestrates the full decoding pipeline.
§Threading
Decoder is Send — a configured decoder can move to another
thread (rayon, tokio::task::spawn_blocking) and decode there
(issue #384). It is deliberately not Sync: in-decode state
lives behind interior mutability (RefCell) and the installed
callbacks are Send-only boxes, so one decoder serves one thread
at a time — upstream libjpeg-turbo’s per-cinfo rule. Our own C
ABI shim is stricter still: a cinfo may not leave the thread that
created it (docs/ABI_COMPATIBILITY.md, “Threading contract”).
Decode the same bytes concurrently by giving each thread its own
Decoder; construction from &[u8] is cheap (header parse only).
Implementations§
Source§impl<'a> Decoder<'a>
impl<'a> Decoder<'a>
Sourcepub fn new(data: &'a [u8]) -> Result<Self>
pub fn new(data: &'a [u8]) -> Result<Self>
Parse the JPEG headers in data and return a configurable
decoder. No entropy decoding and no pixel work happen here, but
for progressive and non-interleaved streams locating the scan
boundaries walks the entropy bytes, so worst-case probe time
scales with the compressed input length (still far cheaper than
a decode). Suitable as a probe (dimensions,
Decoder::exif_orientation, ICC/EXIF/XMP metadata) even when
no decode follows. Uses DecodeLimits::default; use
Decoder::new_with_limits to bound resource use differently.
Sourcepub fn new_with_limits(data: &'a [u8], limits: DecodeLimits) -> Result<Self>
pub fn new_with_limits(data: &'a [u8], limits: DecodeLimits) -> Result<Self>
Like Self::new, but the limits apply from marker parsing
onward: a max_scans tighter than the parse default bounds
ScanInfo buffering during the header walk itself, not just at
decode time (issue #355).
Sourcepub fn new_with_tables(
body_data: &'a [u8],
tables: &TablesOnlyState,
) -> Result<Self>
pub fn new_with_tables( body_data: &'a [u8], tables: &TablesOnlyState, ) -> Result<Self>
Create a decoder for a body-only abbreviated stream using preloaded tables.
The body_data must contain SOF and SOS markers but may omit DQT and DHT.
Tables from tables are injected into the decoder’s internal state before decoding.
Matches libjpeg-turbo’s abbreviated compressed data datastream handling:
use read_header() to get a TablesOnlyState, then this function to decode
the body-only stream.
Sourcepub fn exif_orientation(&self) -> Option<u8>
pub fn exif_orientation(&self) -> Option<u8>
EXIF orientation (1-8) from the already-parsed headers, without
any pixel decode (issue #391). Decoder::new is a header parse
only, so probing a camera JPEG’s orientation costs no decoding:
let decoder = libjpeg_turbo_rs::Decoder::new(&jpeg)?;
// This fixture carries no EXIF; a camera JPEG returns Some(1..=8).
// Map 2-8 with TransformOp::from_exif_orientation (lossless, DCT
// domain) or Image::apply_orientation (pixels).
assert_eq!(decoder.exif_orientation(), None);Sourcepub fn header(&self) -> &FrameHeader
pub fn header(&self) -> &FrameHeader
The parsed frame header: dimensions, per-component sampling,
precision, progressive/lossless flags. Available immediately
after Decoder::new, before any pixel decode.
Sourcepub fn density(&self) -> &DensityInfo
pub fn density(&self) -> &DensityInfo
Pixel density parsed from the JFIF APP0 marker (or
DensityInfo::default() if no JFIF was present).
Mirrors stock libjpeg’s cinfo.density_unit / X_density / Y_density exposed after jpeg_read_header.
Sourcepub fn saw_jfif_marker(&self) -> bool
pub fn saw_jfif_marker(&self) -> bool
Whether the source carried a JFIF APP0 marker (regardless of
the density values it contained). Mirrors stock libjpeg’s
cinfo.saw_JFIF_marker.
Sourcepub fn jfif_version(&self) -> (u8, u8)
pub fn jfif_version(&self) -> (u8, u8)
JFIF version bytes from the APP0 marker. Returns (0, 0) if
saw_jfif_marker() is false.
Sourcepub fn is_arithmetic(&self) -> bool
pub fn is_arithmetic(&self) -> bool
Whether the source uses arithmetic entropy coding (SOF9 / SOF10 / SOF11).
Returns true for arithmetic-coded streams and false for
Huffman-coded streams (SOF0 / SOF1 / SOF2 / SOF3). Mirrors stock
libjpeg’s cinfo.arith_code populated by jpeg_read_header.
Sourcepub fn set_output_format(&mut self, format: PixelFormat)
pub fn set_output_format(&mut self, format: PixelFormat)
Set the desired output pixel format.
Sourcepub fn set_scale(&mut self, scale: ScalingFactor)
pub fn set_scale(&mut self, scale: ScalingFactor)
Set the decompression scaling factor (e.g., 1/2, 1/4, 1/8).
Sourcepub fn set_lenient(&mut self, lenient: bool)
pub fn set_lenient(&mut self, lenient: bool)
Enable lenient mode: continue decoding on errors, filling corrupt areas with gray.
Sourcepub fn set_crop(&mut self, x: usize, width: usize)
pub fn set_crop(&mut self, x: usize, width: usize)
Set horizontal crop region. Offsets are auto-aligned to iMCU boundaries.
Sourcepub fn set_crop_y(&mut self, y: usize, height: usize)
pub fn set_crop_y(&mut self, y: usize, height: usize)
Set only the vertical crop range, leaving any horizontal crop
untouched. MCU rows fully outside the range skip IDCT during
decoding (issue #383: backs StreamingDecoder::skip_scanlines).
Sourcepub fn output_height(&self) -> usize
pub fn output_height(&self) -> usize
Rows a decode will actually emit: the scaled frame height, except
on the 12-bit and lossless paths, which bypass scaled decode (see
output_buffer_size). crop_y/crop_height are interpreted in
these output rows, matching C, where jpeg_skip_scanlines
validates against cinfo->output_height (jdapistd.c).
Sourcepub fn set_crop_region(
&mut self,
x: usize,
y: usize,
width: usize,
height: usize,
)
pub fn set_crop_region( &mut self, x: usize, y: usize, width: usize, height: usize, )
Set full crop region (horizontal + vertical). MCU rows outside the vertical range will skip IDCT during decoding.
Sourcepub fn set_stop_on_warning(&mut self, stop: bool)
pub fn set_stop_on_warning(&mut self, stop: bool)
Treat warnings as fatal errors.
Sourcepub fn set_max_pixels(&mut self, limit: usize)
pub fn set_max_pixels(&mut self, limit: usize)
Set maximum allowed image size in pixels. Reject images exceeding this.
Sourcepub fn set_max_memory(&mut self, limit: usize)
pub fn set_max_memory(&mut self, limit: usize)
Set maximum memory usage in bytes.
Sourcepub fn set_scan_limit(&mut self, limit: u32)
pub fn set_scan_limit(&mut self, limit: u32)
Set maximum number of progressive scans before error.
Sourcepub fn set_limits(&mut self, limits: DecodeLimits)
pub fn set_limits(&mut self, limits: DecodeLimits)
Configure all decoder resource limits at once (issue #355).
Defaults (DecodeLimits::default) are permissive — they accept
everything djpeg accepts in the corpus gates while rejecting the
pathological corner (a header-only 65535x65535 SOF exceeds the
default max_pixels before any plane allocation). Use
DecodeLimits::strict for zune-like tight bounds. Exceeding a
limit is a typed JpegError::LimitExceeded, never a panic.
Note on max_scans: marker parsing happens in the constructor,
bounded by the construction-time cap (new uses the 8192
default; new_with_limits threads the caller’s value, higher or
lower). Setting a different max_scans here affects only the
decode-time check — a stream needing a larger parse cap must be
constructed with new_with_limits.
Sourcepub fn limits(&self) -> &DecodeLimits
pub fn limits(&self) -> &DecodeLimits
The currently configured resource limits.
Sourcepub fn set_fast_upsample(&mut self, fast: bool)
pub fn set_fast_upsample(&mut self, fast: bool)
Enable or disable fast (nearest-neighbor) upsampling.
Sourcepub fn jpeg_color_space(&self) -> ColorSpace
pub fn jpeg_color_space(&self) -> ColorSpace
Get the JPEG color space detected from the file header.
Maps component count and Adobe APP14 marker to a ColorSpace value,
matching libjpeg-turbo’s jpeg_color_space behavior.
Sourcepub fn jpeg_subsampling(&self) -> Subsampling
pub fn jpeg_subsampling(&self) -> Subsampling
Get the chroma subsampling detected from the SOF component sampling factors.
Compares luma vs chroma sampling factors to determine the standard
subsampling mode. Returns Subsampling::Unknown for grayscale
(caller should check component count and map to TJSAMP_GRAY=3).
Sourcepub fn set_fast_dct(&mut self, fast: bool)
pub fn set_fast_dct(&mut self, fast: bool)
Enable or disable fast DCT for decoding.
Sourcepub fn set_dct_method(&mut self, method: DctMethod)
pub fn set_dct_method(&mut self, method: DctMethod)
Set the DCT/IDCT method for decoding.
Sourcepub fn set_block_smoothing(&mut self, smooth: bool)
pub fn set_block_smoothing(&mut self, smooth: bool)
Enable or disable inter-block smoothing.
Sourcepub fn set_output_colorspace(&mut self, cs: ColorSpace)
pub fn set_output_colorspace(&mut self, cs: ColorSpace)
Override the output color space.
Sourcepub fn set_dither_565(&mut self, dither: bool)
pub fn set_dither_565(&mut self, dither: bool)
Enable or disable ordered dithering for RGB565 output.
When enabled, applies a 4x4 ordered dither pattern before truncating 8-bit RGB to 5-6-5, reducing visible banding in smooth gradients. Matches libjpeg-turbo’s dithered RGB565 output mode.
Sourcepub fn set_merged_upsample(&mut self, enabled: bool)
pub fn set_merged_upsample(&mut self, enabled: bool)
Enable merged upsampling optimization (combines upsample + color convert).
When enabled and subsampling is 4:2:0 or 4:2:2, uses a merged path that performs chroma upsampling and YCbCr->RGB conversion in a single pass. This avoids writing upsampled chroma to intermediate buffers, improving cache behavior. Slightly less accurate than separate fancy upsample because merged uses box-filter (nearest-neighbor) chroma replication.
Sourcepub fn save_markers(&mut self, config: MarkerSaveConfig)
pub fn save_markers(&mut self, config: MarkerSaveConfig)
Configure which markers to save during decoding.
By default, the decoder only parses known markers (JFIF, ICC, EXIF, Adobe, COM)
and discards unknown APP markers. Call this to preserve arbitrary APP/COM markers
in the decoded Image.saved_markers field.
This re-parses the JPEG header with the new configuration.
Sourcepub fn saved_markers(&self) -> &[SavedMarker]
pub fn saved_markers(&self) -> &[SavedMarker]
Saved APP/COM markers from the source JPEG, populated by the most
recent header parse. Empty unless save_markers() has been called
with a non-None config (or the underlying parser was constructed
with one). Used by C-ABI consumers (crates/libjpeg-turbo-rs-capi)
that need to re-emit source markers verbatim during transcode.
Sourcepub fn with_output_format(self, format: PixelFormat) -> Self
pub fn with_output_format(self, format: PixelFormat) -> Self
Chainable Decoder::set_output_format.
use libjpeg_turbo_rs::{Decoder, PixelFormat};
let image = Decoder::new(&jpeg)?
.with_output_format(PixelFormat::Bgra)
.with_block_smoothing(false)
.decode_image()?;
assert_eq!(image.pixel_format, PixelFormat::Bgra);Sourcepub fn with_scale(self, scale: ScalingFactor) -> Self
pub fn with_scale(self, scale: ScalingFactor) -> Self
Chainable Decoder::set_scale.
Sourcepub fn with_lenient(self, lenient: bool) -> Self
pub fn with_lenient(self, lenient: bool) -> Self
Chainable Decoder::set_lenient.
Sourcepub fn with_crop(self, x: usize, width: usize) -> Self
pub fn with_crop(self, x: usize, width: usize) -> Self
Chainable Decoder::set_crop.
Sourcepub fn with_crop_y(self, y: usize, height: usize) -> Self
pub fn with_crop_y(self, y: usize, height: usize) -> Self
Chainable Decoder::set_crop_y.
Sourcepub fn with_crop_region(
self,
x: usize,
y: usize,
width: usize,
height: usize,
) -> Self
pub fn with_crop_region( self, x: usize, y: usize, width: usize, height: usize, ) -> Self
Chainable Decoder::set_crop_region.
Sourcepub fn with_stop_on_warning(self, stop: bool) -> Self
pub fn with_stop_on_warning(self, stop: bool) -> Self
Chainable Decoder::set_stop_on_warning.
Sourcepub fn with_max_pixels(self, limit: usize) -> Self
pub fn with_max_pixels(self, limit: usize) -> Self
Chainable Decoder::set_max_pixels.
Sourcepub fn with_max_memory(self, limit: usize) -> Self
pub fn with_max_memory(self, limit: usize) -> Self
Chainable Decoder::set_max_memory.
Sourcepub fn with_scan_limit(self, limit: u32) -> Self
pub fn with_scan_limit(self, limit: u32) -> Self
Chainable Decoder::set_scan_limit.
Sourcepub fn with_limits(self, limits: DecodeLimits) -> Self
pub fn with_limits(self, limits: DecodeLimits) -> Self
Chainable Decoder::set_limits.
Sourcepub fn with_fast_upsample(self, fast: bool) -> Self
pub fn with_fast_upsample(self, fast: bool) -> Self
Chainable Decoder::set_fast_upsample.
Sourcepub fn with_fast_dct(self, fast: bool) -> Self
pub fn with_fast_dct(self, fast: bool) -> Self
Chainable Decoder::set_fast_dct.
Sourcepub fn with_dct_method(self, method: DctMethod) -> Self
pub fn with_dct_method(self, method: DctMethod) -> Self
Chainable Decoder::set_dct_method.
Sourcepub fn with_block_smoothing(self, smooth: bool) -> Self
pub fn with_block_smoothing(self, smooth: bool) -> Self
Chainable Decoder::set_block_smoothing.
Sourcepub fn with_output_colorspace(self, cs: ColorSpace) -> Self
pub fn with_output_colorspace(self, cs: ColorSpace) -> Self
Chainable Decoder::set_output_colorspace.
Sourcepub fn with_dither_565(self, dither: bool) -> Self
pub fn with_dither_565(self, dither: bool) -> Self
Chainable Decoder::set_dither_565.
Sourcepub fn with_merged_upsample(self, enabled: bool) -> Self
pub fn with_merged_upsample(self, enabled: bool) -> Self
Chainable Decoder::set_merged_upsample.
Sourcepub fn with_save_markers(self, config: MarkerSaveConfig) -> Self
pub fn with_save_markers(self, config: MarkerSaveConfig) -> Self
Chainable Decoder::save_markers.
Like save_markers, a marker re-parse failure is swallowed and
previously parsed metadata stays in effect — check
Decoder::saved_markers afterwards if the distinction matters.
Sourcepub fn with_marker_processor<F>(self, marker_type: u8, processor: F) -> Self
pub fn with_marker_processor<F>(self, marker_type: u8, processor: F) -> Self
Chainable Decoder::set_marker_processor.
Sourcepub fn with_resync_strategy<S>(self, strategy: S) -> Selfwhere
S: RestartResyncStrategy + Send + 'static,
pub fn with_resync_strategy<S>(self, strategy: S) -> Selfwhere
S: RestartResyncStrategy + Send + 'static,
Chainable Decoder::set_resync_strategy.
Sourcepub fn set_marker_processor<F>(&mut self, marker_type: u8, processor: F)
pub fn set_marker_processor<F>(&mut self, marker_type: u8, processor: F)
Register a custom marker processor callback for a specific marker type.
The callback must be Send: the decoder itself is Send
(issue #384), so everything installed into it travels across
threads with it.
Sourcepub fn set_resync_strategy<S>(&mut self, strategy: S)where
S: RestartResyncStrategy + Send + 'static,
pub fn set_resync_strategy<S>(&mut self, strategy: S)where
S: RestartResyncStrategy + Send + 'static,
Install a custom RestartResyncStrategy to handle RST-marker desync
events (mirrors C libjpeg-turbo’s jpeg_resync_to_restart hook).
When the decoder encounters a restart marker whose RST number does
not match the expected counter — or when no RST marker is found at
the expected position — the strategy’s on_desync method is
consulted. The returned ResyncAction tells the decoder whether to
continue (accept the observed marker), skip to the next RST in the
stream, or abort with a CorruptData error.
If no strategy is installed, the decoder defaults to Continue —
the historical Rust behavior of unconditionally accepting whatever
RST marker it finds.
pub fn decode(data: &'a [u8]) -> Result<Image>
pub fn decode_to(data: &'a [u8], format: PixelFormat) -> Result<Image>
Sourcepub fn decode_image(&self) -> Result<Image>
pub fn decode_image(&self) -> Result<Image>
Decode the full image into an owned Image using the
configuration set on this decoder (output format, scaling, crop,
leniency, …). To decode into a caller-owned buffer, see
Decoder::decode_image_into (which avoids the per-frame output
allocation on the standard direct-output paths; its docs list the
staged exceptions).
Sourcepub fn output_buffer_size(&self) -> Result<usize>
pub fn output_buffer_size(&self) -> Result<usize>
Bytes decode_image_into needs for this stream with the current
decoder options. Exact for the standard paths; a safe upper
bound when an output-colourspace override is active (sized at 4
bytes/pixel) or when cropping trims the image below the
MCU-aligned estimate.
Sourcepub fn decode_image_into(&self, out: &mut [u8]) -> Result<ImageInfo>
pub fn decode_image_into(&self, out: &mut [u8]) -> Result<ImageInfo>
Decode into a caller-provided buffer, returning the metadata
Image would carry minus the pixel Vec (issue #354).
out must hold at least Self::output_buffer_size bytes; a
short buffer is a typed JpegError::BufferTooSmall, never a
panic or truncation. The standard baseline/progressive output
paths (grayscale, 4:4:4, and every streamed subsampling mode)
write pixels directly into out with no output-sized heap
allocation; the remaining paths (CMYK, 12-bit, lossless, output
colourspace overrides, vertical crop) stage through an internal
buffer and copy, which is still allocation-neutral versus
decode_image and byte-identical to it.
On error the contents of out are unspecified: a decode may
have written part of the frame before failing.
Sourcepub fn decode_raw(self) -> Result<RawImage>
pub fn decode_raw(self) -> Result<RawImage>
Decode JPEG to raw downsampled component planes.
Returns component planes at their native (potentially subsampled)
resolution, without performing color conversion or upsampling.
This matches libjpeg-turbo’s jpeg_read_raw_data() functionality.