Code cleanup
This commit is contained in:
parent
f7dd2f0323
commit
ec65bf7676
2 changed files with 139 additions and 128 deletions
|
|
@ -258,9 +258,7 @@ fn reductions_palette_full_reduction(b: &mut Bencher) {
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn reductions_alpha_black(b: &mut Bencher) {
|
fn reductions_alpha_black(b: &mut Bencher) {
|
||||||
let input = test::black_box(PathBuf::from(
|
let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha_black.png"));
|
||||||
"tests/files/rgba_8_reduce_alpha_black.png",
|
|
||||||
));
|
|
||||||
let png = png::PngData::new(&input, false).unwrap();
|
let png = png::PngData::new(&input, false).unwrap();
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
|
@ -271,9 +269,7 @@ fn reductions_alpha_black(b: &mut Bencher) {
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn reductions_alpha_white(b: &mut Bencher) {
|
fn reductions_alpha_white(b: &mut Bencher) {
|
||||||
let input = test::black_box(PathBuf::from(
|
let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha_white.png"));
|
||||||
"tests/files/rgba_8_reduce_alpha_white.png",
|
|
||||||
));
|
|
||||||
let png = png::PngData::new(&input, false).unwrap();
|
let png = png::PngData::new(&input, false).unwrap();
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
|
@ -284,9 +280,7 @@ fn reductions_alpha_white(b: &mut Bencher) {
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn reductions_alpha_left(b: &mut Bencher) {
|
fn reductions_alpha_left(b: &mut Bencher) {
|
||||||
let input = test::black_box(PathBuf::from(
|
let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha_left.png"));
|
||||||
"tests/files/rgba_8_reduce_alpha_left.png",
|
|
||||||
));
|
|
||||||
let png = png::PngData::new(&input, false).unwrap();
|
let png = png::PngData::new(&input, false).unwrap();
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
|
@ -297,9 +291,7 @@ fn reductions_alpha_left(b: &mut Bencher) {
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn reductions_alpha_right(b: &mut Bencher) {
|
fn reductions_alpha_right(b: &mut Bencher) {
|
||||||
let input = test::black_box(PathBuf::from(
|
let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha_right.png"));
|
||||||
"tests/files/rgba_8_reduce_alpha_right.png",
|
|
||||||
));
|
|
||||||
let png = png::PngData::new(&input, false).unwrap();
|
let png = png::PngData::new(&input, false).unwrap();
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
|
@ -310,9 +302,7 @@ fn reductions_alpha_right(b: &mut Bencher) {
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn reductions_alpha_up(b: &mut Bencher) {
|
fn reductions_alpha_up(b: &mut Bencher) {
|
||||||
let input = test::black_box(PathBuf::from(
|
let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha_up.png"));
|
||||||
"tests/files/rgba_8_reduce_alpha_up.png",
|
|
||||||
));
|
|
||||||
let png = png::PngData::new(&input, false).unwrap();
|
let png = png::PngData::new(&input, false).unwrap();
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
|
@ -323,9 +313,7 @@ fn reductions_alpha_up(b: &mut Bencher) {
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn reductions_alpha_down(b: &mut Bencher) {
|
fn reductions_alpha_down(b: &mut Bencher) {
|
||||||
let input = test::black_box(PathBuf::from(
|
let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha_down.png"));
|
||||||
"tests/files/rgba_8_reduce_alpha_down.png",
|
|
||||||
));
|
|
||||||
let png = png::PngData::new(&input, false).unwrap();
|
let png = png::PngData::new(&input, false).unwrap();
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
|
|
||||||
243
src/png.rs
243
src/png.rs
|
|
@ -774,143 +774,167 @@ impl PngData {
|
||||||
|
|
||||||
pub fn reduce_alpha_channel(&mut self, optim: AlphaOptim) -> bool {
|
pub fn reduce_alpha_channel(&mut self, optim: AlphaOptim) -> bool {
|
||||||
let (bpc, bpp) = match self.ihdr_data.color_type {
|
let (bpc, bpp) = match self.ihdr_data.color_type {
|
||||||
ColorType::RGBA => {
|
ColorType::RGBA |
|
||||||
match self.ihdr_data.bit_depth {
|
|
||||||
BitDepth::Sixteen => (2, 8),
|
|
||||||
BitDepth::Eight => (1, 4),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ColorType::GrayscaleAlpha => {
|
ColorType::GrayscaleAlpha => {
|
||||||
match self.ihdr_data.bit_depth {
|
let cpp = self.channels_per_pixel();
|
||||||
BitDepth::Sixteen => (2, 4),
|
let bpc = self.ihdr_data.bit_depth.as_u8() / 8;
|
||||||
BitDepth::Eight => (1, 2),
|
(bpc as usize, (bpc * cpp) as usize)
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut reduced = Vec::with_capacity(self.raw_data.len());
|
|
||||||
|
|
||||||
match optim {
|
match optim {
|
||||||
AlphaOptim::NoOp => {
|
AlphaOptim::NoOp => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AlphaOptim::Black => {
|
AlphaOptim::Black => {
|
||||||
for line in self.scan_lines() {
|
self.raw_data = self.reduce_alpha_to_black(bpc, bpp);
|
||||||
reduced.push(line.filter);
|
|
||||||
for pixel in line.data.chunks(bpp) {
|
|
||||||
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
|
||||||
for _ in 0..bpp {
|
|
||||||
reduced.push(0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reduced.extend_from_slice(pixel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
AlphaOptim::White => {
|
AlphaOptim::White => {
|
||||||
for line in self.scan_lines() {
|
self.raw_data = self.reduce_alpha_to_white(bpc, bpp);
|
||||||
reduced.push(line.filter);
|
|
||||||
for pixel in line.data.chunks(bpp) {
|
|
||||||
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
|
||||||
for _ in 0..(bpp - bpc) {
|
|
||||||
reduced.push(255);
|
|
||||||
}
|
|
||||||
for _ in 0..bpc {
|
|
||||||
reduced.push(0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reduced.extend_from_slice(pixel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
AlphaOptim::Up => {
|
AlphaOptim::Up => {
|
||||||
let mut lines = Vec::new();
|
self.raw_data = self.reduce_alpha_to_up(bpc, bpp);
|
||||||
let scan_lines = self.scan_lines().collect::<Vec<ScanLine>>();
|
|
||||||
let mut last_line = vec![0; scan_lines[0].data.len()];
|
|
||||||
let mut current_line = Vec::with_capacity(last_line.len());
|
|
||||||
for line in scan_lines.into_iter().rev() {
|
|
||||||
current_line.push(line.filter);
|
|
||||||
for (pixel, last_pixel) in line.data.chunks(bpp).zip(last_line.chunks(bpp)) {
|
|
||||||
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
|
||||||
current_line.extend_from_slice(&last_pixel[0..(bpp - bpc)]);
|
|
||||||
for _ in 0..bpc {
|
|
||||||
current_line.push(0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
current_line.extend_from_slice(pixel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
last_line = current_line.clone();
|
|
||||||
lines.push(current_line.clone());
|
|
||||||
current_line.clear();
|
|
||||||
}
|
|
||||||
reduced.extend(lines.into_iter().rev().flatten());
|
|
||||||
}
|
}
|
||||||
AlphaOptim::Down => {
|
AlphaOptim::Down => {
|
||||||
let mut last_line = vec![0; self.scan_lines().next().unwrap().data.len()];
|
self.raw_data = self.reduce_alpha_to_down(bpc, bpp);
|
||||||
for line in self.scan_lines() {
|
|
||||||
reduced.push(line.filter);
|
|
||||||
for (pixel, last_pixel) in line.data.chunks(bpp).zip(last_line.chunks(bpp)) {
|
|
||||||
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
|
||||||
reduced.extend_from_slice(&last_pixel[0..(bpp - bpc)]);
|
|
||||||
for _ in 0..bpc {
|
|
||||||
reduced.push(0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reduced.extend_from_slice(pixel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
last_line = reduced.clone();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
AlphaOptim::Left => {
|
AlphaOptim::Left => {
|
||||||
for line in self.scan_lines() {
|
self.raw_data = self.reduce_alpha_to_left(bpc, bpp);
|
||||||
let mut line_bytes = Vec::with_capacity(line.data.len());
|
|
||||||
let mut last_pixel = vec![0; bpp];
|
|
||||||
for pixel in line.data.chunks(bpp).rev() {
|
|
||||||
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
|
||||||
line_bytes.extend_from_slice(&last_pixel[0..(bpp - bpc)]);
|
|
||||||
for _ in 0..bpc {
|
|
||||||
line_bytes.push(0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
line_bytes.extend_from_slice(pixel);
|
|
||||||
}
|
|
||||||
last_pixel = pixel.to_owned();
|
|
||||||
}
|
|
||||||
reduced.push(line.filter);
|
|
||||||
reduced.extend(line_bytes.chunks(bpp).rev().flatten());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
AlphaOptim::Right => {
|
AlphaOptim::Right => {
|
||||||
for line in self.scan_lines() {
|
self.raw_data = self.reduce_alpha_to_right(bpc, bpp);
|
||||||
reduced.push(line.filter);
|
|
||||||
let mut last_pixel = vec![0; bpp];
|
|
||||||
for pixel in line.data.chunks(bpp) {
|
|
||||||
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
|
||||||
reduced.extend_from_slice(&last_pixel[0..(bpp - bpc)]);
|
|
||||||
for _ in 0..bpc {
|
|
||||||
reduced.push(0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reduced.extend_from_slice(pixel);
|
|
||||||
}
|
|
||||||
last_pixel = pixel.to_owned();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.raw_data = reduced;
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reduce_alpha_to_black(&self, bpc: usize, bpp: usize) -> Vec<u8> {
|
||||||
|
let mut reduced = Vec::with_capacity(self.raw_data.len());
|
||||||
|
for line in self.scan_lines() {
|
||||||
|
reduced.push(line.filter);
|
||||||
|
for pixel in line.data.chunks(bpp) {
|
||||||
|
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
||||||
|
for _ in 0..bpp {
|
||||||
|
reduced.push(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reduced.extend_from_slice(pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reduced
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reduce_alpha_to_white(&self, bpc: usize, bpp: usize) -> Vec<u8> {
|
||||||
|
let mut reduced = Vec::with_capacity(self.raw_data.len());
|
||||||
|
for line in self.scan_lines() {
|
||||||
|
reduced.push(line.filter);
|
||||||
|
for pixel in line.data.chunks(bpp) {
|
||||||
|
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
||||||
|
for _ in 0..(bpp - bpc) {
|
||||||
|
reduced.push(255);
|
||||||
|
}
|
||||||
|
for _ in 0..bpc {
|
||||||
|
reduced.push(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reduced.extend_from_slice(pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reduced
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reduce_alpha_to_up(&self, bpc: usize, bpp: usize) -> Vec<u8> {
|
||||||
|
let mut lines = Vec::new();
|
||||||
|
let scan_lines = self.scan_lines().collect::<Vec<ScanLine>>();
|
||||||
|
let mut last_line = vec![0; scan_lines[0].data.len()];
|
||||||
|
let mut current_line = Vec::with_capacity(last_line.len());
|
||||||
|
for line in scan_lines.into_iter().rev() {
|
||||||
|
current_line.push(line.filter);
|
||||||
|
for (pixel, last_pixel) in line.data.chunks(bpp).zip(last_line.chunks(bpp)) {
|
||||||
|
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
||||||
|
current_line.extend_from_slice(&last_pixel[0..(bpp - bpc)]);
|
||||||
|
for _ in 0..bpc {
|
||||||
|
current_line.push(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
current_line.extend_from_slice(pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last_line = current_line.clone();
|
||||||
|
lines.push(current_line.clone());
|
||||||
|
current_line.clear();
|
||||||
|
}
|
||||||
|
lines.into_iter().rev().flatten().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reduce_alpha_to_down(&self, bpc: usize, bpp: usize) -> Vec<u8> {
|
||||||
|
let mut reduced = Vec::with_capacity(self.raw_data.len());
|
||||||
|
let mut last_line = vec![0; self.scan_lines().next().unwrap().data.len()];
|
||||||
|
for line in self.scan_lines() {
|
||||||
|
reduced.push(line.filter);
|
||||||
|
for (pixel, last_pixel) in line.data.chunks(bpp).zip(last_line.chunks(bpp)) {
|
||||||
|
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
||||||
|
reduced.extend_from_slice(&last_pixel[0..(bpp - bpc)]);
|
||||||
|
for _ in 0..bpc {
|
||||||
|
reduced.push(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reduced.extend_from_slice(pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last_line = reduced.clone();
|
||||||
|
}
|
||||||
|
reduced
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reduce_alpha_to_left(&self, bpc: usize, bpp: usize) -> Vec<u8> {
|
||||||
|
let mut reduced = Vec::with_capacity(self.raw_data.len());
|
||||||
|
for line in self.scan_lines() {
|
||||||
|
let mut line_bytes = Vec::with_capacity(line.data.len());
|
||||||
|
let mut last_pixel = vec![0; bpp];
|
||||||
|
for pixel in line.data.chunks(bpp).rev() {
|
||||||
|
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
||||||
|
line_bytes.extend_from_slice(&last_pixel[0..(bpp - bpc)]);
|
||||||
|
for _ in 0..bpc {
|
||||||
|
line_bytes.push(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
line_bytes.extend_from_slice(pixel);
|
||||||
|
}
|
||||||
|
last_pixel = pixel.to_owned();
|
||||||
|
}
|
||||||
|
reduced.push(line.filter);
|
||||||
|
reduced.extend(line_bytes.chunks(bpp).rev().flatten());
|
||||||
|
}
|
||||||
|
reduced
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reduce_alpha_to_right(&self, bpc: usize, bpp: usize) -> Vec<u8> {
|
||||||
|
let mut reduced = Vec::with_capacity(self.raw_data.len());
|
||||||
|
for line in self.scan_lines() {
|
||||||
|
reduced.push(line.filter);
|
||||||
|
let mut last_pixel = vec![0; bpp];
|
||||||
|
for pixel in line.data.chunks(bpp) {
|
||||||
|
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
||||||
|
reduced.extend_from_slice(&last_pixel[0..(bpp - bpc)]);
|
||||||
|
for _ in 0..bpc {
|
||||||
|
reduced.push(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reduced.extend_from_slice(pixel);
|
||||||
|
}
|
||||||
|
last_pixel = pixel.to_owned();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reduced
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert the image to the specified interlacing type
|
/// Convert the image to the specified interlacing type
|
||||||
/// Returns true if the interlacing was changed, false otherwise
|
/// Returns true if the interlacing was changed, false otherwise
|
||||||
/// The `interlace` parameter specifies the *new* interlacing mode
|
/// The `interlace` parameter specifies the *new* interlacing mode
|
||||||
|
|
@ -932,7 +956,6 @@ impl PngData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_png_block(key: &[u8], header: &[u8], output: &mut Vec<u8>) {
|
fn write_png_block(key: &[u8], header: &[u8], output: &mut Vec<u8>) {
|
||||||
let mut header_data = Vec::with_capacity(header.len() + 4);
|
let mut header_data = Vec::with_capacity(header.len() + 4);
|
||||||
header_data.extend_from_slice(key);
|
header_data.extend_from_slice(key);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue