Add documentation to publicly visible areas of lib

Fixes #17
This commit is contained in:
Joshua Holmer 2016-03-08 11:59:37 -05:00
parent 911f51faa9
commit eba8062ba5
4 changed files with 99 additions and 0 deletions

View file

@ -1,3 +1,6 @@
**Version 0.2.1**
- Add rustdoc for public methods and structs
**Version 0.2.0**
- Fix program version that is displayed when running `oxipng -V`
- Ensure `--quiet` mode is actually quiet (@SethDusek [#20](https://github.com/shssoichiro/oxipng/pull/20))

View file

@ -1,6 +1,7 @@
use libz_sys;
use libc::c_int;
/// Decompress a data stream using the DEFLATE algorithm
pub fn inflate(data: &[u8]) -> Result<Vec<u8>, String> {
let mut input = data.to_owned();
let mut stream = super::stream::Stream::new_decompress();
@ -17,6 +18,7 @@ pub fn inflate(data: &[u8]) -> Result<Vec<u8>, String> {
Ok(output)
}
/// Compress a data stream using the zlib implementation of the DEFLATE algorithm
pub fn deflate(data: &[u8], zc: u8, zm: u8, zs: u8, zw: u8) -> Result<Vec<u8>, String> {
let mut input = data.to_owned();
let mut stream = super::stream::Stream::new_compress(zc as c_int,

View file

@ -17,33 +17,66 @@ pub mod deflate {
pub mod png;
#[derive(Clone,Debug)]
/// Options controlling the output of the `optimize` function
pub struct Options {
/// Whether the input file should be backed up before writing the output
pub backup: bool,
/// Path to write the output file to
pub out_file: PathBuf,
/// Used only in CLI interface
pub out_dir: Option<PathBuf>,
/// Write to stdout instead of a file
pub stdout: bool,
/// Attempt to fix errors when decoding the input file
pub fix_errors: bool,
/// Don't actually write any output, just calculate the best results
pub pretend: bool,
/// Used only in CLI interface
pub recursive: bool,
/// Overwrite existing output files
pub clobber: bool,
/// Create new output files if they don't exist
pub create: bool,
/// Write to output even if there was no improvement in compression
pub force: bool,
/// Ensure the output file has the same permissions as the input file
pub preserve_attrs: bool,
/// How verbose the console logging should be (`None` for quiet, `Some(0)` for normal, `Some(1)` for verbose)
pub verbosity: Option<u8>,
/// Which filters to try on the file (0-5)
pub filter: HashSet<u8>,
/// Whether to change the interlacing type of the file
/// `None` will not change the current interlacing type
/// `Some(x)` will change the file to interlacing mode `x`
pub interlace: Option<u8>,
/// Which zlib compression levels to try on the file (1-9)
pub compression: HashSet<u8>,
/// Which zlib memory levels to try on the file (1-9)
pub memory: HashSet<u8>,
/// Which zlib compression strategies to try on the file (0-3)
pub strategies: HashSet<u8>,
/// Window size to use when compressing the file, as `2^window` bytes
/// Doesn't affect compression but may affect speed and memory usage
/// 15 is recommended default, 8-15 are valid values
pub window: u8,
/// Whether to attempt bit depth reduction
pub bit_depth_reduction: bool,
/// Whether to attempt color type reduction
pub color_type_reduction: bool,
/// Whether to attempt palette reduction
pub palette_reduction: bool,
/// Whether to perform IDAT recoding
/// If any type of reduction is performed, IDAT recoding will be performed
/// regardless of this setting
pub idat_recoding: bool,
/// Which headers to strip from the PNG file, if any
pub strip: png::Headers,
/// Whether to use heuristics to pick the best filter and compression
/// Intended for use with `-o 1` from the CLI interface
pub use_heuristics: bool,
}
/// Perform optimization on the input file using the options provided
pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> {
// Decode PNG from file
if opts.verbosity.is_some() {

View file

@ -10,11 +10,17 @@ use std::iter::Iterator;
use std::path::Path;
#[derive(Debug,PartialEq,Clone,Copy)]
/// The color type used to represent this image
pub enum ColorType {
/// Grayscale, with one color channel
Grayscale,
/// RGB, with three color channels
RGB,
/// Indexed, with one byte per pixel representing one of up to 256 colors in the image
Indexed,
/// Grayscale + Alpha, with two color channels
GrayscaleAlpha,
/// RGBA, with four color channels
RGBA,
}
@ -45,11 +51,17 @@ impl ColorType {
}
#[derive(Debug,PartialEq,Clone,Copy)]
/// The number of bits to be used per channel per pixel
pub enum BitDepth {
/// One bit per channel per pixel
One,
/// Two bits per channel per pixel
Two,
/// Four bits per channel per pixel
Four,
/// Eight bits per channel per pixel
Eight,
/// Sixteen bits per channel per pixel
Sixteen,
}
@ -68,6 +80,7 @@ impl fmt::Display for BitDepth {
}
impl BitDepth {
/// Retrieve the number of bits per channel per pixel as a `u8`
pub fn as_u8(&self) -> u8 {
match *self {
BitDepth::One => 1,
@ -77,6 +90,7 @@ impl BitDepth {
BitDepth::Sixteen => 16,
}
}
/// Parse a number of bits per channel per pixel into a `BitDepth`
pub fn from_u8(depth: u8) -> BitDepth {
match depth {
1 => BitDepth::One,
@ -90,15 +104,22 @@ impl BitDepth {
}
#[derive(Debug,PartialEq,Clone)]
/// Options to use for performing operations on headers (such as stripping)
pub enum Headers {
/// None
None,
/// Some, with a list of 4-character chunk codes
Some(Vec<String>),
/// Headers that won't affect rendering (all but cHRM, gAMA, iCCP, sBIT, sRGB, bKGD, hIST, pHYs, sPLT)
Safe,
/// All non-critical headers
All,
}
#[derive(Debug,Clone)]
/// An iterator over the scan lines of a PNG image
pub struct ScanLines<'a> {
/// A reference to the PNG image being iterated upon
pub png: &'a PngData,
start: usize,
end: usize,
@ -126,34 +147,55 @@ impl<'a> Iterator for ScanLines<'a> {
}
#[derive(Debug,Clone)]
/// A scan line in a PNG image
pub struct ScanLine {
/// The filter type used to encode the current scan line (0-4)
pub filter: u8,
/// The byte data for the current scan line, encoded with the filter specified in the `filter` field
pub data: Vec<u8>,
}
#[derive(Debug,Clone)]
/// Contains all data relevant to a PNG image
pub struct PngData {
/// The filtered and compressed data of the IDAT chunk
pub idat_data: Vec<u8>,
/// The headers stored in the IHDR chunk
pub ihdr_data: IhdrData,
/// The uncompressed, optionally filtered data from the IDAT chunk
pub raw_data: Vec<u8>,
/// The palette containing colors used in an Indexed image
/// Contains 3 bytes per color (R+G+B), up to 768
pub palette: Option<Vec<u8>>,
/// The pixel value that should be rendered as transparent
pub transparency_pixel: Option<Vec<u8>>,
/// A map of how transparent each color in the palette should be
pub transparency_palette: Option<Vec<u8>>,
/// All non-critical headers from the PNG are stored here
pub aux_headers: HashMap<String, Vec<u8>>,
}
#[derive(Debug,Clone,Copy)]
/// Headers from the IHDR chunk of the image
pub struct IhdrData {
/// The width of the image in pixels
pub width: u32,
/// The height of the image in pixels
pub height: u32,
/// The color type of the image
pub color_type: ColorType,
/// The bit depth of the image
pub bit_depth: BitDepth,
/// The compression method used for this image (0 for DEFLATE)
pub compression: u8,
/// The filter mode used for this image (currently only 0 is valid)
pub filter: u8,
/// The interlacing mode of the image (0 = None, 1 = Adam7)
pub interlaced: u8,
}
impl PngData {
/// Create a new `PngData` struct by opening a file
pub fn new(filepath: &Path) -> Result<PngData, String> {
let mut file = match File::open(filepath) {
Ok(f) => f,
@ -237,6 +279,7 @@ impl PngData {
// Return the PngData
Ok(png_data)
}
/// Return the number of channels in the image, based on color type
pub fn channels_per_pixel(&self) -> u8 {
match self.ihdr_data.color_type {
ColorType::Grayscale | ColorType::Indexed => 1,
@ -245,6 +288,7 @@ impl PngData {
ColorType::RGBA => 4,
}
}
/// Format the `PngData` struct into a valid PNG bytestream
pub fn output(&self) -> Vec<u8> {
// FIXME: This code can all be refactored
// PNG header
@ -341,6 +385,7 @@ impl PngData {
output
}
/// Return an iterator over the scanlines of the image
pub fn scan_lines(&self) -> ScanLines {
ScanLines {
png: &self,
@ -348,6 +393,7 @@ impl PngData {
end: 0,
}
}
/// Reverse all filters applied on the image, returning an unfiltered IDAT bytestream
pub fn unfilter_image(&self) -> Vec<u8> {
let mut unfiltered = Vec::with_capacity(self.raw_data.len());
let tmp = self.ihdr_data.bit_depth.as_u8() * self.channels_per_pixel();
@ -442,6 +488,13 @@ impl PngData {
}
unfiltered
}
/// Apply the specified filter type to all rows in the image
/// 0: None
/// 1: Sub
/// 2: Up
/// 3: Average
/// 4: Paeth
/// 5: All (heuristically pick the best filter for each line)
pub fn filter_image(&self, filter: u8) -> Vec<u8> {
let mut filtered = Vec::with_capacity(self.raw_data.len());
let tmp = self.ihdr_data.bit_depth.as_u8() * self.channels_per_pixel();
@ -601,6 +654,8 @@ impl PngData {
}
filtered
}
/// Attempt to reduce the bit depth of the image
/// Returns true if the bit depth was reduced, false otherwise
pub fn reduce_bit_depth(&mut self) -> bool {
if self.ihdr_data.bit_depth != BitDepth::Sixteen {
if self.ihdr_data.color_type == ColorType::Indexed ||
@ -645,10 +700,14 @@ impl PngData {
self.raw_data = reduced;
true
}
/// Attempt to reduce the number of colors in the palette
/// Returns true if the palette was reduced, false otherwise
pub fn reduce_palette(&mut self) -> bool {
// TODO: Implement
false
}
/// Attempt to reduce the color type of the image
/// Returns true if the color type was reduced, false otherwise
pub fn reduce_color_type(&mut self) -> bool {
let mut changed = false;
let mut should_reduce_bit_depth = false;
@ -732,6 +791,8 @@ impl PngData {
changed
}
/// Convert the image to the specified interlacing type
/// Returns true if the interlacing was changed, false otherwise
pub fn change_interlacing(&mut self, interlace: u8) -> bool {
// TODO: Implement
if interlace != self.ihdr_data.interlaced {