Expand depth to 8-bit
This commit is contained in:
parent
f109752ec1
commit
f8a93545ea
1 changed files with 64 additions and 0 deletions
|
|
@ -177,3 +177,67 @@ pub fn reduced_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> O
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expand a 1/2/4-bit image to 8-bit, returning the expanded image if successful
|
||||||
|
#[must_use]
|
||||||
|
pub fn expanded_bit_depth_to_8(png: &PngImage) -> Option<PngImage> {
|
||||||
|
let bit_depth = png.ihdr.bit_depth as u32;
|
||||||
|
if bit_depth >= 8 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
// Calculate the current number of pixels per byte
|
||||||
|
let ppb = 8 / bit_depth;
|
||||||
|
let is_gray = matches!(png.ihdr.color_type, ColorType::Grayscale { .. });
|
||||||
|
|
||||||
|
let mut reduced = Vec::with_capacity((png.ihdr.width * png.ihdr.height) as usize);
|
||||||
|
let mut length = 0;
|
||||||
|
let mask = (1 << bit_depth) - 1;
|
||||||
|
for line in png.scan_lines(false) {
|
||||||
|
for &(mut byte) in line.data {
|
||||||
|
// Loop over each pixel in the byte
|
||||||
|
for _ in 0..ppb {
|
||||||
|
// Align the current pixel with the mask
|
||||||
|
byte = byte.rotate_left(bit_depth);
|
||||||
|
let mut val = byte & mask;
|
||||||
|
if is_gray {
|
||||||
|
// Expand gray by repeating the bits
|
||||||
|
let mut bits = bit_depth;
|
||||||
|
while bits < 8 {
|
||||||
|
val = val << bits | val;
|
||||||
|
bits <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reduced.push(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Trim any overflow
|
||||||
|
length += line.num_pixels;
|
||||||
|
reduced.truncate(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the image is grayscale we also need to expand the transparency pixel
|
||||||
|
let color_type = if let ColorType::Grayscale {
|
||||||
|
transparent_shade: Some(mut trans),
|
||||||
|
} = png.ihdr.color_type
|
||||||
|
{
|
||||||
|
let mut bits = bit_depth;
|
||||||
|
while bits < 8 {
|
||||||
|
trans = trans << bits | trans;
|
||||||
|
bits <<= 1;
|
||||||
|
}
|
||||||
|
ColorType::Grayscale {
|
||||||
|
transparent_shade: Some(trans),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
png.ihdr.color_type.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(PngImage {
|
||||||
|
data: reduced,
|
||||||
|
ihdr: IhdrData {
|
||||||
|
color_type,
|
||||||
|
bit_depth: BitDepth::Eight,
|
||||||
|
..png.ihdr
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue