commit
ad494e5a71
2 changed files with 18 additions and 14 deletions
|
|
@ -1,3 +1,6 @@
|
||||||
|
**Version 0.3.1 (unreleased)**
|
||||||
|
- Performance optimizations
|
||||||
|
|
||||||
**Version 0.3.0**
|
**Version 0.3.0**
|
||||||
- Properly decode interlaced images
|
- Properly decode interlaced images
|
||||||
- [SEMVER_MINOR] Allow converting between progressive and interlaced images ([#3](https://github.com/shssoichiro/oxipng/issues/3))
|
- [SEMVER_MINOR] Allow converting between progressive and interlaced images ([#3](https://github.com/shssoichiro/oxipng/issues/3))
|
||||||
|
|
|
||||||
29
src/png.rs
29
src/png.rs
|
|
@ -473,12 +473,8 @@ impl PngData {
|
||||||
let (best_filter, best_line) = trials.iter()
|
let (best_filter, best_line) = trials.iter()
|
||||||
.min_by_key(|x| {
|
.min_by_key(|x| {
|
||||||
x.1.iter().fold(0u64, |acc, &x| {
|
x.1.iter().fold(0u64, |acc, &x| {
|
||||||
let signed: i16 = if x > 127 {
|
let signed = x as i8;
|
||||||
(x as i16) - 256
|
acc + (signed as i16).abs() as u64
|
||||||
} else {
|
|
||||||
x as i16
|
|
||||||
};
|
|
||||||
acc + signed.abs() as u64
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -685,7 +681,7 @@ fn interlace_image(png: &mut PngData) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Copy pixels into interlaced passes
|
// Copy pixels into interlaced passes
|
||||||
let pix_modulo = (((i / bits_per_pixel as usize) as f32).floor() as usize) % 8;
|
let pix_modulo = (i / bits_per_pixel as usize) % 8;
|
||||||
match index % 8 {
|
match index % 8 {
|
||||||
0 => {
|
0 => {
|
||||||
match pix_modulo {
|
match pix_modulo {
|
||||||
|
|
@ -1039,10 +1035,11 @@ fn reduce_rgba_to_rgb(png: &PngData) -> Option<Vec<u8>> {
|
||||||
let mut reduced = Vec::with_capacity(png.raw_data.len());
|
let mut reduced = Vec::with_capacity(png.raw_data.len());
|
||||||
let byte_depth = png.ihdr_data.bit_depth.as_u8() >> 3;
|
let byte_depth = png.ihdr_data.bit_depth.as_u8() >> 3;
|
||||||
let bpp: usize = 4 * byte_depth as usize;
|
let bpp: usize = 4 * byte_depth as usize;
|
||||||
|
let colored_bytes = bpp - byte_depth as usize;
|
||||||
for line in png.scan_lines() {
|
for line in png.scan_lines() {
|
||||||
reduced.push(line.filter);
|
reduced.push(line.filter);
|
||||||
for (i, byte) in line.data.iter().enumerate() {
|
for (i, byte) in line.data.iter().enumerate() {
|
||||||
if i % bpp >= (bpp - byte_depth as usize) {
|
if i % bpp >= colored_bytes {
|
||||||
if *byte != 255 {
|
if *byte != 255 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
@ -1059,13 +1056,14 @@ fn reduce_rgba_to_grayscale_alpha(png: &PngData) -> Option<Vec<u8>> {
|
||||||
let mut reduced = Vec::with_capacity(png.raw_data.len());
|
let mut reduced = Vec::with_capacity(png.raw_data.len());
|
||||||
let byte_depth = png.ihdr_data.bit_depth.as_u8() >> 3;
|
let byte_depth = png.ihdr_data.bit_depth.as_u8() >> 3;
|
||||||
let bpp: usize = 4 * byte_depth as usize;
|
let bpp: usize = 4 * byte_depth as usize;
|
||||||
|
let colored_bytes = bpp - byte_depth as usize;
|
||||||
for line in png.scan_lines() {
|
for line in png.scan_lines() {
|
||||||
reduced.push(line.filter);
|
reduced.push(line.filter);
|
||||||
let mut low_bytes = Vec::with_capacity(4);
|
let mut low_bytes = Vec::with_capacity(4);
|
||||||
let mut high_bytes = Vec::with_capacity(4);
|
let mut high_bytes = Vec::with_capacity(4);
|
||||||
let mut trans_bytes = Vec::with_capacity(byte_depth as usize);
|
let mut trans_bytes = Vec::with_capacity(byte_depth as usize);
|
||||||
for (i, byte) in line.data.iter().enumerate() {
|
for (i, byte) in line.data.iter().enumerate() {
|
||||||
if i % bpp < (bpp - byte_depth as usize) {
|
if i % bpp < colored_bytes {
|
||||||
if byte_depth == 1 || i % 2 == 1 {
|
if byte_depth == 1 || i % 2 == 1 {
|
||||||
low_bytes.push(*byte);
|
low_bytes.push(*byte);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1190,6 +1188,7 @@ fn reduce_grayscale_to_palette(png: &PngData) -> Option<(Vec<u8>, Vec<u8>)> {
|
||||||
// Only perform reduction if we can get to 4-bits or less
|
// Only perform reduction if we can get to 4-bits or less
|
||||||
let mut palette = Vec::with_capacity(16);
|
let mut palette = Vec::with_capacity(16);
|
||||||
let bpp: usize = png.ihdr_data.bit_depth.as_u8() as usize;
|
let bpp: usize = png.ihdr_data.bit_depth.as_u8() as usize;
|
||||||
|
let bpp_inverse = 8 - bpp;
|
||||||
for line in png.scan_lines() {
|
for line in png.scan_lines() {
|
||||||
reduced.extend(BitVec::from_bytes(&[line.filter]));
|
reduced.extend(BitVec::from_bytes(&[line.filter]));
|
||||||
let bit_vec = BitVec::from_bytes(&line.data);
|
let bit_vec = BitVec::from_bytes(&line.data);
|
||||||
|
|
@ -1197,11 +1196,11 @@ fn reduce_grayscale_to_palette(png: &PngData) -> Option<(Vec<u8>, Vec<u8>)> {
|
||||||
for (i, bit) in bit_vec.iter().enumerate() {
|
for (i, bit) in bit_vec.iter().enumerate() {
|
||||||
cur_pixel.push(bit);
|
cur_pixel.push(bit);
|
||||||
if i % bpp == bpp - 1 {
|
if i % bpp == bpp - 1 {
|
||||||
let pix_value = cur_pixel.to_bytes()[0] >> (8 - bpp);
|
let pix_value = cur_pixel.to_bytes()[0] >> bpp_inverse;
|
||||||
let pix_slice = vec![pix_value, pix_value, pix_value];
|
let pix_slice = vec![pix_value, pix_value, pix_value];
|
||||||
if palette.contains(&pix_slice) {
|
if palette.contains(&pix_slice) {
|
||||||
let index = palette.iter().enumerate().find(|&x| x.1 == &pix_slice).unwrap().0;
|
let index = palette.iter().enumerate().find(|&x| x.1 == &pix_slice).unwrap().0;
|
||||||
let idx = BitVec::from_bytes(&[(index as u8) << (8 - bpp)]);
|
let idx = BitVec::from_bytes(&[(index as u8) << bpp_inverse]);
|
||||||
for b in idx.iter().take(bpp) {
|
for b in idx.iter().take(bpp) {
|
||||||
reduced.push(b);
|
reduced.push(b);
|
||||||
}
|
}
|
||||||
|
|
@ -1211,7 +1210,7 @@ fn reduce_grayscale_to_palette(png: &PngData) -> Option<(Vec<u8>, Vec<u8>)> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
palette.push(pix_slice.clone());
|
palette.push(pix_slice.clone());
|
||||||
let idx = BitVec::from_bytes(&[(len as u8) << (8 - bpp)]);
|
let idx = BitVec::from_bytes(&[(len as u8) << bpp_inverse]);
|
||||||
for b in idx.iter().take(bpp) {
|
for b in idx.iter().take(bpp) {
|
||||||
reduced.push(b);
|
reduced.push(b);
|
||||||
}
|
}
|
||||||
|
|
@ -1252,6 +1251,7 @@ fn reduce_palette_to_grayscale(png: &PngData) -> Option<Vec<u8>> {
|
||||||
|
|
||||||
// Iterate through scanlines and assign grayscale value to each pixel
|
// Iterate through scanlines and assign grayscale value to each pixel
|
||||||
let bit_depth: usize = png.ihdr_data.bit_depth.as_u8() as usize;
|
let bit_depth: usize = png.ihdr_data.bit_depth.as_u8() as usize;
|
||||||
|
let bit_depth_inverse = 8 - bit_depth;
|
||||||
for line in png.scan_lines() {
|
for line in png.scan_lines() {
|
||||||
reduced.extend(BitVec::from_bytes(&[line.filter]));
|
reduced.extend(BitVec::from_bytes(&[line.filter]));
|
||||||
let bit_vec = BitVec::from_bytes(&line.data);
|
let bit_vec = BitVec::from_bytes(&line.data);
|
||||||
|
|
@ -1262,7 +1262,7 @@ fn reduce_palette_to_grayscale(png: &PngData) -> Option<Vec<u8>> {
|
||||||
cur_pixel.push(bit);
|
cur_pixel.push(bit);
|
||||||
if cur_pixel.len() == bit_depth {
|
if cur_pixel.len() == bit_depth {
|
||||||
// `to_bytes` gives us e.g. 10000000 for a 1-bit pixel, when we would want 00000001
|
// `to_bytes` gives us e.g. 10000000 for a 1-bit pixel, when we would want 00000001
|
||||||
let padded_pixel = cur_pixel.to_bytes()[0] >> (8 - bit_depth);
|
let padded_pixel = cur_pixel.to_bytes()[0] >> bit_depth_inverse;
|
||||||
let palette_idx: usize = padded_pixel as usize * 3;
|
let palette_idx: usize = padded_pixel as usize * 3;
|
||||||
reduced.extend(BitVec::from_bytes(&[palette[palette_idx]]));
|
reduced.extend(BitVec::from_bytes(&[palette[palette_idx]]));
|
||||||
// BitVec's clear function doesn't set len to 0
|
// BitVec's clear function doesn't set len to 0
|
||||||
|
|
@ -1325,10 +1325,11 @@ fn reduce_grayscale_alpha_to_grayscale(png: &PngData) -> Option<Vec<u8>> {
|
||||||
let mut reduced = Vec::with_capacity(png.raw_data.len());
|
let mut reduced = Vec::with_capacity(png.raw_data.len());
|
||||||
let byte_depth = png.ihdr_data.bit_depth.as_u8() >> 3;
|
let byte_depth = png.ihdr_data.bit_depth.as_u8() >> 3;
|
||||||
let bpp: usize = 2 * byte_depth as usize;
|
let bpp: usize = 2 * byte_depth as usize;
|
||||||
|
let colored_bytes = bpp - byte_depth as usize;
|
||||||
for line in png.scan_lines() {
|
for line in png.scan_lines() {
|
||||||
reduced.push(line.filter);
|
reduced.push(line.filter);
|
||||||
for (i, byte) in line.data.iter().enumerate() {
|
for (i, byte) in line.data.iter().enumerate() {
|
||||||
if i % bpp >= (bpp - byte_depth as usize) {
|
if i % bpp >= colored_bytes {
|
||||||
if *byte != 255 {
|
if *byte != 255 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue