PNG initial code

png-branch
an 2019-03-18 08:24:20 -04:00
parent 422a7989f5
commit 92eeecd0a6
342 changed files with 5763 additions and 5 deletions

10
LICENSE
View File

@ -1,6 +1,10 @@
Some of the data contained in tests/data and benches/data is
Copyright © Bungie Software. I do not own them, but am permitted to
redistribute them. Everything else is:
Some of the data contained in tests/data is Copyright © Bungie Software. I do
not own them, but am permitted to redistribute them. PngSuite is included in
the test suite as well, its license is under tests/data/png/LICENSE. Everything
else, including all source code is licensed as Public Domain as stated below.
All program sources are licensed as such, are fully original, and may be used
freely. If you wish to contribute to the project you MUST explicitly accept the
terms and conditions and put your code as well under this license.
To the extent possible under law, I, Alison Sanderson, have waived all
copyright and related or neighboring rights to this Document as described by

View File

@ -38,7 +38,7 @@ macro_rules! c_enum
$(#[$outer:meta])*
$vi:vis enum $t:ident: $ti:ty
{
$($(#[$inner:meta])* $va:expr => $en:ident,)+
$($va:expr => $en:ident,)+
}
) => {
$(#[$outer])*
@ -48,16 +48,25 @@ macro_rules! c_enum
$($en,)+
}
#[allow(dead_code)]
impl $t
{
/// Returns, if representable, the variant of `Self` from `n`.
$vi fn from_repr(n: $ti) -> Result<Self, ReprError>
{
match n {
$($(#[$inner])* $va => Ok($t::$en),)+
$($va => Ok($t::$en),)+
n => Err(ReprError::new(n))
}
}
/// Returns the representation of this type.
$vi fn to_repr(self) -> $ti
{
match self {
$($t::$en => $va,)+
}
}
}
};
}

View File

@ -5,6 +5,7 @@ pub mod machdr;
pub mod map;
pub mod phy;
pub mod pict;
pub mod png;
pub mod ppm;
pub mod shp;
pub mod snd;

334
source/marathon/png.rs Normal file
View File

@ -0,0 +1,334 @@
//! Portable Network Graphics loader.
use crate::{durandal::{bin::*, cksum, err::*, image},
marathon::defl};
pub fn load_png(b: &[u8]) -> ResultS<image::Image16>
{
read_data! {
8, BE in b =>
magic = u8[0..8] slice;
}
if magic != b"\x89PNG\r\n\x1A\n" {
bail!("invalid magic number");
}
let mut p = 8;
// header chunk always comes first
let (len, cnk) = load_chunk(&b[p..])?;
p += len;
if cnk.typ != b"IHDR" {
bail!("IHDR not first chunk");
}
let hdr = load_cnk_ihdr(cnk)?;
let mut pal = None;
let mut bmp = Vec::new();
// loop over all the chunks, mainly grabbing IDAT chunks
loop {
let (len, cnk) = load_chunk(&b[p..])?;
p += len;
match &cnk.typ.0 {
b"PLTE" => pal = Some(load_cnk_plte(cnk)?),
b"IDAT" => bmp.extend_from_slice(&cnk.dat),
b"IEND" => break,
_ => {
if !cnk.aux {
bail!("no handler for vital chunk");
}
}
}
}
// inflate the bitmap
let bmp = &bmp[defl::load_zlib_header(&bmp)?..];
let bmp = defl::load_deflate(bmp)?.1;
let im = interlaced_adam7(&hdr, &bmp)?;
dbg!(im);
unimplemented!();
}
pub fn interlaced_adam7(hdr: &Header, i_bmp: &[u8]) -> ResultS<image::Image16>
{
const INCR_X: [usize; 7] = [8, 8, 4, 4, 2, 2, 1];
const INCR_Y: [usize; 7] = [8, 8, 8, 4, 4, 2, 2];
const BEGN_X: [usize; 7] = [0, 4, 0, 2, 0, 1, 0];
const BEGN_Y: [usize; 7] = [0, 0, 4, 0, 2, 0, 1];
let mut im = image::Image16::new_empty(hdr.width, hdr.heigh);
let mut p = 0;
for pass in 0..7 {
let w = hdr.width / INCR_X[pass];
let h = hdr.heigh / INCR_Y[pass];
if w == 0 || h == 0 {
continue;
}
let scanl = std::cmp::max(w * usize::from(hdr.pbits), 8) / 8 + 1;
let pp = p;
p += scanl * h;
let mut last = Vec::new();
let block = ok!(i_bmp.get(pp..p), "not enough data")?;
for y in 0..h {
let beg = y * scanl;
let end = beg + scanl;
let llin = if last.is_empty() {None} else {Some(last.as_slice())};
let line = &block[beg..end];
let line = unfilter_line(hdr, line, llin)?;
last = line;
}
}
Ok(im)
}
pub fn unfilter_line(hdr: &Header, line: &[u8], last: Option<&[u8]>)
-> ResultS<Vec<u8>>
{
let filt = FilterType::from_repr(line[0])?;
let line = &line[1..];
let mut out = line.to_vec();
let pbytes = usize::from(std::cmp::max(hdr.pbits / 8, 1));
match filt {
FilterType::None => {}
FilterType::Sub => {
for x in 0..line.len() {
if x > pbytes {
out[x] = out[x].wrapping_add(out[x - pbytes]);
}
}
}
FilterType::Up => {
if let Some(last) = last {
for x in 0..line.len() {
out[x] = out[x].wrapping_add(last[x]);
}
}
}
FilterType::Average => {
for x in 0..line.len() {
let mut n = 0;
if x > pbytes {
n = out[x - pbytes];
}
if let Some(last) = last {
n = n.wrapping_add(last[x]);
}
out[x] = out[x].wrapping_add(n / 2);
}
}
FilterType::Paeth => {
for x in 0..line.len() {
let u = if x > pbytes {out[x - pbytes]} else {0};
let v = if let Some(last) = last {last[x]} else {0};
let s = if let Some(last) = last {
if x > pbytes {last[x - pbytes]} else {0}
} else {
0
};
out[x] = out[x].wrapping_add(paeth_predictor(u, v, s));
}
}
}
Ok(out)
}
/// The Paeth prediction function.
pub fn paeth_predictor(a: u8, b: u8, c: u8) -> u8
{
let ia = i16::from(a);
let ib = i16::from(b);
let ic = i16::from(c);
let p = ia + ib - ic;
let pa = (p - ia).abs();
let pb = (p - ib).abs();
let pc = (p - ic).abs();
if pa <= pb && pa <= pc {
a
} else if pb <= pc {
b
} else {
c
}
}
pub fn load_chunk(b: &[u8]) -> ResultS<(usize, Chunk)>
{
read_data! {
4, BE in b =>
len = u32[0] usize;
}
read_data! {
len + 12, BE in b =>
typ = Ident[4];
dat = u8[8..8 + len] slice;
crc = u32[8 + len];
}
let computed_crc = cksum::crc32(&typ.0, !0);
let computed_crc = cksum::crc32(dat, !computed_crc);
if crc != computed_crc {
bail!("bad CRC in chunk");
}
let dat = dat.to_vec();
let aux = typ.0[0] & 0x20 != 0;
let cpy = typ.0[3] & 0x20 != 0;
Ok((len + 12, Chunk{typ, dat, aux, cpy}))
}
pub fn load_cnk_ihdr(cnk: Chunk) -> ResultS<Header>
{
read_data! {
13, BE in cnk.dat =>
width = u32[0] usize;
heigh = u32[4] usize;
depth = u8[8];
ctype = u8[9];
compr = u8[10];
filtr = u8[11];
xlace = u8[12];
}
if compr != 0 {bail!("unrecognized compression method");}
if filtr != 0 {bail!("unrecognized filter method");}
if width == 0 {bail!("zero width");}
if heigh == 0 {bail!("zero height");}
let depth = BitDepth::from_repr(depth)?;
let ctype = ColorType::from_repr(ctype)?;
let xlace = XlaceMode::from_repr(xlace)?;
let pbits = depth.to_repr();
let pbits = match ctype {
ColorType::Grayscale => pbits,
ColorType::Truecolor => pbits * 3,
ColorType::Indexed => pbits,
ColorType::GrayscaleAlpha => pbits * 2,
ColorType::TruecolorAlpha => pbits * 4,
};
Ok(Header{width, heigh, pbits, depth, ctype, xlace})
}
pub fn load_cnk_plte(cnk: Chunk) -> ResultS<ColorMap>
{
let mut colors = [image::Color8::new(0, 0, 0); 256];
let mut p = 0;
for col in colors.iter_mut() {
read_data! {
p + 3, BE in cnk.dat =>
r = u8[p];
g = u8[p + 1];
b = u8[p + 2];
}
p += 3;
*col = image::Color8::new(r, g, b);
if p == cnk.dat.len() {
break;
} else if p > cnk.dat.len() {
bail!("bad PLTE length");
}
}
Ok(colors)
}
pub type ColorMap = [image::Color8; 256];
#[derive(Debug)]
pub struct Header
{
width: usize,
heigh: usize,
pbits: u8,
depth: BitDepth,
ctype: ColorType,
xlace: XlaceMode,
}
#[derive(Debug)]
pub struct Chunk
{
typ: Ident,
dat: Vec<u8>,
aux: bool,
cpy: bool,
}
c_enum! {
#[derive(Debug)]
enum BitDepth: u8
{
1 => Bits1,
2 => Bits2,
4 => Bits4,
8 => Bits8,
16 => Bits16,
}
}
c_enum! {
#[derive(Debug)]
enum ColorType: u8
{
0 => Grayscale,
2 => Truecolor,
3 => Indexed,
4 => GrayscaleAlpha,
6 => TruecolorAlpha,
}
}
c_enum! {
#[derive(Debug)]
enum FilterType: u8
{
0 => None,
1 => Sub,
2 => Up,
3 => Average,
4 => Paeth,
}
}
c_enum! {
#[derive(Debug)]
enum XlaceMode: u8
{
0 => None,
1 => Adam7,
}
}
// EOF

View File

@ -0,0 +1,9 @@
PngSuite
--------
Permission to use, copy, modify and distribute these images for any
purpose and without fee is hereby granted.
(c) Willem van Schaik, 1996, 2011

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 792 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 742 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 985 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Some files were not shown because too many files have changed in this diff Show More