A few inconsequential changes
This commit is contained in:
parent
6c355b0c83
commit
9d48ae911e
2 changed files with 51 additions and 25 deletions
63
src/png.rs
63
src/png.rs
|
|
@ -263,7 +263,7 @@ impl PngData {
|
||||||
output.append(&mut ihdr_data);
|
output.append(&mut ihdr_data);
|
||||||
output.write_u32::<BigEndian>(crc).ok();
|
output.write_u32::<BigEndian>(crc).ok();
|
||||||
// Ancillary headers
|
// Ancillary headers
|
||||||
for (key, header) in &self.aux_headers {
|
for (key, header) in self.aux_headers.iter().filter(|&(ref key, _)| !(**key == "bKGD" || **key == "hIST" || **key == "tRNS")) {
|
||||||
let mut header_data = Vec::with_capacity(header.len() + 4);
|
let mut header_data = Vec::with_capacity(header.len() + 4);
|
||||||
header_data.extend(key.as_bytes());
|
header_data.extend(key.as_bytes());
|
||||||
header_data.extend_from_slice(header);
|
header_data.extend_from_slice(header);
|
||||||
|
|
@ -305,6 +305,17 @@ impl PngData {
|
||||||
output.append(&mut pixel_data);
|
output.append(&mut pixel_data);
|
||||||
output.write_u32::<BigEndian>(crc).ok();
|
output.write_u32::<BigEndian>(crc).ok();
|
||||||
}
|
}
|
||||||
|
// Special ancillary headers that need to come after PLTE but before IDAT
|
||||||
|
for (key, header) in self.aux_headers.iter().filter(|&(ref key, _)| **key == "bKGD" || **key == "hIST" || **key == "tRNS") {
|
||||||
|
let mut header_data = Vec::with_capacity(header.len() + 4);
|
||||||
|
header_data.extend(key.as_bytes());
|
||||||
|
header_data.extend_from_slice(header);
|
||||||
|
output.reserve(header_data.len() + 8);
|
||||||
|
output.write_u32::<BigEndian>(header_data.len() as u32 - 4).ok();
|
||||||
|
let crc = crc32::checksum_ieee(&header_data);
|
||||||
|
output.append(&mut header_data);
|
||||||
|
output.write_u32::<BigEndian>(crc).ok();
|
||||||
|
}
|
||||||
// IDAT data
|
// IDAT data
|
||||||
let mut idat_data = Vec::with_capacity(self.idat_data.len() + 4);
|
let mut idat_data = Vec::with_capacity(self.idat_data.len() + 4);
|
||||||
idat_data.extend_from_slice(b"IDAT");
|
idat_data.extend_from_slice(b"IDAT");
|
||||||
|
|
@ -788,34 +799,39 @@ fn reduce_rgba_to_grayscale_alpha(png: &PngData) -> Option<Vec<u8>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reduce_rgba_to_palette(png: &PngData) -> Option<(Vec<u8>, Vec<u8>, Vec<u8>)> {
|
fn reduce_rgba_to_palette(png: &PngData) -> Option<(Vec<u8>, Vec<u8>, Vec<u8>)> {
|
||||||
|
if png.ihdr_data.bit_depth != BitDepth::Eight {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let mut reduced = Vec::with_capacity(png.raw_data.len());
|
let mut reduced = Vec::with_capacity(png.raw_data.len());
|
||||||
let mut palette = HashMap::with_capacity(255);
|
let mut palette = Vec::with_capacity(256);
|
||||||
let byte_depth: usize = (png.ihdr_data.bit_depth.as_u8() >> 3) as usize;
|
let bpp: usize = 4;
|
||||||
let bpp: usize = 4 * byte_depth;
|
|
||||||
for line in png.scan_lines() {
|
for line in png.scan_lines() {
|
||||||
reduced.push(line.filter);
|
reduced.push(line.filter);
|
||||||
let mut cur_pixel = Vec::with_capacity(bpp);
|
let mut cur_pixel = Vec::with_capacity(bpp);
|
||||||
for (i, byte) in line.data.iter().enumerate() {
|
for (i, byte) in line.data.iter().enumerate() {
|
||||||
cur_pixel.push(*byte);
|
cur_pixel.push(*byte);
|
||||||
if i % bpp == bpp - 1 {
|
if i % bpp == bpp - 1 {
|
||||||
if !palette.contains_key(&cur_pixel) {
|
if !palette.contains(&cur_pixel) {
|
||||||
let len = palette.len();
|
let len = palette.len();
|
||||||
if len >= 255 {
|
if len == 256 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
palette.insert(cur_pixel.clone(), len as u8);
|
palette.push(cur_pixel.clone());
|
||||||
|
reduced.push(len as u8);
|
||||||
|
} else {
|
||||||
|
let idx = palette.iter().enumerate().find(|&x| x.1 == &cur_pixel).unwrap().0;
|
||||||
|
reduced.push(idx as u8);
|
||||||
}
|
}
|
||||||
reduced.push(*palette.get(&cur_pixel).unwrap());
|
|
||||||
cur_pixel.clear();
|
cur_pixel.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut color_palette = Vec::with_capacity(palette.len() * byte_depth * 3);
|
let mut color_palette = Vec::with_capacity(palette.len() * 3);
|
||||||
let mut trans_palette = Vec::with_capacity(palette.len() * byte_depth);
|
let mut trans_palette = Vec::with_capacity(palette.len());
|
||||||
for color in palette.keys() {
|
for color in &palette {
|
||||||
for (i, byte) in color.iter().enumerate() {
|
for (i, byte) in color.iter().enumerate() {
|
||||||
if i < byte_depth * 3 {
|
if i < 3 {
|
||||||
color_palette.push(*byte);
|
color_palette.push(*byte);
|
||||||
} else {
|
} else {
|
||||||
trans_palette.push(*byte);
|
trans_palette.push(*byte);
|
||||||
|
|
@ -827,31 +843,36 @@ fn reduce_rgba_to_palette(png: &PngData) -> Option<(Vec<u8>, Vec<u8>, Vec<u8>)>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reduce_rgb_to_palette(png: &PngData) -> Option<(Vec<u8>, Vec<u8>)> {
|
fn reduce_rgb_to_palette(png: &PngData) -> Option<(Vec<u8>, Vec<u8>)> {
|
||||||
|
if png.ihdr_data.bit_depth != BitDepth::Eight {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let mut reduced = Vec::with_capacity(png.raw_data.len());
|
let mut reduced = Vec::with_capacity(png.raw_data.len());
|
||||||
let mut palette = HashMap::with_capacity(255);
|
let mut palette = Vec::with_capacity(256);
|
||||||
let byte_depth: usize = (png.ihdr_data.bit_depth.as_u8() >> 3) as usize;
|
let bpp: usize = 3;
|
||||||
let bpp: usize = 3 * byte_depth;
|
|
||||||
for line in png.scan_lines() {
|
for line in png.scan_lines() {
|
||||||
reduced.push(line.filter);
|
reduced.push(line.filter);
|
||||||
let mut cur_pixel = Vec::with_capacity(bpp);
|
let mut cur_pixel = Vec::with_capacity(bpp);
|
||||||
for (i, byte) in line.data.iter().enumerate() {
|
for (i, byte) in line.data.iter().enumerate() {
|
||||||
cur_pixel.push(*byte);
|
cur_pixel.push(*byte);
|
||||||
if i % bpp == bpp - 1 {
|
if i % bpp == bpp - 1 {
|
||||||
if !palette.contains_key(&cur_pixel) {
|
if !palette.contains(&cur_pixel) {
|
||||||
let len = palette.len();
|
let len = palette.len();
|
||||||
if len >= 255 {
|
if len == 256 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
palette.insert(cur_pixel.clone(), len as u8);
|
palette.push(cur_pixel.clone());
|
||||||
|
reduced.push(len as u8);
|
||||||
|
} else {
|
||||||
|
let idx = palette.iter().enumerate().find(|&x| x.1 == &cur_pixel).unwrap().0;
|
||||||
|
reduced.push(idx as u8);
|
||||||
}
|
}
|
||||||
reduced.push(*palette.get(&cur_pixel).unwrap());
|
|
||||||
cur_pixel.clear();
|
cur_pixel.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut color_palette = Vec::with_capacity(palette.len() * byte_depth * 3);
|
let mut color_palette = Vec::with_capacity(palette.len() * 3);
|
||||||
for color in palette.keys() {
|
for color in &palette {
|
||||||
color_palette.extend_from_slice(&color);
|
color_palette.extend_from_slice(&color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -383,10 +383,7 @@ fn strip_headers() {
|
||||||
assert!(output.exists());
|
assert!(output.exists());
|
||||||
|
|
||||||
let png = match png::PngData::new(&output) {
|
let png = match png::PngData::new(&output) {
|
||||||
Ok(x) => {
|
Ok(x) => x,
|
||||||
remove_file(output).ok();
|
|
||||||
x
|
|
||||||
},
|
|
||||||
Err(x) => {
|
Err(x) => {
|
||||||
remove_file(output).ok();
|
remove_file(output).ok();
|
||||||
panic!(x.to_owned())
|
panic!(x.to_owned())
|
||||||
|
|
@ -394,6 +391,14 @@ fn strip_headers() {
|
||||||
};
|
};
|
||||||
|
|
||||||
assert!(!png.aux_headers.contains_key("tEXt"));
|
assert!(!png.aux_headers.contains_key("tEXt"));
|
||||||
|
|
||||||
|
let old_png = image::open(&input).unwrap();
|
||||||
|
let new_png = image::open(&output).unwrap();
|
||||||
|
|
||||||
|
// Conversion should be lossless
|
||||||
|
assert!(old_png.pixels().map(|x| x.2.channels().to_owned()).collect::<Vec<Vec<u8>>>() == new_png.pixels().map(|x| x.2.channels().to_owned()).collect::<Vec<Vec<u8>>>());
|
||||||
|
|
||||||
|
remove_file(output).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue