Restore documentation on transparency/palette
This commit is contained in:
parent
184a2a6b32
commit
cad122f904
6 changed files with 27 additions and 16 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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]]),
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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)),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue