Skip to content

Commit 2531272

Browse files
Add crate-level documentation (image-rs#61)
1 parent 129e7c4 commit 2531272

File tree

4 files changed

+163
-2
lines changed

4 files changed

+163
-2
lines changed

src/color/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ impl ColorFormat {
8585
self.channels.count() * self.precision.size()
8686
}
8787

88-
/// The number of bytes per pixel in a decoded surface/output buffer.
88+
/// The number of **bytes** in a decoded surface/output buffer.
8989
///
90-
/// If the number if bytes is larger than `isize::MAX`, `None` is returned.
90+
/// If the number of bytes is larger than `isize::MAX`, `None` is returned.
9191
pub fn buffer_size(&self, size: Size) -> Option<usize> {
9292
let bytes_per_pixel = self.bytes_per_pixel() as u64;
9393
let pixels = size.pixels();

src/decoder.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use crate::{
99
};
1010

1111
/// A decoder for reading the pixel data of a DDS file.
12+
///
13+
/// See crate-level documentation for usage examples.
1214
pub struct Decoder<R> {
1315
reader: R,
1416

@@ -20,12 +22,19 @@ pub struct Decoder<R> {
2022
pub options: DecodeOptions,
2123
}
2224
impl<R> Decoder<R> {
25+
/// Creates a new decoder from the given reader.
26+
///
27+
/// Same as [`Self::new_with_options`] with default options.
2328
pub fn new(reader: R) -> Result<Self, DecodingError>
2429
where
2530
R: Read,
2631
{
2732
Self::new_with_options(reader, &ParseOptions::default())
2833
}
34+
/// Creates a new decoder from the given reader.
35+
///
36+
/// This will read the header from the reader. How the header is read can
37+
/// be configured with the given options.
2938
pub fn new_with_options(mut reader: R, options: &ParseOptions) -> Result<Self, DecodingError>
3039
where
3140
R: Read,
@@ -34,10 +43,19 @@ impl<R> Decoder<R> {
3443
Self::from_header(reader, header)
3544
}
3645

46+
/// Creates a new decoder from the given reader and header.
47+
///
48+
/// Same as [`Self::from_header_with`] with the [`Format`] being detected
49+
/// from the given header.
3750
pub fn from_header(reader: R, header: Header) -> Result<Self, DecodingError> {
3851
let format = Format::from_header(&header)?;
3952
Self::from_header_with(reader, header, format)
4053
}
54+
/// Creates a new decoder from the given reader, header, and format.
55+
///
56+
/// Calling this method will NOT read data from the reader. The header and
57+
/// format are used to determine the layout of the data in the DDS file.
58+
/// The reader will only be used again when reading surfaces or seeking.
4159
pub fn from_header_with(
4260
reader: R,
4361
header: Header,

src/encoder.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use crate::{
1010
};
1111

1212
/// An encoder for DDS files.
13+
///
14+
/// See crate-level documentation for usage examples.
1315
pub struct Encoder<W> {
1416
writer: W,
1517
format: Format,

src/lib.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,144 @@
1+
//! # DDS
2+
//!
3+
//! A Rust library for decoding and encoding DDS (DirectDraw Surface) files.
4+
//!
5+
//! ## The DDS format
6+
//!
7+
//! DDS is a container format for storing compressed and uncompressed textures,
8+
//! cube maps, volumes, buffers, and arrays of the before. It is used by
9+
//! DirectX, OpenGL, Vulkan, and other graphics APIs.
10+
//!
11+
//! A DDS files has 2 parts: a header and a data section. The header describes
12+
//! the type of data in the file (e.g. a BC1-compressed 100x200px texture) and
13+
//! determines the layout of the data section. The data section then contains
14+
//! the binary pixel data.
15+
//!
16+
//! ## Features
17+
//!
18+
//! - `rayon` (default): Parallel encoding using the `rayon` crate.
19+
//!
20+
//! This feature will enable parallel encoding of DDS files. Both the
21+
//! high-level [`Encoder`] and low-level [`encode()`] functions will use this
22+
//! feature to speed up processing.
23+
//!
24+
//! All features marked with "(default)" are enabled by default.
25+
//!
26+
//! ## Usage
27+
//!
28+
//! ### Decoding
29+
//!
30+
//! The [`Decoder`] type is the high-level interface for decoding DDS files.
31+
//!
32+
//! The most common case, a single image, can be decoded as follows:
33+
//!
34+
//! ```no_run
35+
//! # use dds::*;
36+
//! # use std::fs::File;
37+
//! let file = File::open("path/to/file.dds").unwrap();
38+
//! let mut decoder = Decoder::new(file).unwrap();
39+
//! // make sure the file is a single image
40+
//! assert!(decoder.layout().texture().is_some());
41+
//! // prepare a buffer to decode into
42+
//! let mut data = vec![0u8; decoder.main_size().pixels() as usize * 4];
43+
//! // create an image view from the buffer
44+
//! let view = ImageViewMut::new(&mut data, decoder.main_size(), ColorFormat::RGBA_U8).unwrap();
45+
//! // decode the image into the buffer
46+
//! decoder.read_surface(view).unwrap();
47+
//! ```
48+
//!
49+
//! Cube maps can be detected using `decoder.layout().is_cube_map()` and decoded
50+
//! with [`Decoder::read_cube_map`].
51+
//!
52+
//! Volumes have to be read one depth slice at a time using [`Decoder::read_surface`].
53+
//!
54+
//! It is also possible to decode a rectangle of a surface using
55+
//! [`Decoder::read_surface_rect`].
56+
//!
57+
//! ### Encoding
58+
//!
59+
//! Since the data of a DDS file is determined by the header, the first step to
60+
//! encoding a DDS file is to create a header. See the documentation of
61+
//! the [`crate::header`] module for more details.
62+
//!
63+
//! ```no_run
64+
//! # use dds::{*, header::*};
65+
//! # use std::fs::File;
66+
//! fn save_rgba_image(
67+
//! file: &mut File,
68+
//! image_data: &[u8],
69+
//! width: u32,
70+
//! height: u32,
71+
//! ) -> Result<(), EncodingError> {
72+
//! let format = Format::BC1_UNORM;
73+
//! let header = Header::new_image(width, height, format);
74+
//!
75+
//! let mut encoder = Encoder::new(file, format, &header)?;
76+
//! encoder.options.quality = CompressionQuality::Fast;
77+
//!
78+
//! let view = ImageView::new(image_data, Size::new(width, height), ColorFormat::RGBA_U8)
79+
//! .expect("invalid image data");
80+
//! encoder.write_surface(view)?;
81+
//! encoder.finish()?;
82+
//! Ok(())
83+
//! }
84+
//! ```
85+
//!
86+
//! Note the use of [`Encoder::finish()`]. This method will verify that the
87+
//! file contains all necessary data.
88+
//!
89+
//! To create DDS files with mipmaps, use [`Encoder::write_surface_with`]:
90+
//!
91+
//! ```no_run
92+
//! # use dds::{*, header::*};
93+
//! # use std::fs::File;
94+
//! fn save_rgba_image_with_mipmaps(
95+
//! file: &mut File,
96+
//! image_data: &[u8],
97+
//! width: u32,
98+
//! height: u32,
99+
//! ) -> Result<(), EncodingError> {
100+
//! let format = Format::BC1_UNORM;
101+
//! let header = Header::new_image(width, height, format).with_mipmaps();
102+
//!
103+
//! let mut encoder = Encoder::new(file, format, &header)?;
104+
//! encoder.options.quality = CompressionQuality::Fast;
105+
//!
106+
//! let view = ImageView::new(image_data, Size::new(width, height), ColorFormat::RGBA_U8)
107+
//! .expect("invalid image data");
108+
//! let write_options = WriteOptions {
109+
//! generate_mipmaps: true,
110+
//! ..Default::default()
111+
//! };
112+
//! encoder.write_surface_with(view, None, &write_options)?;
113+
//! encoder.finish()?;
114+
//! Ok(())
115+
//! }
116+
//! ```
117+
//!
118+
//! Cube maps can be created by encoding their 6 faces in the order:
119+
//! +X -X +Y -Y +Z -Z.
120+
//!
121+
//! Volumes have to be encoded one depth slice at a time using [`Encoder::write_surface`].
122+
//!
123+
//! ### Progress reporting
124+
//!
125+
//! The decoder is generally so fast that progress reporting is not needed.
126+
//!
127+
//! The encoder, however, can take a long time to encode large images. Use the
128+
//! `progress` parameter of the [`Encoder::write_surface_with`] method to get
129+
//! periodic updates on the encoding progress. See the [`Progress`] type for
130+
//! more details.
131+
//!
132+
//! ### Low-level API
133+
//!
134+
//! Besides the `Encoder` and `Decoder` types, the library also exposes a low-level
135+
//! API for encoding and decoding DDS surfaces. It should generally not be
136+
//! necessary to use this API.
137+
//!
138+
//! The [`encode()`] and [`decode()`] functions are used to encode and decode a
139+
//! single DDS surface. The [`SplitSurface`] type can be used to split a surface
140+
//! into multiple fragments for parallel encoding.
141+
1142
#![forbid(unsafe_code)]
2143

3144
mod cast;

0 commit comments

Comments
 (0)