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 /// The color type used to represent this image
pub enum ColorType { pub enum ColorType {
/// Grayscale, with one color channel /// 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, with three color channels
RGB { transparent: Option<RGB16> }, RGB {
/// Indexed, with one byte per pixel representing one of up to 256 colors in the image /// Optional color value that should be rendered as transparent
Indexed { palette: Vec<RGBA8> }, 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 /// Grayscale + Alpha, with two color channels
GrayscaleAlpha, GrayscaleAlpha,
/// RGBA, with four color channels /// RGBA, with four color channels

View file

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

View file

@ -191,13 +191,13 @@ impl PngData {
} }
} }
ColorType::Grayscale { ColorType::Grayscale {
transparent: Some(trns), transparent_shade: Some(trns),
} => { } => {
// Transparency pixel - 2 byte u16 // Transparency pixel - 2 byte u16
write_png_block(b"tRNS", &trns.to_be_bytes(), &mut output); write_png_block(b"tRNS", &trns.to_be_bytes(), &mut output);
} }
ColorType::RGB { ColorType::RGB {
transparent: Some(trns), transparent_color: Some(trns),
} => { } => {
// Transparency pixel - 6 byte RGB16 // Transparency pixel - 6 byte RGB16
let trns_data: Vec<_> = trns.iter().flat_map(|c| c.to_be_bytes()).collect(); 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, _ => trns as u16,
}); });
let target_color_type = match png.ihdr.color_type { let target_color_type = match png.ihdr.color_type {
ColorType::GrayscaleAlpha => ColorType::Grayscale { transparent }, ColorType::GrayscaleAlpha => ColorType::Grayscale {
transparent_shade: transparent,
},
_ => ColorType::RGB { _ => 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 // If the image is grayscale we also need to reduce the transparency pixel
let color_type = if let ColorType::Grayscale { let color_type = if let ColorType::Grayscale {
transparent: Some(trans), transparent_shade: Some(trans),
} = png.ihdr.color_type } = png.ihdr.color_type
{ {
let reduced_trans = (trans & 0xFF) >> (bit_depth - minimum_bits); 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 // If the transparency doesn't fit the new bit depth it is therefore unused - set it to None
ColorType::Grayscale { ColorType::Grayscale {
transparent: if trans == check { transparent_shade: if trans == check {
Some(reduced_trans) Some(reduced_trans)
} else { } else {
None 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 raw_data = Vec::with_capacity(png.data.len());
let mut palette = FxIndexMap::default(); let mut palette = FxIndexMap::default();
palette.reserve(257); 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 // 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( reduce_scanline_to_palette(
png.data.as_rgb().iter().cloned().map(|px| { png.data.as_rgb().iter().cloned().map(|px| {
px.alpha(if Some(px) != transparency_pixel { 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 { 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 // 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) .filter(|t| t.r == t.g && t.g == t.b)
.map(|t| t.r), .map(|t| t.r),
}, },