Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/color/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,13 @@ impl Precision {
/// A color format with a specific number of channels and precision.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ColorFormat {
/// The number and semantics of the channels.
pub channels: Channels,
/// The precision/bit depth of the values in all channels.
pub precision: Precision,
}
impl ColorFormat {
/// Creates a new `ColorFormat` with the given channels and precision.
pub const fn new(channels: Channels, precision: Precision) -> Self {
Self {
channels,
Expand Down
9 changes: 8 additions & 1 deletion src/decode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub(crate) const fn get_decoders(format: Format) -> DecoderSet {
Format::Y410 => Y410,
Format::Y416 => Y416,

// sub-sampled formats
// subsampled formats
Format::R1_UNORM => R1_UNORM,
Format::R8G8_B8G8_UNORM => R8G8_B8G8_UNORM,
Format::G8R8_G8B8_UNORM => G8R8_G8B8_UNORM,
Expand Down Expand Up @@ -223,6 +223,13 @@ pub fn decode_rect<R: Read + Seek>(
}
}

/// Options for decoding images.
///
/// ## See also
///
/// - [`decode`]
/// - [`decode_rect`]
/// - [`Decoder::options`](crate::Decoder::options)
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct DecodeOptions {
Expand Down
2 changes: 1 addition & 1 deletion src/decode/read_write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ pub(crate) fn process_bi_planar_helper<
pub(crate) struct BiPlaneInfo {
pub plane1_element_size: u8,
pub plane2_element_size: u8,
/// The sub-sampling of plane2.
/// The subsampling of plane2.
pub sub_sampling: (u8, u8),
}
pub(crate) fn for_each_bi_planar(
Expand Down
3 changes: 3 additions & 0 deletions src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ pub struct Decoder<R> {
layout: DataLayout,

iter: SurfaceIterator,
/// The options used for decoding.
///
/// Default: [`DecodeOptions::default()`]
pub options: DecodeOptions,
}
impl<R> Decoder<R> {
Expand Down
2 changes: 1 addition & 1 deletion src/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub(crate) const fn dxgi_format_to_supported(dxgi_format: DxgiFormat) -> Option<
DxgiFormat::Y410 => Some(Format::Y410),
DxgiFormat::Y416 => Some(Format::Y416),

// sub-sampled formats
// subsampled formats
DxgiFormat::R8G8_B8G8_UNORM => Some(Format::R8G8_B8G8_UNORM),
DxgiFormat::G8R8_G8B8_UNORM => Some(Format::G8R8_G8B8_UNORM),
DxgiFormat::YUY2 => Some(Format::YUY2),
Expand Down
26 changes: 25 additions & 1 deletion src/encode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ pub(crate) const fn get_encoders(format: Format) -> Option<EncoderSet> {
Format::Y410 => Y410,
Format::Y416 => Y416,

// sub-sampled formats
// subsampled formats
Format::R1_UNORM => R1_UNORM,
Format::R8G8_B8G8_UNORM => R8G8_B8G8_UNORM,
Format::G8R8_G8B8_UNORM => G8R8_G8B8_UNORM,
Expand Down Expand Up @@ -222,6 +222,12 @@ fn encode_parallel(
progress.checked_report(1.0)
}

/// Options for encoding images.
///
/// ## See also
///
/// - [`encode`]
/// - [`Encoder::encoding`](crate::Encoder::encoding)
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct EncodeOptions {
Expand All @@ -240,6 +246,9 @@ pub struct EncodeOptions {
pub dithering: Dithering,
/// The error metric for block compression formats.
///
/// This is currently only supported for BC1-3. All other formats will
/// ignore this option and assume [`ErrorMetric::Uniform`].
///
/// Default: [`ErrorMetric::Uniform`]
pub error_metric: ErrorMetric,
/// The compression quality.
Expand Down Expand Up @@ -276,6 +285,8 @@ impl Default for EncodeOptions {
}
}

/// Specifies whether dithering is enabled/supported for color and/or alpha
/// channels.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Dithering {
/// Dithering is disabled for all channels.
Expand All @@ -289,6 +300,7 @@ pub enum Dithering {
Alpha = 0b10,
}
impl Dithering {
/// Creates a new `Dithering` given the channels it is enabled for.
pub const fn new(color: bool, alpha: bool) -> Self {
match (color, alpha) {
(true, true) => Dithering::ColorAndAlpha,
Expand All @@ -298,9 +310,11 @@ impl Dithering {
}
}

/// Whether dithering is enabled for color channels.
pub const fn color(self) -> bool {
matches!(self, Dithering::ColorAndAlpha | Dithering::Color)
}
/// Whether dithering is enabled for the alpha channel.
pub const fn alpha(self) -> bool {
matches!(self, Dithering::ColorAndAlpha | Dithering::Alpha)
}
Expand All @@ -318,10 +332,20 @@ impl Dithering {
}
}

/// The error metric encoders use to optimize compressed formats.
///
/// Not all formats support all error metrics. See
/// [`EncodeOptions::error_metric`] for more details.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum ErrorMetric {
/// The error of all channels is weighted equally.
#[default]
Uniform,
/// Color is assumed to be sRGB, and the error is calculated in a
/// perceptually uniform color space.
///
/// [Oklab](https://en.wikipedia.org/wiki/Oklab_color_space) is currently
/// used as the perceptually uniform color space.
Perceptual,
}

Expand Down
34 changes: 25 additions & 9 deletions src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ pub struct Encoder<W> {

/// The encoding options used to encode surfaces.
///
/// Defaults: `EncodeOptions::default()`
/// Default: `EncodeOptions::default()`
pub encoding: EncodeOptions,
/// Options regarding automatic mipmap generation.
///
/// Set `self.mipmaps.generate = true` to enable automatic mipmap generation.
///
/// Defaults: `MipmapOptions::default()`
/// Default: `MipmapOptions::default()`
pub mipmaps: MipmapOptions,

// internal cache for resizing
Expand Down Expand Up @@ -283,16 +283,30 @@ impl<W> Encoder<W> {
}
}

/// The filter to use when resizing images for mipmap generation.
///
/// ## See also
///
/// - [`MipmapOptions::resize_filter`]
#[derive(Debug, Clone, Copy, Default)]
pub enum ResizeFilter {
/// Nearest neighbor interpolation (=point filtering).
Nearest,
/// Box (also called area or binning).
///
/// This is the default filter, because it produces mipmaps that are
/// generally free of artifacts and sharp (without being over sharpened).
#[default]
Box,
/// Triangle filtering (=linear interpolation).
Triangle,
/// Mitchell interpolation.
Mitchell,
/// Lanczos interpolation with a radius of 3.
Lanczos3,
}

/// Options for automatic mipmap generation in [`Encoder`].
#[derive(Debug, Clone, Copy)]
pub struct MipmapOptions {
/// Whether to generate mipmaps for the texture.
Expand All @@ -301,23 +315,25 @@ pub struct MipmapOptions {
/// generate all mipmaps until the next level 0 object or EOF.
///
/// Note: Generating mipmaps for volume depth slices is not supported. This
/// will **NOT** result in an error and instead the encoder will silently
/// ignore the option.
/// will **NOT** result in an error. Instead, the encoder will silently
/// ignore the option and assume mipmap generation is disabled.
///
/// Default: `false`
pub generate: bool,
/// Whether the alpha channel (if any) is straight alpha.
/// Whether the alpha channel (if any) is straight alpha transparency.
///
/// This is important when generating mipmaps. Resizing RGBA with straight
/// alpha requires that the alpha channel is premultiplied into the color
/// channels before resizing and then unpremultiplied after resizing. This
/// channels before resizing and then un-premultiplied after resizing. This
/// is necessary to avoid color bleeding.
///
/// If the alpha channel is premultiplied alpha or custom (e.g. like in
/// channel-packed textures), this option should be set to `false`.
/// If the alpha channel is premultiplied alpha transparency or custom
/// (e.g. like in channel-packed textures), this option should be set to
/// `false`.
///
/// If this option is set to `false`, all channels will be resized
/// independently of each other.
/// independently of each other. If set to `true`, the alpha channel will
/// be interpreted as straight alpha transparency and handled accordingly.
///
/// Default: `true`
pub resize_straight_alpha: bool,
Expand Down
5 changes: 5 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@ pub enum EncodingError {
/// Returned by [`Encoder`](crate::Encoder) and [`encode()`](crate::encode()) when the format
/// does not support encoding.
UnsupportedFormat(Format),
/// Returned when the format requires the image size to be a multiple of
/// certain dimensions, but the provided image does not satisfy this.
///
/// The two `NonZeroU32` values specify the required width and height
/// multiples respectively.
InvalidSize(NonZeroU32, NonZeroU32),

/// Returned by [`Encoder`](crate::Encoder) when the user tries to write a surface
Expand Down
8 changes: 4 additions & 4 deletions src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub enum Format {
Y410,
Y416,

// sub-sampled formats
// subsampled formats
R1_UNORM,
R8G8_B8G8_UNORM,
G8R8_G8B8_UNORM,
Expand Down Expand Up @@ -147,13 +147,13 @@ impl Format {
}
/// Returns the format of a surface from a DXGI format.
///
/// `None` if the DXGI format is not supported for decoding.
/// `None` if the DXGI format is not supported for decoding/encoding.
pub const fn from_dxgi(dxgi: DxgiFormat) -> Option<Format> {
detect::dxgi_format_to_supported(dxgi)
}
/// Returns the format of a surface from a FourCC code.
///
/// `None` if the FourCC code is not supported for decoding.
/// `None` if the FourCC code is not supported for decoding/encoding.
pub const fn from_four_cc(four_cc: FourCC) -> Option<Format> {
detect::four_cc_to_supported(four_cc)
}
Expand Down Expand Up @@ -240,7 +240,7 @@ impl TryFrom<Format> for DxgiFormat {
Format::Y410 => DxgiFormat::Y410,
Format::Y416 => DxgiFormat::Y416,

// sub-sampled
// subsampled
Format::R1_UNORM => DxgiFormat::R1_UNORM,
Format::R8G8_B8G8_UNORM => DxgiFormat::R8G8_B8G8_UNORM,
Format::G8R8_G8B8_UNORM => DxgiFormat::G8R8_G8B8_UNORM,
Expand Down
6 changes: 3 additions & 3 deletions src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//!
//! [`RawHeader`] is a low-level representation of an unparsed DDS header. It is
//! bit-for-bit what is on disk. You rarely need to interact with this type, but
//! it can useful for manually detecting and parsing non-standard DDS files.
//! it can be useful for manually detecting and parsing non-standard DDS files.
//!
//! # Creating a header
//!
Expand Down Expand Up @@ -420,7 +420,7 @@ pub struct ParseOptions {
/// DDS files typically start with the magic bytes `"DDS "`. By default, the
/// decoder will check for these bytes and error if they are not present.
///
/// If this is set to `true`, the decoder assume that the magic bytes are
/// If this is set to `true`, the decoder assumes that the magic bytes are
/// not present and immediately start reading the header. This can be used
/// to read DDS files without magic bytes.
///
Expand Down Expand Up @@ -1871,7 +1871,7 @@ impl TryFrom<u32> for DxgiFormat {
type Error = u32;

fn try_from(value: u32) -> Result<Self, Self::Error> {
// NOTE: This implementation is NOT generated by the marco for
// NOTE: This implementation is NOT generated by the macro for
// performance and code size reasons. On virtually any optimization
// level, the below code translates to around 6 instructions, while a
// generated match arm (0 | 1 | 2 | ... | 115 | 130 | 131 | 132 => ...)
Expand Down
8 changes: 7 additions & 1 deletion src/iter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
use crate::{DataLayout, DataRegion, Size, SurfaceDescriptor, Texture, Volume};

/// Information about the surface to be read or written.
///
/// ## See also
///
/// - [`Decoder::surface_info`](crate::Decoder::surface_info)
/// - [`Encoder::surface_info`](crate::Encoder::surface_info)
#[derive(Debug, Clone, Copy)]
pub struct SurfaceInfo<'a> {
size: Size,
Expand Down Expand Up @@ -27,7 +33,7 @@ impl SurfaceInfo<'_> {
self.len
}

/// Whether this surface is has a mipmapping level greater than 0.
/// Whether this surface has a mipmap level greater than 0.
///
/// For textures and texture arrays, this means that the texture is not
/// a level 0 texture. For volumes, this means that the surface is not a
Expand Down
9 changes: 6 additions & 3 deletions src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ use crate::{
LayoutError, PixelInfo, Size,
};

/// An object or collection of objects in the data section of a DDS file.
pub trait DataRegion {
/// The number of bytes this object occupies in the data section of a DDS file.
///
/// It is guaranteed that `self.offset() + self.len() <= u64::MAX`.
/// It is guaranteed that `self.data_offset() + self.data_len() <= u64::MAX`.
/// See [`DataRegion::data_end()`].
fn data_len(&self) -> u64;
/// The byte offset of this object in the data section of a DDS file.
fn data_offset(&self) -> u64;
/// The byte offset of the byte after this object in the data section of a DDS file.
///
/// This is equivalent to `self.offset() + self.len()`.
/// This is equivalent to `self.data_offset() + self.data_len()`.
fn data_end(&self) -> u64 {
self.data_offset() + self.data_len()
}
Expand Down Expand Up @@ -396,6 +398,7 @@ impl DataRegion for Volume {
}
}

/// Describes what kind of elements the texture array contains.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TextureArrayKind {
/// An array of textures.
Expand Down Expand Up @@ -589,7 +592,7 @@ pub enum DataLayout {
/// }
/// ```
Volume(Volume),
/// A simply array of 2D textures.
/// A simple array of 2D textures.
///
/// All textures within the array have the same size, mipmap count, and
/// pixel format.
Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@
//! to get periodic updates on the encoding progress. See the [`Progress`] type
//! for more details.
//!
//! #### Cancellation
//!
//! The encoder supports cancelling the encoding operation using a
//! [`CancellationToken`] and [`Progress::with_cancellation()`].
//!
//! ### Low-level API
//!
//! Besides the `Encoder` and `Decoder` types, the library also exposes a low-level
Expand Down
Loading
Loading