Skip to main content

EncodePixelFormat

Enum EncodePixelFormat 

Source
pub enum EncodePixelFormat<'a> {
    Bilevel {
        pixels: &'a [u8],
    },
    TransparencyMask {
        pixels: &'a [u8],
    },
    Gray8 {
        pixels: &'a [u8],
    },
    Gray16Le {
        pixels: &'a [u8],
    },
    Rgb24 {
        pixels: &'a [u8],
    },
    Palette8 {
        indices: &'a [u8],
        palette: &'a [RgbColor],
    },
    CieLab8 {
        pixels: &'a [u8],
    },
    CieLabL8 {
        pixels: &'a [u8],
    },
    Cmyk32 {
        pixels: &'a [u8],
    },
    YCbCr24 {
        pixels: &'a [u8],
    },
    YCbCrSubsampled24 {
        pixels: &'a [u8],
        subsampling: (u16, u16),
    },
}
Expand description

Pixel layouts the encoder knows how to write.

Variants§

§

Bilevel

1-bit bilevel (1 sample per pixel, MSB-first byte packing). pixels must contain ceil(width / 8) * height bytes. The bit convention follows §10 / §11: bit value 0 = white, 1 = black. The WhiteIsZero (default) PhotometricInterpretation reads those bits straight through; combine with BlackIsZero by inverting the input first. Required for CCITT compression schemes (TiffCompression::CcittRle, TiffCompression::CcittT4OneD).

Fields

§pixels: &'a [u8]
§

TransparencyMask

1-bit transparency mask (TIFF 6.0 §“PhotometricInterpretation” value 4, page 37). 1 sample per pixel, MSB-first byte packing — the on-disk layout is identical to Self::Bilevel, but the encoder writes PhotometricInterpretation = 4 (Transparency Mask) and sets bit 2 of NewSubfileType (tag 254), which the spec defines as “1 if the image defines a transparency mask for another image in this TIFF file. The PhotometricInterpretation value must be 4”. pixels must contain ceil(width / 8) * height bytes; the bit convention is fixed by spec (§Photometric- Interpretation page 37: “The 1-bits define the interior of the region; the 0-bits define the exterior of the region”). The spec recommends PackBits but does not forbid the other compressions; this encoder accepts None / PackBits / LZW / Deflate / Zstd / CCITT-MH / CCITT-T.4-1D, the same compressor set Self::Bilevel accepts.

Fields

§pixels: &'a [u8]
§

Gray8

8-bit greyscale (BlackIsZero, 1 sample per pixel). pixels.len() == width * height.

Fields

§pixels: &'a [u8]
§

Gray16Le

16-bit greyscale (BlackIsZero, 1 sample per pixel, little-endian on disk). pixels.len() == width * height * 2.

Fields

§pixels: &'a [u8]
§

Rgb24

8-bit packed RGB. pixels.len() == width * height * 3.

Fields

§pixels: &'a [u8]
§

Palette8

8-bit indexed palette. indices.len() == width * height, palette.len() <= 256 (any extras are ignored).

Fields

§indices: &'a [u8]
§palette: &'a [RgbColor]
§

CieLab8

8-bit chunky 1976 CIE L*a*b* (PhotometricInterpretation = 8, SamplesPerPixel = 3, BitsPerSample = 8 / 8 / 8) per TIFF 6.0 §23 “CIE L*a*b* Images” (page 110). pixels is row-major interleaved (L*, a*, b*) triples — pixels.len() == width * height * 3. The on-disk bit interpretation is fixed by §23: L* is unsigned 0..255 mapping linearly to the perceptual 0..100 lightness scale, and a* / b* are two’s-complement signed bytes in -128..127 representing the red/green and yellow/blue chrominance channels (§23: “The a* and b* ranges will be represented as signed 8 bit values”). The encoder writes these bytes through to the strip / tile / plane payload verbatim — the caller owns the colourimetric encoding, exactly as the decoder takes them verbatim back off disk. Compressors accepted: None / PackBits / LZW / Deflate / Zstd (the byte-aligned, photometric-agnostic set the other multi-bit photometric paths use); CCITT is bilevel-only per §10 / §11 and rejected here. Predictor = 2 (TIFF 6.0 §14 horizontal differencing, per-component on chunky multi-sample data) composes; PlanarConfiguration = 2 (separate L* / a* / b* component planes) composes (§14 says differencing in planar “works the same as it does for grayscale data” — each plane is differenced independently with an offset of one sample); tiled layout (§15) composes for both chunky and planar.

Fields

§pixels: &'a [u8]
§

CieLabL8

