Skip to content

Commit

Permalink
inflate/png: Add trns filtering
Browse files Browse the repository at this point in the history
Signed-off-by: caleb <[email protected]>
  • Loading branch information
etemesi254 committed Dec 23, 2022
1 parent 6fbcc43 commit 558bf07
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 28 deletions.
32 changes: 10 additions & 22 deletions zune-png/src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ impl<'a> PngDecoder<'a>
{
self.parse_idat(header)?;
}
PngChunkType::tRNS =>
{
self.parse_trns(header)?;
}

PngChunkType::IEND =>
{
Expand Down Expand Up @@ -255,25 +259,10 @@ impl<'a> PngDecoder<'a>
// runs.
//

// {
// use std::fs::OpenOptions;
// use std::io::Write;
// let mut file = OpenOptions::new()
// .write(true)
// .create(true)
// .truncate(true)
// .open("/home/caleb/Documents/zune-image/zune-inflate/tests/zlib/412845_PNG.zlib")
// .unwrap();
//
// file.write_all(&self.idat_chunks).unwrap();
// }
let mut decoder = zune_inflate::DeflateDecoder::new(&self.idat_chunks);

let deflate_data = decoder.decode_zlib().unwrap();

// let deflate_data = _decode_writer_flate(&self.idat_chunks);
// assert_eq!(deflate_data_x, deflate_data);

let info = &self.png_info;

let mut img_width_bytes;
Expand Down Expand Up @@ -407,9 +396,7 @@ impl<'a> PngDecoder<'a>
// This is the loop filter,
// the only trick we have is how we do get the top row
//
// We do it in the following way
// 1. Iterate one stride below, chunk taking 2x width
//
// Complicated filters are handled in filters.rs

let mut prev_row_start = 0;
let width_stride = chunk_size - 1;
Expand All @@ -427,6 +414,7 @@ impl<'a> PngDecoder<'a>
out_position += width_stride;
// take filter
let filter_byte = in_stride[0];
let raw = &in_stride[1..];
// get it's type
let filter = FilterMethod::from_int(filter_byte)
.ok_or_else(|| PngErrors::Generic(format!("Unknown filter {filter_byte}")))?;
Expand All @@ -438,19 +426,19 @@ impl<'a> PngDecoder<'a>
FilterMethod::None =>
{
// memcpy
current[0..width_stride].copy_from_slice(&in_stride[1..]);
current[0..width_stride].copy_from_slice(raw);
}
FilterMethod::Average =>
{
handle_avg(prev_row, &in_stride[1..], current, components);
handle_avg(prev_row, raw, current, components);
}
FilterMethod::Sub =>
{
handle_sub(&in_stride[1..], current, components);
handle_sub(raw, current, components);
}
FilterMethod::Up =>
{
for ((filt, recon), up) in in_stride[1..].iter().zip(current).zip(prev_row)
for ((filt, recon), up) in raw.iter().zip(current).zip(prev_row)
{
*recon = (*filt).wrapping_add(*up)
}
Expand Down
47 changes: 42 additions & 5 deletions zune-png/src/headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl<'a> PngDecoder<'a>
}
else
{
return Err(PngErrors::Generic(format!("Unknown color value {}", color)));
return Err(PngErrors::Generic(format!("Unknown color value {color}")));
}
self.png_info.component = self.png_info.color.num_components();
// verify colors plus bit depths
Expand Down Expand Up @@ -104,8 +104,7 @@ impl<'a> PngDecoder<'a>
else
{
return Err(PngErrors::Generic(format!(
"Unknown filter method {}",
filter_method
"Unknown filter method {filter_method}"
)));
}

Expand All @@ -118,8 +117,7 @@ impl<'a> PngDecoder<'a>
else
{
return Err(PngErrors::Generic(format!(
"Unknown interlace method {}",
interlace_method
"Unknown interlace method {interlace_method}",
)));
}

Expand Down Expand Up @@ -181,4 +179,43 @@ impl<'a> PngDecoder<'a>

Ok(())
}

pub(crate) fn parse_trns(&mut self, chunk: PngChunk) -> Result<(), PngErrors>
{
match self.png_info.color
{
PngColor::Luma =>
{
let _grey_sample = self.stream.get_u16_be();
}
PngColor::RGB =>
{
let _red_sample = self.stream.get_u16_be();
let _blue_sample = self.stream.get_u16_be();
let _green_sample = self.stream.get_u16_be();
}
PngColor::Palette =>
{
if self.palette.is_empty()
{
return Err(PngErrors::GenericStatic("tRNS chunk before plTE"));
}
if self.palette.len() <= chunk.length * 4
{
return Err(PngErrors::GenericStatic("tRNS chunk with too long entries"));
}
for i in 0..chunk.length
{
self.palette[i * 4 + 3] = self.stream.get_u8();
}
}
_ =>
{
let msg = format!("A tRNS chunk shall not appear for colour type {:?} as it is already transparent", self.png_info.color);

return Err(PngErrors::Generic(msg));
}
}
Ok(())
}
}
12 changes: 11 additions & 1 deletion zune-png/tests/test_filters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn decode_ref(data: &[u8]) -> Vec<u8>

fn decode_zune(data: &[u8]) -> Vec<u8>
{
zune_png::PngDecoder::new(&data)
zune_png::PngDecoder::new(data)
.decode()
.unwrap()
.u8()
Expand Down Expand Up @@ -111,3 +111,13 @@ fn test_paeth()
test_decoding(path);
}
}

#[test]
fn test_black_and_white()
{
{
let path = env!("CARGO_MANIFEST_DIR").to_string() + "/tests/png_suite/basi0g01.png";

test_decoding(path);
}
}

0 comments on commit 558bf07

Please sign in to comment.