Restore documentation on transparency/palette

This commit is contained in:
Andrew 2023-04-28 09:12:02 +12:00 committed by Josh Holmer
parent 184a2a6b32
commit cad122f904
6 changed files with 27 additions and 16 deletions

View file

@ -7,11 +7,20 @@ use crate::PngError;
/// The color type used to represent this image
pub enum ColorType {
/// Grayscale, with one color channel
Grayscale { transparent: Option<u16> },
Grayscale {
/// Optional shade of gray that should be rendered as transparent
transparent_shade: Option<u16>,
},
/// RGB, with three color channels
RGB { transparent: Option<RGB16> },
/// Indexed, with one byte per pixel representing one of up to 256 colors in the image
Indexed { palette: Vec<RGBA8> },
RGB {
/// Optional color value that should be rendered as transparent
transparent_color: Option<RGB16>,
},
/// Indexed, with one byte per pixel representing a color from the palette
Indexed {
/// The palette containing the colors used, up to 256 entries
palette: Vec<RGBA8>,
},
/// Grayscale + Alpha, with two color channels
GrayscaleAlpha,
/// RGBA, with four color channels

View file

@ -155,12 +155,12 @@ pub fn parse_ihdr_header(
Ok(IhdrData {
color_type: match byte_data[9] {
0 => ColorType::Grayscale {
transparent: trns_data
transparent_shade: trns_data
.filter(|t| t.len() >= 2)
.map(|t| u16::from_be_bytes([t[0], t[1]])),
},
2 => ColorType::RGB {
transparent: trns_data.filter(|t| t.len() >= 6).map(|t| RGB16 {
transparent_color: trns_data.filter(|t| t.len() >= 6).map(|t| RGB16 {
r: u16::from_be_bytes([t[0], t[1]]),
g: u16::from_be_bytes([t[2], t[3]]),
b: u16::from_be_bytes([t[4], t[5]]),

View file

@ -191,13 +191,13 @@ impl PngData {
}
}
ColorType::Grayscale {
transparent: Some(trns),
transparent_shade: Some(trns),
} => {
// Transparency pixel - 2 byte u16
write_png_block(b"tRNS", &trns.to_be_bytes(), &mut output);
}
ColorType::RGB {
transparent: Some(trns),
transparent_color: Some(trns),
} => {
// Transparency pixel - 6 byte RGB16
let trns_data: Vec<_> = trns.iter().flat_map(|c| c.to_be_bytes()).collect();

View file

@ -80,9 +80,11 @@ pub fn reduced_alpha_channel(png: &PngImage, optimize_alpha: bool) -> Option<Png
_ => trns as u16,
});
let target_color_type = match png.ihdr.color_type {
ColorType::GrayscaleAlpha => ColorType::Grayscale { transparent },
ColorType::GrayscaleAlpha => ColorType::Grayscale {
transparent_shade: transparent,
},
_ => ColorType::RGB {
transparent: transparent.map(|t| RGB16::new(t, t, t)),
transparent_color: transparent.map(|t| RGB16::new(t, t, t)),
},
};

View file

@ -127,7 +127,7 @@ pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Op
// If the image is grayscale we also need to reduce the transparency pixel
let color_type = if let ColorType::Grayscale {
transparent: Some(trans),
transparent_shade: Some(trans),
} = png.ihdr.color_type
{
let reduced_trans = (trans & 0xFF) >> (bit_depth - minimum_bits);
@ -140,7 +140,7 @@ pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Op
}
// If the transparency doesn't fit the new bit depth it is therefore unused - set it to None
ColorType::Grayscale {
transparent: if trans == check {
transparent_shade: if trans == check {
Some(reduced_trans)
} else {
None

View file

@ -41,9 +41,9 @@ pub fn reduce_to_palette(png: &PngImage) -> Option<PngImage> {
let mut raw_data = Vec::with_capacity(png.data.len());
let mut palette = FxIndexMap::default();
palette.reserve(257);
let ok = if let ColorType::RGB { transparent } = png.ihdr.color_type {
let ok = if let ColorType::RGB { transparent_color } = png.ihdr.color_type {
// Convert the RGB16 transparency to RGB8
let transparency_pixel = transparent.map(|t| t.map(|c| c as u8));
let transparency_pixel = transparent_color.map(|t| t.map(|c| c as u8));
reduce_scanline_to_palette(
png.data.as_rgb().iter().cloned().map(|px| {
px.alpha(if Some(px) != transparency_pixel {
@ -168,9 +168,9 @@ pub fn reduce_rgb_to_grayscale(png: &PngImage) -> Option<PngImage> {
}
let color_type = match png.ihdr.color_type {
ColorType::RGB { transparent } => ColorType::Grayscale {
ColorType::RGB { transparent_color } => ColorType::Grayscale {
// Copy the transparent component if it is also gray
transparent: transparent
transparent_shade: transparent_color
.filter(|t| t.r == t.g && t.g == t.b)
.map(|t| t.r),
},