-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New PNG inputs for benchmarking non-compressed, non-filtered data.
- Loading branch information
1 parent
f10238a
commit e70e93c
Showing
6 changed files
with
142 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,24 @@ | ||
Copyrights: | ||
|
||
Lohengrin_-_Illustrated_Sporting_and_Dramatic_News.png: Public Domain, according to Wikimedia | ||
kodim*.png: Eastman Kodak Company, released for unrestricted use | ||
Transparency.png: Public Domain, according to Wikimedia | ||
* `Lohengrin_-_Illustrated_Sporting_and_Dramatic_News.png`: Public Domain, according to Wikimedia | ||
* `kodim*.png`: Eastman Kodak Company, released for unrestricted use | ||
* `Transparency.png`: Public Domain, according to Wikimedia | ||
* `8x8-noncompressed.png` and `128x128-noncompressed.png`: Created using the | ||
ad-hoc tool that can be found in the `noncompressed` folder. | ||
|
||
The images use different filtering: | ||
Lohengrin: no filtering | ||
kodim02: mixed | ||
kodim07: mainly paeth | ||
kodim17: mainly sub | ||
kodim23: mixed | ||
|
||
* Lohengrin: no filtering | ||
* kodim02: mixed | ||
* kodim07: mainly paeth | ||
* kodim17: mainly sub | ||
* kodim23: mixed | ||
|
||
The `noncompressed` images use no filtering, and `00` compression mode (i.e. | ||
`BTYPE` = `00` = no compression; see | ||
https://datatracker.ietf.org/doc/html/rfc1951#section-3.2.3 for more details). | ||
These images are somewhat artificial, but may be useful for benchmarking | ||
performance of parts outside of `fdeflate` crate and/or the `unfilter` function | ||
(e.g. these images were originally used to evaluate changes to minimize copying | ||
of image pixels between various buffers - see [this discussion](TODO) for more | ||
details). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[package] | ||
name = "pnggen" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
adler32 = "1.2.0" | ||
byteorder = "1.5.0" | ||
crc32fast = "1.3.2" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
use byteorder::WriteBytesExt; | ||
use std::fs::File; | ||
use std::io::Write; | ||
|
||
fn write_png_sig(w: &mut impl Write) { | ||
const SIG: [u8; 8] = [137, 80, 78, 71, 13, 10, 26, 10]; | ||
w.write_all(&SIG).unwrap(); | ||
} | ||
|
||
fn write_chunk(w: &mut impl Write, chunk_type: &[u8], data: &[u8]) { | ||
let crc = { | ||
let input = chunk_type | ||
.iter() | ||
.copied() | ||
.chain(data.iter().copied()) | ||
.collect::<Vec<_>>(); | ||
crc32fast::hash(input.as_slice()) | ||
}; | ||
w.write_u32::<byteorder::BigEndian>(data.len() as u32) | ||
.unwrap(); | ||
w.write_all(chunk_type).unwrap(); | ||
w.write_all(data).unwrap(); | ||
w.write_u32::<byteorder::BigEndian>(crc).unwrap(); | ||
} | ||
|
||
fn write_ihdr(w: &mut impl Write, width: u32) { | ||
let mut data = Vec::new(); | ||
data.write_u32::<byteorder::BigEndian>(width).unwrap(); | ||
data.write_u32::<byteorder::BigEndian>(width).unwrap(); // height | ||
data.write_u8(8).unwrap(); // bit depth = always 8-bits per channel | ||
data.write_u8(6).unwrap(); // color type = color + alpha | ||
data.write_u8(0).unwrap(); // compression method (0 is the only allowed value) | ||
data.write_u8(0).unwrap(); // filter method (0 is the only allowed value) | ||
data.write_u8(0).unwrap(); // interlace method = no interlacing | ||
// | ||
write_chunk(w, b"IHDR", &data); | ||
} | ||
|
||
fn write_noncompressed_deflate_block(w: &mut impl Write, data: &[u8], last: bool) { | ||
if last { | ||
w.write_u8(1).unwrap(); | ||
} else { | ||
w.write_u8(0).unwrap(); | ||
} | ||
|
||
assert!(data.len() < 65535); | ||
let len = data.len() as u16; | ||
w.write_u16::<byteorder::LittleEndian>(len).unwrap(); | ||
w.write_u16::<byteorder::LittleEndian>(!len).unwrap(); | ||
|
||
w.write_all(data).unwrap(); | ||
} | ||
|
||
fn write_idat(w: &mut impl Write, width: u32) { | ||
// Generate arbitrary test pixels. | ||
let image_pixels = { | ||
let mut row = Vec::new(); | ||
row.write_u8(0).unwrap(); // filter = no filter | ||
|
||
let row_pixels = (0..width) | ||
.map(|i| { | ||
let color: u8 = (i * 255 / width) as u8; | ||
let alpha: u8 = 0xff; | ||
[color, 255 - color, color / 2, alpha] | ||
}) | ||
.flatten(); | ||
row.extend(row_pixels); | ||
|
||
std::iter::repeat(row) | ||
.take(width as usize) | ||
.flatten() | ||
.collect::<Vec<_>>() | ||
}; | ||
|
||
let mut zlib_data = Vec::new(); | ||
zlib_data.write_u8(0x78).unwrap(); // CM + CINFO | ||
zlib_data.write_u8(0x01).unwrap(); // FLG | ||
|
||
let mut chunks = image_pixels.as_slice().chunks_exact(8192); | ||
while let Some(chunk) = chunks.next() { | ||
write_noncompressed_deflate_block(&mut zlib_data, chunk, false); | ||
} | ||
write_noncompressed_deflate_block(&mut zlib_data, chunks.remainder(), true); | ||
|
||
let adler = adler32::adler32(image_pixels.as_slice()).unwrap(); | ||
zlib_data.write_u32::<byteorder::BigEndian>(adler).unwrap(); | ||
|
||
write_chunk(w, b"IDAT", &zlib_data); | ||
} | ||
|
||
fn write_iend(w: &mut impl Write) { | ||
write_chunk(w, b"IEND", &[]); | ||
} | ||
|
||
fn write_png_file(w: &mut impl Write, width: u32) { | ||
write_png_sig(w); | ||
write_ihdr(w, width); | ||
write_idat(w, width); | ||
write_iend(w); | ||
} | ||
|
||
fn main() { | ||
let mut f = File::create("8x8-noncompressed.png").unwrap(); | ||
write_png_file(&mut f, 8); | ||
|
||
let mut f = File::create("128x128-noncompressed.png").unwrap(); | ||
write_png_file(&mut f, 128); | ||
} |