8-bit 1-sample CIE L* monochrome (PhotometricInterpretation = 8, SamplesPerPixel = 1, BitsPerSample = 8) per TIFF 6.0 §23 page 110 “Usage of other Fields”: “SamplesPerPixel - ExtraSamples: 3 for L*a*b*, 1 implies L* only, for monochrome data”. pixels.len() == width * height. Each byte is L* on the 0..255-maps-to-0..100 scale. As with Self::CieLab8, the bytes are written through verbatim. Compressors accepted: None / PackBits / LZW / Deflate / Zstd. Predictor = 2 composes (single-sample chunky path with offset = 1); PlanarConfiguration = 2 is rejected per §“PlanarConfiguration” “irrelevant” for SamplesPerPixel = 1; tiled layout composes.

Fields

§pixels: &'a [u8]
§

Cmyk32

8-bit chunky CMYK per TIFF 6.0 §16 “CMYK Images” (page 69): PhotometricInterpretation = 5, SamplesPerPixel = 4, BitsPerSample = 8, 8, 8, 8. pixels is row-major interleaved cyan, magenta, yellow, black quadruples — its length must equal width * height * 4. The on-disk bit interpretation is fixed by §16: each component is the amount of that ink at the pixel on the canonical InkSet = 1 CMYK ordering, where 0 means no ink and 255 means full coverage (§16 InkSet page 70: “Usually, a value of 0 represents 0 % ink coverage and a value of 255 represents 100 % ink coverage for that component”). The encoder writes the caller-supplied bytes through to the strip, tile, or plane payload verbatim — the caller owns the colourimetric encoding, exactly as the decoder takes them verbatim off disk and collapses them into additive RGB by the §16 “amount of dye” convention. Alongside the §16-required Baseline tags SamplesPerPixel, BitsPerSample, and PhotometricInterpretation, the encoder also writes the two optional §16 separated-image tags InkSet = 1 (tag 332, the “CMYK” InkSet value) and NumberOfInks = 4 (tag 334). Both match their §16 defaults, but emitting them explicitly makes the written file self-describing to readers that key on those fields. Compressors accepted: the byte-aligned, photometric-agnostic set the other multi-bit photometric paths use (None, PackBits, LZW, Deflate, Zstd). CCITT is bilevel-only per §10 and §11 and rejected here. Predictor = 2 (TIFF 6.0 §14 horizontal differencing, per-component on chunky multi-sample data with offset SamplesPerPixel = 4) composes. PlanarConfiguration = 2 composes too: each of the four component planes is written as its own strip per §“PlanarConfiguration”, and the §14 predictor differences each plane independently with an offset of one sample (§14: “Differencing works the same as it does for grayscale data” when PlanarConfiguration is 2). Tiled layout (§15) composes for both chunky and planar.

Fields

§pixels: &'a [u8]
§

YCbCr24

8-bit chunky (Y, Cb, Cr) per TIFF 6.0 §21 “YCbCr Images” (page 89), PhotometricInterpretation = 6, SamplesPerPixel = 3, BitsPerSample = 8, 8, 8 at the §21 chroma-subsampling-1:1 (YCbCrSubSampling = [1, 1]) layout. pixels is row-major, interleaved (Y, Cb, Cr) triples — pixels.len() == width * height * 3. At YCbCrSubSampling = [1, 1] the §21 “Ordering of Component Samples” rule for PlanarConfiguration = 1 collapses to one Y sample per data unit (1×1 luminance grid) followed by one Cb sample and one Cr sample — i.e. the bytes are written through to the strip / tile payload exactly as the caller supplied them, with no re-tiling. The caller owns the RGB→YCbCr conversion; the encoder transports the supplied bytes verbatim, matching the decoder’s build_rgb24_from_ycbcr path which treats §21’s stated chunky data-unit layout as fact. Alongside the §21 / Baseline tags (SamplesPerPixel, BitsPerSample, PhotometricInterpretation), the encoder emits the three §21 fields with their full-range no-headroom/no-footroom values fixed by §20 “ReferenceBlackWhite” page 87 (“Useful ReferenceBlackWhite values for YCbCr images are: [0, 255, 128, 255, 128, 255] no headroom/footroom”):

  • YCbCrSubSampling = [1, 1] (tag 530), the chunky-444 layout the encoder writes;
  • YCbCrPositioning = 1 (tag 531), §21 “centered” — the tag’s documented default and the only positioning that matters when both subsampling factors are 1;
  • ReferenceBlackWhite = [0/1, 255/1, 128/1, 255/1, 128/1, 255/1] (tag 532), the §20 page 87 “no headroom/footroom” reference coding range — §21 says this field “must be used explicitly” for Class Y images.

