more correct encoder, big pngs don't work yet
This commit is contained in:
parent
5c12875e81
commit
99c4262155
BIN
in/1kb.qoi
Normal file
BIN
in/1kb.qoi
Normal file
Binary file not shown.
BIN
out/1kb.qoi
BIN
out/1kb.qoi
Binary file not shown.
BIN
out/dice.qoi
BIN
out/dice.qoi
Binary file not shown.
@ -9,17 +9,17 @@ impl Ops {
|
|||||||
// @TODO don't alloc here, get a mut reference and extend here
|
// @TODO don't alloc here, get a mut reference and extend here
|
||||||
fn format (self) -> Vec<u8> {
|
fn format (self) -> Vec<u8> {
|
||||||
// cast_diff
|
// cast_diff
|
||||||
let cd = |diff: i8| cast_with_bias(diff, 2);
|
let cd = |diff: i8| cast_with_bias(diff, -2);
|
||||||
// cast_luma_green
|
// cast_luma_green
|
||||||
let clg = |diff: i8| cast_with_bias(diff, 32);
|
let clg = |diff: i8| cast_with_bias(diff, -32);
|
||||||
// cast_luma_red_blue
|
// cast_luma_red_blue
|
||||||
let clrb = |diff: i8| cast_with_bias(diff, 8);
|
let clrb = |diff: i8| cast_with_bias(diff, -8);
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Ops::Nop => vec![],
|
Ops::Nop => vec![],
|
||||||
Ops::Rgb([r, g, b]) => vec![254, r, g, b],
|
Ops::Rgb([r, g, b]) => vec![254, r, g, b],
|
||||||
Ops::Rgba([r, g, b, a]) => vec![255, r, g, b, a],
|
Ops::Rgba([r, g, b, a]) => vec![255, r, g, b, a],
|
||||||
Ops::Index(idx) => vec![0b1111 & idx as u8],
|
Ops::Index(idx) => vec![idx as u8],
|
||||||
Ops::Run(len) => vec![(3 << 6) | (len - 1)],
|
Ops::Run(len) => vec![(3 << 6) | (len - 1)],
|
||||||
Ops::Diff([dr, dg, db]) => vec![(1 << 6) | ((cd(dr) << 4) | (cd(dg) << 2) | cd(db)) ],
|
Ops::Diff([dr, dg, db]) => vec![(1 << 6) | ((cd(dr) << 4) | (cd(dg) << 2) | cd(db)) ],
|
||||||
Ops::Luma([dr, dg, db]) => vec![(2 << 6) | clg(dg), (clrb(dr) << 4) | clrb(db)],
|
Ops::Luma([dr, dg, db]) => vec![(2 << 6) | clg(dg), (clrb(dr) << 4) | clrb(db)],
|
||||||
@ -75,7 +75,7 @@ fn encode_body (header: Header, data: &[u8]) -> Option<Vec<u8>> {
|
|||||||
// INDEX -> DIFF -> LUMA -> RGB(A)
|
// INDEX -> DIFF -> LUMA -> RGB(A)
|
||||||
if known[hash] == rgba {
|
if known[hash] == rgba {
|
||||||
cur = Ops::Index(hash);
|
cur = Ops::Index(hash);
|
||||||
} else if let Some(ops) = diff_ops([r, g, b], [last[0], last[1], last[2]]) {
|
} else if let Some(ops) = diff_ops([last[0], last[1], last[2]], [r, g, b]) {
|
||||||
cur = ops;
|
cur = ops;
|
||||||
} else {
|
} else {
|
||||||
cur = header.channels.ops_color(&rgba[..header.channels.num()])?;
|
cur = header.channels.ops_color(&rgba[..header.channels.num()])?;
|
||||||
@ -90,7 +90,7 @@ fn encode_body (header: Header, data: &[u8]) -> Option<Vec<u8>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn encode_full (header: Header, bytes: &[u8]) -> Option<Vec<u8>> {
|
pub fn encode_full (header: Header, bytes: &[u8]) -> Option<Vec<u8>> {
|
||||||
let mut out = Vec::with_capacity(header.width as usize * header.height as usize * 4);
|
let mut out = Vec::with_capacity(header.width as usize * header.height as usize * 4);
|
||||||
out.extend_from_slice(&encode_header(header)?);
|
out.extend_from_slice(&encode_header(header)?);
|
||||||
out.extend_from_slice(&encode_body(header, bytes)?);
|
out.extend_from_slice(&encode_body(header, bytes)?);
|
||||||
@ -103,8 +103,6 @@ fn encode_full (header: Header, bytes: &[u8]) -> Option<Vec<u8>> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user