The §21 default YCbCrCoefficients (tag 529, CCIR Recommendation 601-1’s {299/1000, 587/1000, 114/1000} luma weights) are omitted: §21 explicitly defaults to those values and the decoder’s ycbcr_to_rgb matrix is the Q16 inverse of the same {0.299, 0.587, 0.114} coefficients, so emitting the tag would just restate the spec default. Future rounds add chroma-subsampled (YCbCrSubSampling = [2, 1], [2, 2], etc.) and PlanarConfiguration = 2 writers; the 1:1 chunky surface here is the minimal §21-conformant slice. Compressors accepted: None / PackBits / LZW / Deflate / Zstd (the byte-aligned photometric-agnostic set the other multi-bit photometric paths use). CCITT is bilevel-only per §10 / §11 and rejected here. Predictor = 2, PlanarConfiguration = 2, and tiled layout are deferred — the §21 sample-ordering rule changes shape under non-1:1 subsampling, so the encoder pins those flags off in this initial YCbCr round and rejects the combinations with a precise error rather than emitting something the decoder might mis-tile.

Fields

§pixels: &'a [u8]
§

YCbCrSubsampled24

8-bit chroma-subsampled (Y, Cb, Cr) per TIFF 6.0 §21 “YCbCr Images” (pages 90–94), PhotometricInterpretation = 6, SamplesPerPixel = 3, BitsPerSample = [8, 8, 8], PlanarConfiguration = 1 (chunky). pixels is the full-resolution row-major interleaved (Y, Cb, Cr) raster (pixels.len() == width * height * 3); the encoder performs the chroma decimation and the §21 “Ordering of Component Samples” data-unit packing.

subsampling is (ChromaSubsampleHoriz, ChromaSubsampleVert) from the §21 YCbCrSubSampling field (tag 530). §21 page 90 restricts each factor to 1, 2, or 4 and requires YCbCrSubsampleVert <= YCbCrSubsampleHoriz, so the supported set is (1,1), (2,1), (2,2), (4,1), (4,2) — the same configurations the decoder’s full-resolution chroma-splat path reverses. (1,1) is accepted here too (it is the trivial no-subsampling case) and behaves identically to EncodePixelFormat::YCbCr24.

§21 page 90: “ImageWidth and ImageLength are constrained to be integer multiples of YCbCrSubsampleHoriz and YCbCrSubsampleVert respectively.” The encoder rejects a width/height that is not a multiple of the corresponding factor with a precise error.

Data-unit layout (§21 page 93): a data unit is ChromaSubsampleVert rows of ChromaSubsampleHoriz Y samples (row-major), then one Cb sample, then one Cr sample. For (sh, sv) = (4, 2) the worked example on page 94 is Y00, Y01, Y02, Y03, Y10, Y11, Y12, Y13, Cb00, Cr00, Y04, …. The encoder visits data units left-to-right then top-to-bottom and emits exactly this byte order, which is what the decoder’s build_rgb24_from_ycbcr block walker consumes.

Chroma decimation: each sh × sv block’s Cb / Cr is the rounded arithmetic mean of the block’s full-resolution Cb / Cr samples (a box filter — the symmetric even-tap filter §21 page 92 calls out for YCbCrPositioning = 1 centered subsampling). The Y samples are transported full-resolution and unchanged, so the luminance round-trips bit-exact; chroma round-trips exactly only when it is already constant across each block (decode splats one Cb / Cr back over the whole block).

The same §21 / §20 fields the 1:1 path emits are written, with tag 530 carrying the actual [sh, sv]. YCbCrPositioning = 1 (centered) is emitted to match the box-filter decimation. Compressors accepted: None / PackBits / LZW / Deflate / Zstd. CCITT is bilevel-only and rejected. Predictor = 2, PlanarConfiguration = 2, and tiled layout are rejected with a precise error (the data-unit packing is single-strip chunky only in this round).

Fields

§pixels: &'a [u8]
§subsampling: (u16, u16)

Trait Implementations§

Source§

impl<'a> Clone for EncodePixelFormat<'a>

Source§

fn clone(&self) -> EncodePixelFormat<'a>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a> Debug for EncodePixelFormat<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for EncodePixelFormat<'a>

§

impl<'a> RefUnwindSafe for EncodePixelFormat<'a>

§

impl<'a> Send for EncodePixelFormat<'a>

§

impl<'a> Sync for EncodePixelFormat<'a>

§

impl<'a> Unpin for EncodePixelFormat<'a>

§

impl<'a> UnsafeUnpin for EncodePixelFormat<'a>

§

impl<'a> UnwindSafe for EncodePixelFormat<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.