From 5404483367a97789f673f2583ae6aafca9d33fb0 Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sun, 15 Oct 2017 18:18:16 -0700 Subject: [PATCH 01/16] begin transformation decoding --- examples/decode.rs | 18 ++++++++++--- examples/flif_large.flif | Bin 0 -> 2082 bytes examples/{flif.flif => flif_small.flif} | Bin src/flif/components/header.rs | 26 +++++++++++++------ src/flif/components/mod.rs | 1 + src/flif/components/transformation.rs | 32 ++++++++++++++++++++++++ 6 files changed, 66 insertions(+), 11 deletions(-) create mode 100644 examples/flif_large.flif rename examples/{flif.flif => flif_small.flif} (100%) create mode 100644 src/flif/components/transformation.rs diff --git a/examples/decode.rs b/examples/decode.rs index 039b134e..21059802 100644 --- a/examples/decode.rs +++ b/examples/decode.rs @@ -3,11 +3,21 @@ extern crate flif; use flif::Decoder; fn main() { - let file = std::fs::File::open("examples/flif.flif").unwrap(); + let file = std::fs::File::open("examples/flif_small.flif").unwrap(); let mut decoder = Decoder::new(file); let flif = decoder.decode().unwrap(); - println!("{:?}", flif.header); - println!("{:?}", flif.metadata); - println!("{:?}", flif.second_header); + println!("Compact Flif Info:"); + println!("├───{:?}", flif.header); + println!("├───{:?}", flif.metadata); + println!("└───{:?}", flif.second_header); + + let file = std::fs::File::open("examples/flif_large.flif").unwrap(); + + let mut decoder = Decoder::new(file); + let flif = decoder.decode().unwrap(); + println!("Large Flif Info:"); + println!("├───{:?}", flif.header); + println!("├───{:?}", flif.metadata); + println!("└───{:?}", flif.second_header); } \ No newline at end of file diff --git a/examples/flif_large.flif b/examples/flif_large.flif new file mode 100644 index 0000000000000000000000000000000000000000..96988181e1228f216e863c5a432ad3cc75d8ec85 GIT binary patch literal 2082 zcmV+-2;KKaOi4yWF@j%$F94%Y{gNz)ZShwHC7z8zrVXm8 zlop&Z=G8T~beo!d6afq^TTfwu@T7+)0OeE);>%5pp!COeN#{z`!(z;$|`Dpj_I4y5-M1m<3MI zEo@rH#{^KuahFjxKqEpaDI_DQyz_L>5pF3Y($E***|8uvKDbZ(LQAH}h7dqIk+w;z z80Ljo>rt9At`cm%ao}Lfn-_ZwYDeRrpg@&ms}MvM4AooM?!oLUQc$Agt$e!Vy&)04 zFCV>)(!cCID#|As5{$+tmwtO|WYwk-+$%j?@W<}@RQ$TWw=pDZI4eA>4fQQ35>&^M zS3p`4s^pGmod%2;U_$?f^R4!qi1n!)Qkr7%_ZrNlsaL2>`;~Tt1$TlWOW|l4Q*L>N z-QultMzDNU#b()glk}GRR%wPy3hCZ98B6=92Ba9W(MBY*TuggCUkralgb`#T#S`9& z8NHImkdY%_ulsb)D&`LIh0|qVL+k&;I9rnealj!gPOuUvdLTV|mobkvBt!-dbTY$n zWmZE)(59t!7SK9Am}e);O#o_JlDdFOhM(O=#i*{`-qJTLoYd)aghSSBtok#_=k?-# zY@5sYW3vwW3`0$WzOip(ap?+Zt& zYAPK4EauW^W}$y0c!k}-(Xwn#4DxBPDaJGOfkxm2&aT-S4t<4_drOcoYfW@Ol&{>j zLH+HJ7CiWe^Z!Bm5USbCZQdz6;jJ~uV$-if%VLGr5vd{j${ys&KcKP}ch8Y;bE z0$4XWJ@LUunZsro(;F-wHB`g1$dJAWjB(dN{wHouDrBwr)ck4(bARd^i3QcS&qF2BC42dIGbxu^p92~n%0^8IUYF$ zGkn%fd-8*!o$00hjtjyew)tA{dP7gHwkMtvk8>eDdfHM_pvaWW#EDVv=GIT#xje5w zxd1h5@zk&~-@vnx(PTU%R(hd-J465f>1abc-7E9qT>qC!dxjrDEIR-HJ6=L;{4Ffx z|CeYBR(b<_T>sq`!*e$QDZl^iZ!p#_TFb&>{J`K+IO%WPZ`nEA09){e`shKmh{FH* z|KP>=A8X_MlEdH&>>+H{a6)a07)BrP17zrDnO$On3&)xfx7rH3``=zyVpfB^-M>8Y*PLF}m#Zg`lQ`3% zggUR+3gcCkpl*s;Z2D@lF0-EIzC=~(lKUtdtzxv8ww@44D_gA@4gxRYg5Is~ZAw40 zpRs!G7t!pzt8OQ+t2mmLmijV*t3Qfg_|AmE^_8TK=?$wTb$(LAmmuzl*7|Jb|2DJNRK7PP0r!A0ozHy_DRLOrm_W z=7(3bDH|*1Np@`%#FQ%zM)#c$RxI&sfrvT|d#d8*HVfe~8hCl8VhYABayAGrf1BEd zu8<>yi~33};eY^oMQ9ydCj0tpZE&MOAWJcW+rn)6pVbIagUskLcZ)xEHA<*_g^|3x z9=;_FmM)1o(>KB=VvmLlAQ?$g_mpwGiT;>1suvxx=ut``)RJ-$kiFpz%nEM(@73(W zrGs4Ny4(>e2)Vpbo+W*%63GzlGA&wz=!W%I^Ne6OF0p z1h4E3Kks#%C_vuY3el_qHRwDO5F@_}3qpu(#>iL!Ccb4*n4ePN5JZJz!(=$fNms&r z;*~iI;Oy!ug0)|{?D?~RZu1R(Fm^$axb&4qw{O zC5Js4@T=?V>h1%IqT>HxJemc#YVEx9B8+K;U5S6Eb9=xoccPI;j9w%{lQygN*1PZ|NsBrcD;m%vhq0wF;nR-98+`u|KsGM z5KX>8(r*9%|Np&w3IN8BcHJP*8feJNApigUTtq&k)!Dy;P5=M;yMmFU)VV8Ldx_{r z7I**u{&^F~HhN7%e#ig+|G{(0sO$x8QC9!zYUlt!YF|AlMI%?, // Placeholder until transformations are implemented + pub transformations: Vec, // Placeholder until transformations are implemented pub invis_pixel_predictor: u8, } @@ -161,11 +162,7 @@ impl SecondHeader { } // TODO: read transformations - let invis_pixel_predictor = if uni_decoder.read_bool()? { - 255 // placeholder - } else { - uni_decoder.read_val(0, 2)? - }; + let (t, invis_pixel_predictor) = Self::read_transformations(&mut uni_decoder)?; Ok(SecondHeader { bits_per_pixel, @@ -176,8 +173,23 @@ impl SecondHeader { cutoff, alpha_divisor, custom_bitchance, - transformations: vec![], + transformations: t, invis_pixel_predictor, }) } + + fn read_transformations<'rac, R: 'rac + Read>(uni_decoder: &mut UniformSymbolDecoder<'rac, R>) -> Result<(Vec, u8)> { + let mut transformations = vec![]; + while uni_decoder.read_bool()? { + let transformation = Transformations::from_int(uni_decoder.read_val(0, 13)?); + transformations.push(transformation); + match transformation { + Transformations::YCoGg => continue, + _ => return Ok((transformations, 255)) + + } + } + + Ok((transformations, uni_decoder.read_val(0, 2)?)) + } } diff --git a/src/flif/components/mod.rs b/src/flif/components/mod.rs index 2ac29d12..8297c962 100644 --- a/src/flif/components/mod.rs +++ b/src/flif/components/mod.rs @@ -1,2 +1,3 @@ pub mod header; pub mod metadata; +pub mod transformation; \ No newline at end of file diff --git a/src/flif/components/transformation.rs b/src/flif/components/transformation.rs new file mode 100644 index 00000000..1288fbd0 --- /dev/null +++ b/src/flif/components/transformation.rs @@ -0,0 +1,32 @@ +#[derive(Copy, Clone, Debug)] +pub enum Transformations { + ChannelCompact, + YCoGg, + PermutePlanes, + Bounds, + PalleteAlpha, + Pallete, + ColorBuckets, + DuplicateFrame, + FrameShape, + FrameLookback +} + +impl Transformations { + pub fn from_int(num: u32) -> Transformations { + use self::Transformations::*; + match num { + 0 => ChannelCompact, + 1 => YCoGg, + 3 => PermutePlanes, + 4 => Bounds, + 5 => PalleteAlpha, + 6 => Pallete, + 7 => ColorBuckets, + 10 => DuplicateFrame, + 11 => FrameShape, + 12 => FrameLookback, + _ => unimplemented!() + } + } +} \ No newline at end of file From 94bd0877fb1e734f3facb23ef82d22d8be726060 Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Mon, 16 Oct 2017 23:47:52 -0500 Subject: [PATCH 02/16] move transformations to a folder --- .../{transformation.rs => transformations/mod.rs} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename src/flif/components/{transformation.rs => transformations/mod.rs} (92%) diff --git a/src/flif/components/transformation.rs b/src/flif/components/transformations/mod.rs similarity index 92% rename from src/flif/components/transformation.rs rename to src/flif/components/transformations/mod.rs index 1288fbd0..be47c741 100644 --- a/src/flif/components/transformation.rs +++ b/src/flif/components/transformations/mod.rs @@ -9,7 +9,7 @@ pub enum Transformations { ColorBuckets, DuplicateFrame, FrameShape, - FrameLookback + FrameLookback, } impl Transformations { @@ -26,7 +26,7 @@ impl Transformations { 10 => DuplicateFrame, 11 => FrameShape, 12 => FrameLookback, - _ => unimplemented!() + _ => unimplemented!(), } } -} \ No newline at end of file +} From 4604b023e3c3b57e78c1608bf75b22a6bb6570a0 Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Mon, 16 Oct 2017 22:29:34 -0700 Subject: [PATCH 03/16] change transformation to a trait --- src/flif/components/header.rs | 22 ++-------- src/flif/components/mod.rs | 2 +- src/flif/components/transformations/bounds.rs | 0 .../transformations/channel_compact.rs | 40 +++++++++++++++++ src/flif/components/transformations/mod.rs | 44 ++++++------------- .../transformations/permute_planes.rs | 0 src/flif/components/transformations/ycocg.rs | 31 +++++++++++++ 7 files changed, 89 insertions(+), 50 deletions(-) create mode 100644 src/flif/components/transformations/bounds.rs create mode 100644 src/flif/components/transformations/channel_compact.rs create mode 100644 src/flif/components/transformations/permute_planes.rs create mode 100644 src/flif/components/transformations/ycocg.rs diff --git a/src/flif/components/header.rs b/src/flif/components/header.rs index a972a41a..830cb7c3 100644 --- a/src/flif/components/header.rs +++ b/src/flif/components/header.rs @@ -3,7 +3,6 @@ use error::*; use numbers::FlifReadExt; use numbers::rac::Rac; use numbers::symbol::UniformSymbolDecoder; -use components::transformation::Transformations; #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum Channels { @@ -106,7 +105,7 @@ pub struct SecondHeader { pub cutoff: u8, pub alpha_divisor: u8, pub custom_bitchance: bool, - pub transformations: Vec, // Placeholder until transformations are implemented + pub transformations: (), // Placeholder until transformations are implemented pub invis_pixel_predictor: u8, } @@ -162,7 +161,7 @@ impl SecondHeader { } // TODO: read transformations - let (t, invis_pixel_predictor) = Self::read_transformations(&mut uni_decoder)?; + let invis_pixel_predictor = 255; Ok(SecondHeader { bits_per_pixel, @@ -173,23 +172,8 @@ impl SecondHeader { cutoff, alpha_divisor, custom_bitchance, - transformations: t, + transformations: (), invis_pixel_predictor, }) } - - fn read_transformations<'rac, R: 'rac + Read>(uni_decoder: &mut UniformSymbolDecoder<'rac, R>) -> Result<(Vec, u8)> { - let mut transformations = vec![]; - while uni_decoder.read_bool()? { - let transformation = Transformations::from_int(uni_decoder.read_val(0, 13)?); - transformations.push(transformation); - match transformation { - Transformations::YCoGg => continue, - _ => return Ok((transformations, 255)) - - } - } - - Ok((transformations, uni_decoder.read_val(0, 2)?)) - } } diff --git a/src/flif/components/mod.rs b/src/flif/components/mod.rs index 8297c962..c079a4b2 100644 --- a/src/flif/components/mod.rs +++ b/src/flif/components/mod.rs @@ -1,3 +1,3 @@ pub mod header; pub mod metadata; -pub mod transformation; \ No newline at end of file +pub mod transformations; diff --git a/src/flif/components/transformations/bounds.rs b/src/flif/components/transformations/bounds.rs new file mode 100644 index 00000000..e69de29b diff --git a/src/flif/components/transformations/channel_compact.rs b/src/flif/components/transformations/channel_compact.rs new file mode 100644 index 00000000..cdd40c57 --- /dev/null +++ b/src/flif/components/transformations/channel_compact.rs @@ -0,0 +1,40 @@ +use super::Transformation; + +pub struct ChannelCompact { + min: u16, + max: u16, + cmin: u16, + cmax: u16, +} +impl ChannelCompact { + pub fn new(transformation: &T, num_channels: u8) -> ChannelCompact { + ChannelCompact { + min: 0, + max: 0, + cmin: 0, + cmax: 0, + } + } +} + +impl Transformation for ChannelCompact { + fn snap(&self, channel: u8, values: u16, pixel: u16) -> u16 { + unimplemented!() + } + + fn min(&self, channel: u8) -> u16 { + unimplemented!() + } + + fn max(&self, channel: u8) -> u16 { + unimplemented!() + } + + fn cmin(&self, channel: u8, values: u16) -> u16 { + unimplemented!() + } + + fn cmax(&self, channel: u8, values: u16) -> u16 { + unimplemented!() + } +} diff --git a/src/flif/components/transformations/mod.rs b/src/flif/components/transformations/mod.rs index be47c741..ef663c68 100644 --- a/src/flif/components/transformations/mod.rs +++ b/src/flif/components/transformations/mod.rs @@ -1,32 +1,16 @@ -#[derive(Copy, Clone, Debug)] -pub enum Transformations { - ChannelCompact, - YCoGg, - PermutePlanes, - Bounds, - PalleteAlpha, - Pallete, - ColorBuckets, - DuplicateFrame, - FrameShape, - FrameLookback, -} +mod bounds; +mod channel_compact; +mod permute_planes; +mod ycocg; + +pub trait Transformation { + fn snap(&self, channel: u8, values: u16, pixel: u16) -> u16; + + fn min(&self, channel: u8) -> u16; + + fn max(&self, channel: u8) -> u16; + + fn cmin(&self, channel: u8, values: u16) -> u16; -impl Transformations { - pub fn from_int(num: u32) -> Transformations { - use self::Transformations::*; - match num { - 0 => ChannelCompact, - 1 => YCoGg, - 3 => PermutePlanes, - 4 => Bounds, - 5 => PalleteAlpha, - 6 => Pallete, - 7 => ColorBuckets, - 10 => DuplicateFrame, - 11 => FrameShape, - 12 => FrameLookback, - _ => unimplemented!(), - } - } + fn cmax(&self, channel: u8, values: u16) -> u16; } diff --git a/src/flif/components/transformations/permute_planes.rs b/src/flif/components/transformations/permute_planes.rs new file mode 100644 index 00000000..e69de29b diff --git a/src/flif/components/transformations/ycocg.rs b/src/flif/components/transformations/ycocg.rs new file mode 100644 index 00000000..8dfa66f8 --- /dev/null +++ b/src/flif/components/transformations/ycocg.rs @@ -0,0 +1,31 @@ +use super::Transformation; + +pub struct YCoGg; + +impl YCoGg { + pub fn new(transformation: &T) -> YCoGg { + YCoGg + } +} + +impl Transformation for YCoGg { + fn snap(&self, channel: u8, values: u16, pixel: u16) -> u16 { + unimplemented!() + } + + fn min(&self, channel: u8) -> u16 { + unimplemented!() + } + + fn max(&self, channel: u8) -> u16 { + unimplemented!() + } + + fn cmin(&self, channel: u8, values: u16) -> u16 { + unimplemented!() + } + + fn cmax(&self, channel: u8, values: u16) -> u16 { + unimplemented!() + } +} From a87467a4539e61aa8a375c4e7ad2ebff54641152 Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Mon, 16 Oct 2017 22:41:11 -0700 Subject: [PATCH 04/16] change uni symbol reader to free function --- src/flif/components/header.rs | 20 +++++++++----------- src/flif/numbers/symbol.rs | 34 ++++++++++++---------------------- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/flif/components/header.rs b/src/flif/components/header.rs index 830cb7c3..1d85e208 100644 --- a/src/flif/components/header.rs +++ b/src/flif/components/header.rs @@ -2,7 +2,7 @@ use std::io::Read; use error::*; use numbers::FlifReadExt; use numbers::rac::Rac; -use numbers::symbol::UniformSymbolDecoder; +use numbers::symbol; #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum Channels { @@ -111,43 +111,41 @@ pub struct SecondHeader { impl SecondHeader { pub fn from_rac(main_header: &Header, rac: &mut Rac) -> Result { - let mut uni_decoder = UniformSymbolDecoder::new(rac); - let bits_per_pixel = (0..main_header.channels as u8) .map(|_| match main_header.bytes_per_channel { BytesPerChannel::One => Ok(8), BytesPerChannel::Two => Ok(16), - BytesPerChannel::Custom => uni_decoder.read_val(1, 16), + BytesPerChannel::Custom => symbol::read_val(rac, 1, 16), }) .collect::>>()?; let alpha_zero = if main_header.channels == Channels::RGBA { - uni_decoder.read_bool()? + symbol::read_bool(rac)? } else { false }; let loops = if main_header.animated { - Some(uni_decoder.read_val(0, 100)?) + Some(symbol::read_val(rac, 0, 100)?) } else { None }; let frame_delay = if main_header.animated { Some((0..main_header.num_frames) - .map(|_| uni_decoder.read_val(0, 60_000)) + .map(|_| symbol::read_val(rac, 0, 60_000)) .collect::>>()?) } else { None }; - let custom_cutoff = uni_decoder.read_bool()?; + let custom_cutoff = symbol::read_bool(rac)?; let (cutoff, alpha_divisor, custom_bitchance) = if custom_cutoff { ( - uni_decoder.read_val(1, 128)?, - uni_decoder.read_val(2, 128)?, - uni_decoder.read_bool()?, + symbol::read_val(rac, 1, 128)?, + symbol::read_val(rac, 2, 128)?, + symbol::read_bool(rac)?, ) } else { (2, 19, false) diff --git a/src/flif/numbers/symbol.rs b/src/flif/numbers/symbol.rs index 7184be6c..7aabe3dd 100644 --- a/src/flif/numbers/symbol.rs +++ b/src/flif/numbers/symbol.rs @@ -3,29 +3,19 @@ use error::*; use num_traits::PrimInt; use super::rac::Rac; -pub struct UniformSymbolDecoder<'rac, R: 'rac> { - rac: &'rac mut Rac, -} - -impl<'rac, R: Read> UniformSymbolDecoder<'rac, R> { - pub fn new(rac: &'rac mut Rac) -> Self { - UniformSymbolDecoder { rac } - } - - pub fn read_val(&mut self, mut min: T, mut max: T) -> Result { - while max != min { - let mid = min + ((max - min) >> 1); - if self.rac.read_bit()? { - min = mid + T::one(); - } else { - max = mid; - } +pub fn read_val(rac: &mut Rac, mut min: T, mut max: T) -> Result { + while max != min { + let mid = min + ((max - min) >> 1); + if rac.read_bit()? { + min = mid + T::one(); + } else { + max = mid; } - - Ok(min) } - pub fn read_bool(&mut self) -> Result { - Ok(self.rac.read_bit()?) - } + Ok(min) +} + +pub fn read_bool(rac: &mut Rac) -> Result { + Ok(rac.read_bit()?) } From 9cb64a563fe049a33c47f89f620abac6e74eb0ec Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sat, 21 Oct 2017 19:16:27 -0700 Subject: [PATCH 05/16] convert symbol coder to a trait --- src/flif/components/header.rs | 18 +++++++++--------- src/flif/numbers/symbol.rs | 31 +++++++++++++++++++------------ 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/flif/components/header.rs b/src/flif/components/header.rs index 1d85e208..9222018a 100644 --- a/src/flif/components/header.rs +++ b/src/flif/components/header.rs @@ -1,8 +1,8 @@ use std::io::Read; use error::*; use numbers::FlifReadExt; +use numbers::symbol::UniformSymbolCoder; use numbers::rac::Rac; -use numbers::symbol; #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum Channels { @@ -115,37 +115,37 @@ impl SecondHeader { .map(|_| match main_header.bytes_per_channel { BytesPerChannel::One => Ok(8), BytesPerChannel::Two => Ok(16), - BytesPerChannel::Custom => symbol::read_val(rac, 1, 16), + BytesPerChannel::Custom => rac.read_val(1, 16), }) .collect::>>()?; let alpha_zero = if main_header.channels == Channels::RGBA { - symbol::read_bool(rac)? + rac.read_bool()? } else { false }; let loops = if main_header.animated { - Some(symbol::read_val(rac, 0, 100)?) + Some(rac.read_val(0, 100)?) } else { None }; let frame_delay = if main_header.animated { Some((0..main_header.num_frames) - .map(|_| symbol::read_val(rac, 0, 60_000)) + .map(|_| rac.read_val(0, 60_000)) .collect::>>()?) } else { None }; - let custom_cutoff = symbol::read_bool(rac)?; + let custom_cutoff = rac.read_bool()?; let (cutoff, alpha_divisor, custom_bitchance) = if custom_cutoff { ( - symbol::read_val(rac, 1, 128)?, - symbol::read_val(rac, 2, 128)?, - symbol::read_bool(rac)?, + rac.read_val(1, 128)?, + rac.read_val(2, 128)?, + rac.read_bool()?, ) } else { (2, 19, false) diff --git a/src/flif/numbers/symbol.rs b/src/flif/numbers/symbol.rs index 7aabe3dd..71a10c24 100644 --- a/src/flif/numbers/symbol.rs +++ b/src/flif/numbers/symbol.rs @@ -3,19 +3,26 @@ use error::*; use num_traits::PrimInt; use super::rac::Rac; -pub fn read_val(rac: &mut Rac, mut min: T, mut max: T) -> Result { - while max != min { - let mid = min + ((max - min) >> 1); - if rac.read_bit()? { - min = mid + T::one(); - } else { - max = mid; +pub trait UniformSymbolCoder { + fn read_val(&mut self, min: T, max: T) -> Result; + fn read_bool(&mut self) -> Result; +} + +impl UniformSymbolCoder for Rac { + fn read_val(&mut self, mut min: T, mut max: T) -> Result { + while max != min { + let mid = min + ((max - min) >> 1); + if self.read_bit()? { + min = mid + T::one(); + } else { + max = mid; + } } - } - Ok(min) -} + Ok(min) + } -pub fn read_bool(rac: &mut Rac) -> Result { - Ok(rac.read_bit()?) + fn read_bool(&mut self) -> Result { + Ok(self.read_bit()?) + } } From 03580c91e5e49deb93cc9033e9b59c890a4f5c4f Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sat, 21 Oct 2017 19:26:26 -0700 Subject: [PATCH 06/16] convert near_zero into a trait --- src/flif/numbers/near_zero.rs | 90 ++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/src/flif/numbers/near_zero.rs b/src/flif/numbers/near_zero.rs index 7156c57b..751962af 100644 --- a/src/flif/numbers/near_zero.rs +++ b/src/flif/numbers/near_zero.rs @@ -5,55 +5,62 @@ use numbers::rac::ChanceTable; use numbers::rac::ChanceTableEntry; use numbers::rac::Rac; -pub fn read_near_zero( - min: i32, - max: i32, - rac: &mut Rac, - context: &mut ChanceTable, -) -> Result { - assert!(min < max); +pub trait NearZeroCoder { + fn read_near_zero(&mut self, min: i32, max: i32, context: &mut ChanceTable); +} - if min == max { - return Ok(min); - } +impl NearZeroCoder for Rac { + fn read_near_zero( + &mut self, + min: i32, + max: i32, + context: &mut ChanceTable, + ) -> Result { + assert!(min < max); - if rac.read(context, ChanceTableEntry::Zero)? { - return Ok(0); - } + if min == max { + return Ok(min); + } + + if self.read(context, ChanceTableEntry::Zero)? { + return Ok(0); + } - let sign = if min < 0 && max > 0 { - rac.read(context, ChanceTableEntry::Sign)? - } else if min < 0 && max < 0 { - false - } else { - true - }; + let sign = if min < 0 && max > 0 { + self.read(context, ChanceTableEntry::Sign)? + } else { + {} + {} + min < 0 + }; + + let absolute_max = ::std::cmp::max(max, -min); + let largest_exponent = + (::std::mem::size_of::() * 8) - absolute_max.leading_zeros() as usize - 1; - let absolute_max = ::std::cmp::max(max, -min); - let largest_exponent = - (::std::mem::size_of::() * 8) - absolute_max.leading_zeros() as usize - 1; + let mut exponent = 0; + loop { + if exponent as usize == largest_exponent + || self.read(context, ChanceTableEntry::Exp(exponent, sign))? + { + break; + } - let mut exponent = 0; - loop { - if exponent as usize == largest_exponent || rac.read(context, ChanceTableEntry::Exp(exponent, sign))? { - break; + exponent += 1; } - exponent += 1; - } + // the first mantissa bit is always 1 + let mut have = 1 << exponent; - // the first mantissa bit is always 1 - let mut have = 1 << exponent; - - // if all other mantissa bits are 1, then the total is have+left - let mut left = have-1; + // if all other mantissa bits are 1, then the total is have+left + let mut left = have - 1; // read mantissa bits from most-significant to least-significant for pos in (exponent - 1)..0 { - left >>= 1; + left >>= 1; // if the bit is 1, then the value will be at least minabs1 - let minabs1 = have | (1< absolute_max { @@ -62,18 +69,15 @@ pub fn read_near_zero( } else if maxabs0 >= 1 { // 0-bit and 1-bit are both possible, // so we read the bit and adjust what we have if it is a 1 - if rac.read(context, ChanceTableEntry::Mant(pos))? { + if self.read(context, ChanceTableEntry::Mant(pos))? { have = minabs1; - } + } } else { // 0-bit is impossible (would make the value zero), // so assume the bit is 1 without reading it have = minabs1; } } - Ok(if sign { - have - } else { - -have - }) + Ok(if sign { have } else { -have }) + } } From 93bf193d88a34faa34e71c2ece590009566549bb Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sat, 21 Oct 2017 19:44:02 -0700 Subject: [PATCH 07/16] fix build issues from trait conversion --- src/flif/numbers/near_zero.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flif/numbers/near_zero.rs b/src/flif/numbers/near_zero.rs index 751962af..b18cb261 100644 --- a/src/flif/numbers/near_zero.rs +++ b/src/flif/numbers/near_zero.rs @@ -6,11 +6,11 @@ use numbers::rac::ChanceTableEntry; use numbers::rac::Rac; pub trait NearZeroCoder { - fn read_near_zero(&mut self, min: i32, max: i32, context: &mut ChanceTable); + fn read_near_zero(&mut self, min: i32, max: i32, context: &mut ChanceTable) -> Result; } impl NearZeroCoder for Rac { - fn read_near_zero( + fn read_near_zero( &mut self, min: i32, max: i32, From 5cd1516e5d2f36841af55b3d81d211ca7f0673d3 Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sat, 21 Oct 2017 19:58:01 -0700 Subject: [PATCH 08/16] make near_zero generic --- src/flif/numbers/near_zero.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/flif/numbers/near_zero.rs b/src/flif/numbers/near_zero.rs index b18cb261..ed5ae26e 100644 --- a/src/flif/numbers/near_zero.rs +++ b/src/flif/numbers/near_zero.rs @@ -6,16 +6,21 @@ use numbers::rac::ChanceTableEntry; use numbers::rac::Rac; pub trait NearZeroCoder { - fn read_near_zero(&mut self, min: i32, max: i32, context: &mut ChanceTable) -> Result; + fn read_near_zero( + &mut self, + min: I, + max: I, + context: &mut ChanceTable, + ) -> Result; } impl NearZeroCoder for Rac { - fn read_near_zero( + fn read_near_zero( &mut self, - min: i32, - max: i32, + min: I, + max: I, context: &mut ChanceTable, - ) -> Result { + ) -> Result { assert!(min < max); if min == max { @@ -23,20 +28,18 @@ impl NearZeroCoder for Rac { } if self.read(context, ChanceTableEntry::Zero)? { - return Ok(0); + return Ok(I::zero()); } - let sign = if min < 0 && max > 0 { + let sign = if min < I::zero() && max > I::zero() { self.read(context, ChanceTableEntry::Sign)? } else { - {} - {} - min < 0 + min < I::zero() }; let absolute_max = ::std::cmp::max(max, -min); let largest_exponent = - (::std::mem::size_of::() * 8) - absolute_max.leading_zeros() as usize - 1; + (::std::mem::size_of::() * 8) - absolute_max.leading_zeros() as usize - 1; let mut exponent = 0; loop { @@ -63,7 +66,7 @@ impl NearZeroCoder for Rac { let minabs1 = have | (1 << pos); // if the bit is 0, then the value will be at most maxabs0 let maxabs0 = have | left; - if minabs1 > absolute_max { + if I::from(minabs1).unwrap() > absolute_max { // 1-bit is impossible (would bump value above maximum), // so assume the bit is 0 without reading it } else if maxabs0 >= 1 { @@ -78,6 +81,7 @@ impl NearZeroCoder for Rac { have = minabs1; } } + let have = I::from(have).unwrap(); Ok(if sign { have } else { -have }) } } From 8a4ebda9c8a412c36fd3efb98635404be76f0745 Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sat, 21 Oct 2017 21:56:09 -0700 Subject: [PATCH 09/16] supposedly read three transforms --- src/flif/components/header.rs | 25 +++++-- src/flif/components/transformations/bounds.rs | 54 ++++++++++++++ .../transformations/channel_compact.rs | 56 +++++++++++--- src/flif/components/transformations/mod.rs | 66 ++++++++++++++++- src/flif/components/transformations/ycocg.rs | 5 +- src/flif/numbers/near_zero.rs | 73 ++++++++++++++++++- 6 files changed, 253 insertions(+), 26 deletions(-) diff --git a/src/flif/components/header.rs b/src/flif/components/header.rs index 9222018a..8a541f74 100644 --- a/src/flif/components/header.rs +++ b/src/flif/components/header.rs @@ -3,6 +3,8 @@ use error::*; use numbers::FlifReadExt; use numbers::symbol::UniformSymbolCoder; use numbers::rac::Rac; +use super::transformations; +use super::transformations::Transformation; #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum Channels { @@ -105,7 +107,7 @@ pub struct SecondHeader { pub cutoff: u8, pub alpha_divisor: u8, pub custom_bitchance: bool, - pub transformations: (), // Placeholder until transformations are implemented + pub transformations: Vec>, // Placeholder until transformations are implemented pub invis_pixel_predictor: u8, } @@ -158,10 +160,7 @@ impl SecondHeader { )); } - // TODO: read transformations - let invis_pixel_predictor = 255; - - Ok(SecondHeader { + let mut second = SecondHeader { bits_per_pixel, alpha_zero, loops, @@ -170,8 +169,18 @@ impl SecondHeader { cutoff, alpha_divisor, custom_bitchance, - transformations: (), - invis_pixel_predictor, - }) + transformations: Vec::new(), + invis_pixel_predictor: 0, + }; + + let transformations = + transformations::load_transformations(rac, (&main_header, &second))?; + // TODO: read transformations + let invis_pixel_predictor = rac.read_val(0, 2)?; + + second.transformations = transformations; + second.invis_pixel_predictor = invis_pixel_predictor; + + Ok(second) } } diff --git a/src/flif/components/transformations/bounds.rs b/src/flif/components/transformations/bounds.rs index e69de29b..80ca408c 100644 --- a/src/flif/components/transformations/bounds.rs +++ b/src/flif/components/transformations/bounds.rs @@ -0,0 +1,54 @@ +use super::Transformation; +use numbers::rac::Rac; +use std::io::Read; +use numbers::near_zero::NearZeroCoder; +use components::header::{Header, SecondHeader}; +use numbers::rac::ChanceTable; +use error::*; + +#[derive(Debug)] +pub struct Bounds { + min: [u16; 4], + max: [u16; 4], +} + +impl Bounds { + pub fn new( + rac: &mut Rac, + trans: &T, + (ref header, ref second): (&Header, &SecondHeader), + ) -> Result { + let mut context = ChanceTable::new(second.alpha_divisor, second.cutoff); + let mut min = [0; 4]; + let mut max = [0; 4]; + for c in 0..header.channels as usize { + min[c] = rac.read_near_zero(0, trans.max(c as u8) - trans.min(c as u8), &mut context)? + + trans.min(c as u8); + max[c] = rac.read_near_zero(0, trans.max(c as u8) - min[c], &mut context)? + min[c]; + } + + Ok(Bounds { min, max }) + } +} + +impl Transformation for Bounds { + fn snap(&self, channel: u8, values: u16, pixel: u16) -> u16 { + unimplemented!() + } + + fn min(&self, channel: u8) -> u16 { + self.min[channel as usize] + } + + fn max(&self, channel: u8) -> u16 { + self.max[channel as usize] + } + + fn cmin(&self, channel: u8, values: u16) -> u16 { + unimplemented!() + } + + fn cmax(&self, channel: u8, values: u16) -> u16 { + unimplemented!() + } +} diff --git a/src/flif/components/transformations/channel_compact.rs b/src/flif/components/transformations/channel_compact.rs index cdd40c57..10934893 100644 --- a/src/flif/components/transformations/channel_compact.rs +++ b/src/flif/components/transformations/channel_compact.rs @@ -1,19 +1,51 @@ use super::Transformation; +use numbers::rac::Rac; +use std::io::Read; +use numbers::near_zero::NearZeroCoder; +use components::header::{Header, SecondHeader}; +use numbers::rac::{ChanceTable, ChanceTableEntry}; +use error::*; +#[derive(Debug)] pub struct ChannelCompact { - min: u16, - max: u16, - cmin: u16, - cmax: u16, + min: [u16; 4], + max: [u16; 4], + decompacted: Vec, } impl ChannelCompact { - pub fn new(transformation: &T, num_channels: u8) -> ChannelCompact { - ChannelCompact { - min: 0, - max: 0, - cmin: 0, - cmax: 0, + pub fn new( + rac: &mut Rac, + transformation: &T, + (ref header, ref second): (&Header, &SecondHeader), + ) -> Result { + let mut context = ChanceTable::new(second.alpha_divisor, second.cutoff); + let mut t = ChannelCompact { + min: [0; 4], + max: [0; 4], + decompacted: Vec::new(), + }; + + for c in 0..header.channels as usize { + t.max[c] = rac.read_near_zero( + 0, + transformation.max(c as u8) - transformation.min(c as u8), + &mut context, + )?; + t.min[c] = transformation.min(c as u8); + for i in 0..t.max[c] { + t.decompacted.push( + t.min[c] + + rac.read_near_zero( + 0, + transformation.max(c as u8) - t.min[c] + t.max[c] - i, + &mut context, + )?, + ); + t.min[c] = t.decompacted[i as usize]; + } } + + Ok(t) } } @@ -23,11 +55,11 @@ impl Transformation for ChannelCompact { } fn min(&self, channel: u8) -> u16 { - unimplemented!() + self.min[channel as usize] } fn max(&self, channel: u8) -> u16 { - unimplemented!() + self.max[channel as usize] } fn cmin(&self, channel: u8, values: u16) -> u16 { diff --git a/src/flif/components/transformations/mod.rs b/src/flif/components/transformations/mod.rs index ef663c68..195b78a1 100644 --- a/src/flif/components/transformations/mod.rs +++ b/src/flif/components/transformations/mod.rs @@ -1,9 +1,18 @@ +use numbers::rac::Rac; +use std::io::Read; +use numbers::symbol::UniformSymbolCoder; +use components::header::{Header, SecondHeader}; +use self::channel_compact::ChannelCompact; +use error::*; +use self::bounds::Bounds; +use self::ycocg::YCoGg; + mod bounds; mod channel_compact; mod permute_planes; mod ycocg; -pub trait Transformation { +pub trait Transformation: ::std::fmt::Debug { fn snap(&self, channel: u8, values: u16, pixel: u16) -> u16; fn min(&self, channel: u8) -> u16; @@ -14,3 +23,58 @@ pub trait Transformation { fn cmax(&self, channel: u8, values: u16) -> u16; } + +#[derive(Debug)] +struct Orig; + +impl Transformation for Orig { + fn snap(&self, _channel: u8, _values: u16, pixel: u16) -> u16 { + pixel + } + + fn min(&self, _channel: u8) -> u16 { + 0 + } + + fn max(&self, _channel: u8) -> u16 { + 255 + } + + fn cmin(&self, _channel: u8, _values: u16) -> u16 { + 0 + } + + fn cmax(&self, _channel: u8, _values: u16) -> u16 { + 255 + } +} + +pub fn load_transformations( + rac: &mut Rac, + (ref header, ref second): (&Header, &SecondHeader), +) -> Result>> { + let mut transforms: Vec> = Vec::new(); + transforms.push(Box::new(Orig)); + while rac.read_bit()? { + let id = rac.read_val(0, 13)?; + let t = match id { + 0 => Box::new(ChannelCompact::new( + rac, + transforms[transforms.len() - 1].as_ref(), + (header, second), + )?), + 1 => Box::new(YCoGg) as Box, + 4 => Box::new(Bounds::new( + rac, + transforms[transforms.len() - 1].as_ref(), + (header, second), + )?), + _ => { + break; + } + }; + transforms.push(t); + } + + Ok(transforms) +} diff --git a/src/flif/components/transformations/ycocg.rs b/src/flif/components/transformations/ycocg.rs index 8dfa66f8..1edc0b76 100644 --- a/src/flif/components/transformations/ycocg.rs +++ b/src/flif/components/transformations/ycocg.rs @@ -1,5 +1,6 @@ use super::Transformation; +#[derive(Debug)] pub struct YCoGg; impl YCoGg { @@ -14,11 +15,11 @@ impl Transformation for YCoGg { } fn min(&self, channel: u8) -> u16 { - unimplemented!() + 0 } fn max(&self, channel: u8) -> u16 { - unimplemented!() + 255 } fn cmin(&self, channel: u8, values: u16) -> u16 { diff --git a/src/flif/numbers/near_zero.rs b/src/flif/numbers/near_zero.rs index ed5ae26e..229a1812 100644 --- a/src/flif/numbers/near_zero.rs +++ b/src/flif/numbers/near_zero.rs @@ -1,12 +1,19 @@ use std::io::Read; use error::*; -use num_traits::{PrimInt, Signed}; +use num_traits::{PrimInt, Signed, Unsigned}; use numbers::rac::ChanceTable; use numbers::rac::ChanceTableEntry; use numbers::rac::Rac; pub trait NearZeroCoder { - fn read_near_zero( + fn read_near_zero( + &mut self, + min: I, + max: I, + context: &mut ChanceTable, + ) -> Result; + + fn read_near_zero_signed( &mut self, min: I, max: I, @@ -15,7 +22,67 @@ pub trait NearZeroCoder { } impl NearZeroCoder for Rac { - fn read_near_zero( + fn read_near_zero( + &mut self, + min: I, + max: I, + context: &mut ChanceTable, + ) -> Result { + if min == max { + return Ok(min); + } + + if self.read(context, ChanceTableEntry::Zero)? { + return Ok(I::zero()); + } + + let largest_exponent = (::std::mem::size_of::() * 8) - max.leading_zeros() as usize - 1; + + let mut exponent = 0; + loop { + if exponent as usize == largest_exponent + || self.read(context, ChanceTableEntry::Exp(exponent, true))? + { + break; + } + + exponent += 1; + } + + // the first mantissa bit is always 1 + let mut have = 1 << exponent; + + // if all other mantissa bits are 1, then the total is have+left + let mut left = have - 1; + + // read mantissa bits from most-significant to least-significant + for pos in (exponent - 1)..0 { + left >>= 1; + + // if the bit is 1, then the value will be at least minabs1 + let minabs1 = have | (1 << pos); + // if the bit is 0, then the value will be at most maxabs0 + let maxabs0 = have | left; + if I::from(minabs1).unwrap() > max { + // 1-bit is impossible (would bump value above maximum), + // so assume the bit is 0 without reading it + } else if maxabs0 >= 1 { + // 0-bit and 1-bit are both possible, + // so we read the bit and adjust what we have if it is a 1 + if self.read(context, ChanceTableEntry::Mant(pos))? { + have = minabs1; + } + } else { + // 0-bit is impossible (would make the value zero), + // so assume the bit is 1 without reading it + have = minabs1; + } + } + let have = I::from(have).unwrap(); + Ok(have) + } + + fn read_near_zero_signed( &mut self, min: I, max: I, From 6da33e9684f4f5e7cef9fe6d429b29ca99794f4f Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sat, 21 Oct 2017 22:25:31 -0700 Subject: [PATCH 10/16] fix near_zero logic error --- src/flif/numbers/near_zero.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flif/numbers/near_zero.rs b/src/flif/numbers/near_zero.rs index 229a1812..de2e11af 100644 --- a/src/flif/numbers/near_zero.rs +++ b/src/flif/numbers/near_zero.rs @@ -56,7 +56,7 @@ impl NearZeroCoder for Rac { let mut left = have - 1; // read mantissa bits from most-significant to least-significant - for pos in (exponent - 1)..0 { + for pos in (0..exponent).rev() { left >>= 1; // if the bit is 1, then the value will be at least minabs1 From 746616612bdf59c9554bf0561b8805dc4159514b Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sat, 21 Oct 2017 22:26:00 -0700 Subject: [PATCH 11/16] fix channel_compact logic --- .../transformations/channel_compact.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/flif/components/transformations/channel_compact.rs b/src/flif/components/transformations/channel_compact.rs index 10934893..e52ade59 100644 --- a/src/flif/components/transformations/channel_compact.rs +++ b/src/flif/components/transformations/channel_compact.rs @@ -8,9 +8,8 @@ use error::*; #[derive(Debug)] pub struct ChannelCompact { - min: [u16; 4], max: [u16; 4], - decompacted: Vec, + decompacted: [Vec; 4], } impl ChannelCompact { pub fn new( @@ -20,9 +19,8 @@ impl ChannelCompact { ) -> Result { let mut context = ChanceTable::new(second.alpha_divisor, second.cutoff); let mut t = ChannelCompact { - min: [0; 4], max: [0; 4], - decompacted: Vec::new(), + decompacted: [Vec::new(), Vec::new(), Vec::new(), Vec::new()], }; for c in 0..header.channels as usize { @@ -31,17 +29,17 @@ impl ChannelCompact { transformation.max(c as u8) - transformation.min(c as u8), &mut context, )?; - t.min[c] = transformation.min(c as u8); + let mut min = transformation.min(c as u8); for i in 0..t.max[c] { - t.decompacted.push( - t.min[c] + t.decompacted[c].push( + min + rac.read_near_zero( 0, - transformation.max(c as u8) - t.min[c] + t.max[c] - i, + transformation.max(c as u8) - (min + (t.max[c] - i)), &mut context, )?, ); - t.min[c] = t.decompacted[i as usize]; + min = t.decompacted[c][i as usize]; } } @@ -55,7 +53,7 @@ impl Transformation for ChannelCompact { } fn min(&self, channel: u8) -> u16 { - self.min[channel as usize] + 0 } fn max(&self, channel: u8) -> u16 { From bcda6a18ee3430c0c03ce2f2d721ce729f121afb Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sat, 21 Oct 2017 23:42:40 -0700 Subject: [PATCH 12/16] fix some more transformation oversights I'm still not too happy with what appears to be an off by one issue with the bounds transformation on the reference image. But I've checked the reference implementation and our calculation matches. It just seems wrong to have a bounds of 1-129. --- src/flif/components/transformations/bounds.rs | 18 +++-- .../transformations/channel_compact.rs | 20 ++--- src/flif/components/transformations/mod.rs | 23 +++--- src/flif/components/transformations/ycocg.rs | 33 +++++--- src/flif/numbers/near_zero.rs | 79 ++----------------- 5 files changed, 63 insertions(+), 110 deletions(-) diff --git a/src/flif/components/transformations/bounds.rs b/src/flif/components/transformations/bounds.rs index 80ca408c..e5663988 100644 --- a/src/flif/components/transformations/bounds.rs +++ b/src/flif/components/transformations/bounds.rs @@ -8,8 +8,8 @@ use error::*; #[derive(Debug)] pub struct Bounds { - min: [u16; 4], - max: [u16; 4], + min: [i16; 4], + max: [i16; 4], } impl Bounds { @@ -25,6 +25,10 @@ impl Bounds { min[c] = rac.read_near_zero(0, trans.max(c as u8) - trans.min(c as u8), &mut context)? + trans.min(c as u8); max[c] = rac.read_near_zero(0, trans.max(c as u8) - min[c], &mut context)? + min[c]; + + // set real min and max + min[c] = ::std::cmp::max(min[c], trans.min(c as u8)); + max[c] = ::std::cmp::min(max[c], trans.max(c as u8)); } Ok(Bounds { min, max }) @@ -32,23 +36,23 @@ impl Bounds { } impl Transformation for Bounds { - fn snap(&self, channel: u8, values: u16, pixel: u16) -> u16 { + fn snap(&self, _channel: u8, _values: i16, _pixel: i16) -> i16 { unimplemented!() } - fn min(&self, channel: u8) -> u16 { + fn min(&self, channel: u8) -> i16 { self.min[channel as usize] } - fn max(&self, channel: u8) -> u16 { + fn max(&self, channel: u8) -> i16 { self.max[channel as usize] } - fn cmin(&self, channel: u8, values: u16) -> u16 { + fn cmin(&self, _channel: u8, _values: i16) -> i16 { unimplemented!() } - fn cmax(&self, channel: u8, values: u16) -> u16 { + fn cmax(&self, _channel: u8, _values: i16) -> i16 { unimplemented!() } } diff --git a/src/flif/components/transformations/channel_compact.rs b/src/flif/components/transformations/channel_compact.rs index e52ade59..c0696e41 100644 --- a/src/flif/components/transformations/channel_compact.rs +++ b/src/flif/components/transformations/channel_compact.rs @@ -3,13 +3,13 @@ use numbers::rac::Rac; use std::io::Read; use numbers::near_zero::NearZeroCoder; use components::header::{Header, SecondHeader}; -use numbers::rac::{ChanceTable, ChanceTableEntry}; +use numbers::rac::ChanceTable; use error::*; #[derive(Debug)] pub struct ChannelCompact { - max: [u16; 4], - decompacted: [Vec; 4], + max: [i16; 4], + decompacted: [Vec; 4], } impl ChannelCompact { pub fn new( @@ -48,23 +48,23 @@ impl ChannelCompact { } impl Transformation for ChannelCompact { - fn snap(&self, channel: u8, values: u16, pixel: u16) -> u16 { + fn snap(&self, _channel: u8, _values: i16, _pixel: i16) -> i16 { unimplemented!() } - fn min(&self, channel: u8) -> u16 { + fn min(&self, _channel: u8) -> i16 { 0 } - fn max(&self, channel: u8) -> u16 { + fn max(&self, channel: u8) -> i16 { self.max[channel as usize] } - fn cmin(&self, channel: u8, values: u16) -> u16 { - unimplemented!() + fn cmin(&self, _channel: u8, _values: i16) -> i16 { + 0 } - fn cmax(&self, channel: u8, values: u16) -> u16 { - unimplemented!() + fn cmax(&self, channel: u8, _values: i16) -> i16 { + self.max[channel as usize] } } diff --git a/src/flif/components/transformations/mod.rs b/src/flif/components/transformations/mod.rs index 195b78a1..9fcff336 100644 --- a/src/flif/components/transformations/mod.rs +++ b/src/flif/components/transformations/mod.rs @@ -13,38 +13,38 @@ mod permute_planes; mod ycocg; pub trait Transformation: ::std::fmt::Debug { - fn snap(&self, channel: u8, values: u16, pixel: u16) -> u16; + fn snap(&self, channel: u8, values: i16, pixel: i16) -> i16; - fn min(&self, channel: u8) -> u16; + fn min(&self, channel: u8) -> i16; - fn max(&self, channel: u8) -> u16; + fn max(&self, channel: u8) -> i16; - fn cmin(&self, channel: u8, values: u16) -> u16; + fn cmin(&self, channel: u8, values: i16) -> i16; - fn cmax(&self, channel: u8, values: u16) -> u16; + fn cmax(&self, channel: u8, values: i16) -> i16; } #[derive(Debug)] struct Orig; impl Transformation for Orig { - fn snap(&self, _channel: u8, _values: u16, pixel: u16) -> u16 { + fn snap(&self, _channel: u8, _values: i16, pixel: i16) -> i16 { pixel } - fn min(&self, _channel: u8) -> u16 { + fn min(&self, _channel: u8) -> i16 { 0 } - fn max(&self, _channel: u8) -> u16 { + fn max(&self, _channel: u8) -> i16 { 255 } - fn cmin(&self, _channel: u8, _values: u16) -> u16 { + fn cmin(&self, _channel: u8, _values: i16) -> i16 { 0 } - fn cmax(&self, _channel: u8, _values: u16) -> u16 { + fn cmax(&self, _channel: u8, _values: i16) -> i16 { 255 } } @@ -63,7 +63,8 @@ pub fn load_transformations( transforms[transforms.len() - 1].as_ref(), (header, second), )?), - 1 => Box::new(YCoGg) as Box, + 1 => Box::new(YCoGg::new(transforms[transforms.len() - 1].as_ref())) + as Box, 4 => Box::new(Bounds::new( rac, transforms[transforms.len() - 1].as_ref(), diff --git a/src/flif/components/transformations/ycocg.rs b/src/flif/components/transformations/ycocg.rs index 1edc0b76..1c712aba 100644 --- a/src/flif/components/transformations/ycocg.rs +++ b/src/flif/components/transformations/ycocg.rs @@ -1,32 +1,45 @@ use super::Transformation; #[derive(Debug)] -pub struct YCoGg; +pub struct YCoGg { + max: i16, +} impl YCoGg { - pub fn new(transformation: &T) -> YCoGg { - YCoGg + pub fn new(transformation: &T) -> YCoGg { + let max_iter = [ + transformation.max(0), + transformation.max(1), + transformation.max(2), + ]; + + let old_max = max_iter.iter().max().unwrap(); + let new_max = (((old_max / 4) + 1) * 4) - 1; + YCoGg { max: new_max } } } impl Transformation for YCoGg { - fn snap(&self, channel: u8, values: u16, pixel: u16) -> u16 { + fn snap(&self, _channel: u8, _values: i16, _pixel: i16) -> i16 { unimplemented!() } - fn min(&self, channel: u8) -> u16 { - 0 + fn min(&self, channel: u8) -> i16 { + match channel { + 0 => 0, + _ => -self.max, + } } - fn max(&self, channel: u8) -> u16 { - 255 + fn max(&self, _channel: u8) -> i16 { + self.max } - fn cmin(&self, channel: u8, values: u16) -> u16 { + fn cmin(&self, _channel: u8, _values: i16) -> i16 { unimplemented!() } - fn cmax(&self, channel: u8, values: u16) -> u16 { + fn cmax(&self, _channel: u8, _values: i16) -> i16 { unimplemented!() } } diff --git a/src/flif/numbers/near_zero.rs b/src/flif/numbers/near_zero.rs index de2e11af..bb399f3d 100644 --- a/src/flif/numbers/near_zero.rs +++ b/src/flif/numbers/near_zero.rs @@ -1,19 +1,12 @@ use std::io::Read; use error::*; -use num_traits::{PrimInt, Signed, Unsigned}; +use num_traits::{PrimInt, Signed}; use numbers::rac::ChanceTable; use numbers::rac::ChanceTableEntry; use numbers::rac::Rac; pub trait NearZeroCoder { - fn read_near_zero( - &mut self, - min: I, - max: I, - context: &mut ChanceTable, - ) -> Result; - - fn read_near_zero_signed( + fn read_near_zero( &mut self, min: I, max: I, @@ -22,74 +15,16 @@ pub trait NearZeroCoder { } impl NearZeroCoder for Rac { - fn read_near_zero( + fn read_near_zero( &mut self, min: I, max: I, context: &mut ChanceTable, ) -> Result { - if min == max { - return Ok(min); + if min > max { + return Err(Error::Unimplemented("something")); } - if self.read(context, ChanceTableEntry::Zero)? { - return Ok(I::zero()); - } - - let largest_exponent = (::std::mem::size_of::() * 8) - max.leading_zeros() as usize - 1; - - let mut exponent = 0; - loop { - if exponent as usize == largest_exponent - || self.read(context, ChanceTableEntry::Exp(exponent, true))? - { - break; - } - - exponent += 1; - } - - // the first mantissa bit is always 1 - let mut have = 1 << exponent; - - // if all other mantissa bits are 1, then the total is have+left - let mut left = have - 1; - - // read mantissa bits from most-significant to least-significant - for pos in (0..exponent).rev() { - left >>= 1; - - // if the bit is 1, then the value will be at least minabs1 - let minabs1 = have | (1 << pos); - // if the bit is 0, then the value will be at most maxabs0 - let maxabs0 = have | left; - if I::from(minabs1).unwrap() > max { - // 1-bit is impossible (would bump value above maximum), - // so assume the bit is 0 without reading it - } else if maxabs0 >= 1 { - // 0-bit and 1-bit are both possible, - // so we read the bit and adjust what we have if it is a 1 - if self.read(context, ChanceTableEntry::Mant(pos))? { - have = minabs1; - } - } else { - // 0-bit is impossible (would make the value zero), - // so assume the bit is 1 without reading it - have = minabs1; - } - } - let have = I::from(have).unwrap(); - Ok(have) - } - - fn read_near_zero_signed( - &mut self, - min: I, - max: I, - context: &mut ChanceTable, - ) -> Result { - assert!(min < max); - if min == max { return Ok(min); } @@ -101,7 +36,7 @@ impl NearZeroCoder for Rac { let sign = if min < I::zero() && max > I::zero() { self.read(context, ChanceTableEntry::Sign)? } else { - min < I::zero() + min >= I::zero() }; let absolute_max = ::std::cmp::max(max, -min); @@ -126,7 +61,7 @@ impl NearZeroCoder for Rac { let mut left = have - 1; // read mantissa bits from most-significant to least-significant - for pos in (exponent - 1)..0 { + for pos in (0..exponent).rev() { left >>= 1; // if the bit is 1, then the value will be at least minabs1 From 57200299fd26168894ff9e89708ea033bf587754 Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sun, 22 Oct 2017 00:03:31 -0700 Subject: [PATCH 13/16] correct invis predictor read --- src/flif/components/header.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/flif/components/header.rs b/src/flif/components/header.rs index 8a541f74..005b8974 100644 --- a/src/flif/components/header.rs +++ b/src/flif/components/header.rs @@ -108,7 +108,7 @@ pub struct SecondHeader { pub alpha_divisor: u8, pub custom_bitchance: bool, pub transformations: Vec>, // Placeholder until transformations are implemented - pub invis_pixel_predictor: u8, + pub invis_pixel_predictor: Option, } impl SecondHeader { @@ -170,13 +170,18 @@ impl SecondHeader { alpha_divisor, custom_bitchance, transformations: Vec::new(), - invis_pixel_predictor: 0, + invis_pixel_predictor: None, }; let transformations = transformations::load_transformations(rac, (&main_header, &second))?; - // TODO: read transformations - let invis_pixel_predictor = rac.read_val(0, 2)?; + + let invis_pixel_predictor = if alpha_zero && main_header.interlaced { + Some(rac.read_val(0, 2)?) + } else { + // Garbage value + None + }; second.transformations = transformations; second.invis_pixel_predictor = invis_pixel_predictor; From bf57ff68c6e8de251f3aad9a667527399ab619cb Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sun, 22 Oct 2017 00:06:03 -0700 Subject: [PATCH 14/16] change large image to have no transformations --- examples/flif_large.flif | Bin 2082 -> 87 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/examples/flif_large.flif b/examples/flif_large.flif index 96988181e1228f216e863c5a432ad3cc75d8ec85..23da1427f41201b5ad115fb7074ec51f6d616dca 100644 GIT binary patch literal 87 zcmV-d0I2^)Oi4yGF@j%$F94?-y45S*uWkSPrugZRTW^amiWixv-R37flU?mc6Rb*I thOv-;0f4;bplPNf2}M;~Y>3SxRz*mB0yZZ1ui{3Sv-uKlF;bqnv1HC7z8zrVXm8 zlop&Z=G8T~beo!d6afq^TTfwu@T7+)0OeE);>%5pp!COeN#{z`!(z;$|`Dpj_I4y5-M1m<3MI zEo@rH#{^KuahFjxKqEpaDI_DQyz_L>5pF3Y($E***|8uvKDbZ(LQAH}h7dqIk+w;z z80Ljo>rt9At`cm%ao}Lfn-_ZwYDeRrpg@&ms}MvM4AooM?!oLUQc$Agt$e!Vy&)04 zFCV>)(!cCID#|As5{$+tmwtO|WYwk-+$%j?@W<}@RQ$TWw=pDZI4eA>4fQQ35>&^M zS3p`4s^pGmod%2;U_$?f^R4!qi1n!)Qkr7%_ZrNlsaL2>`;~Tt1$TlWOW|l4Q*L>N z-QultMzDNU#b()glk}GRR%wPy3hCZ98B6=92Ba9W(MBY*TuggCUkralgb`#T#S`9& z8NHImkdY%_ulsb)D&`LIh0|qVL+k&;I9rnealj!gPOuUvdLTV|mobkvBt!-dbTY$n zWmZE)(59t!7SK9Am}e);O#o_JlDdFOhM(O=#i*{`-qJTLoYd)aghSSBtok#_=k?-# zY@5sYW3vwW3`0$WzOip(ap?+Zt& zYAPK4EauW^W}$y0c!k}-(Xwn#4DxBPDaJGOfkxm2&aT-S4t<4_drOcoYfW@Ol&{>j zLH+HJ7CiWe^Z!Bm5USbCZQdz6;jJ~uV$-if%VLGr5vd{j${ys&KcKP}ch8Y;bE z0$4XWJ@LUunZsro(;F-wHB`g1$dJAWjB(dN{wHouDrBwr)ck4(bARd^i3QcS&qF2BC42dIGbxu^p92~n%0^8IUYF$ zGkn%fd-8*!o$00hjtjyew)tA{dP7gHwkMtvk8>eDdfHM_pvaWW#EDVv=GIT#xje5w zxd1h5@zk&~-@vnx(PTU%R(hd-J465f>1abc-7E9qT>qC!dxjrDEIR-HJ6=L;{4Ffx z|CeYBR(b<_T>sq`!*e$QDZl^iZ!p#_TFb&>{J`K+IO%WPZ`nEA09){e`shKmh{FH* z|KP>=A8X_MlEdH&>>+H{a6)a07)BrP17zrDnO$On3&)xfx7rH3``=zyVpfB^-M>8Y*PLF}m#Zg`lQ`3% zggUR+3gcCkpl*s;Z2D@lF0-EIzC=~(lKUtdtzxv8ww@44D_gA@4gxRYg5Is~ZAw40 zpRs!G7t!pzt8OQ+t2mmLmijV*t3Qfg_|AmE^_8TK=?$wTb$(LAmmuzl*7|Jb|2DJNRK7PP0r!A0ozHy_DRLOrm_W z=7(3bDH|*1Np@`%#FQ%zM)#c$RxI&sfrvT|d#d8*HVfe~8hCl8VhYABayAGrf1BEd zu8<>yi~33};eY^oMQ9ydCj0tpZE&MOAWJcW+rn)6pVbIagUskLcZ)xEHA<*_g^|3x z9=;_FmM)1o(>KB=VvmLlAQ?$g_mpwGiT;>1suvxx=ut``)RJ-$kiFpz%nEM(@73(W zrGs4Ny4(>e2)Vpbo+W*%63GzlGA&wz=!W%I^Ne6OF0p z1h4E3Kks#%C_vuY3el_qHRwDO5F@_}3qpu(#>iL!Ccb4*n4ePN5JZJz!(=$fNms&r z;*~iI;Oy!ug0)|{?D?~RZu1R(Fm^$axb&4qw{O zC5Js4@T=?V>h1%IqT>HxJemc#YVEx9B8+K;U5S6Eb9=xoccPI;j9w%{lQygN*1PZ|NsBrcD;m%vhq0wF;nR-98+`u|KsGM z5KX>8(r*9%|Np&w3IN8BcHJP*8feJNApigUTtq&k)!Dy;P5=M;yMmFU)VV8Ldx_{r z7I**u{&^F~HhN7%e#ig+|G{(0sO$x8QC9!zYUlt!YF|AlMI%? Date: Sun, 22 Oct 2017 00:25:25 -0700 Subject: [PATCH 15/16] sort use statements --- src/flif/components/header.rs | 2 +- src/flif/components/transformations/bounds.rs | 8 ++++---- src/flif/components/transformations/channel_compact.rs | 8 ++++---- src/flif/components/transformations/mod.rs | 7 +++---- src/flif/numbers/rac.rs | 4 ++-- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/flif/components/header.rs b/src/flif/components/header.rs index 005b8974..7da18a40 100644 --- a/src/flif/components/header.rs +++ b/src/flif/components/header.rs @@ -1,8 +1,8 @@ use std::io::Read; use error::*; use numbers::FlifReadExt; -use numbers::symbol::UniformSymbolCoder; use numbers::rac::Rac; +use numbers::symbol::UniformSymbolCoder; use super::transformations; use super::transformations::Transformation; diff --git a/src/flif/components/transformations/bounds.rs b/src/flif/components/transformations/bounds.rs index e5663988..ee119b97 100644 --- a/src/flif/components/transformations/bounds.rs +++ b/src/flif/components/transformations/bounds.rs @@ -1,10 +1,10 @@ -use super::Transformation; -use numbers::rac::Rac; use std::io::Read; -use numbers::near_zero::NearZeroCoder; use components::header::{Header, SecondHeader}; -use numbers::rac::ChanceTable; use error::*; +use numbers::near_zero::NearZeroCoder; +use numbers::rac::ChanceTable; +use numbers::rac::Rac; +use super::Transformation; #[derive(Debug)] pub struct Bounds { diff --git a/src/flif/components/transformations/channel_compact.rs b/src/flif/components/transformations/channel_compact.rs index c0696e41..a17ffa64 100644 --- a/src/flif/components/transformations/channel_compact.rs +++ b/src/flif/components/transformations/channel_compact.rs @@ -1,10 +1,10 @@ -use super::Transformation; -use numbers::rac::Rac; use std::io::Read; -use numbers::near_zero::NearZeroCoder; use components::header::{Header, SecondHeader}; -use numbers::rac::ChanceTable; use error::*; +use numbers::near_zero::NearZeroCoder; +use numbers::rac::ChanceTable; +use numbers::rac::Rac; +use super::Transformation; #[derive(Debug)] pub struct ChannelCompact { diff --git a/src/flif/components/transformations/mod.rs b/src/flif/components/transformations/mod.rs index 9fcff336..9e026f95 100644 --- a/src/flif/components/transformations/mod.rs +++ b/src/flif/components/transformations/mod.rs @@ -1,15 +1,14 @@ -use numbers::rac::Rac; use std::io::Read; -use numbers::symbol::UniformSymbolCoder; use components::header::{Header, SecondHeader}; -use self::channel_compact::ChannelCompact; use error::*; +use numbers::rac::Rac; +use numbers::symbol::UniformSymbolCoder; +use self::channel_compact::ChannelCompact; use self::bounds::Bounds; use self::ycocg::YCoGg; mod bounds; mod channel_compact; -mod permute_planes; mod ycocg; pub trait Transformation: ::std::fmt::Debug { diff --git a/src/flif/numbers/rac.rs b/src/flif/numbers/rac.rs index 8b954ce5..4f9adcc3 100644 --- a/src/flif/numbers/rac.rs +++ b/src/flif/numbers/rac.rs @@ -1,7 +1,7 @@ -use std::io::Write; use std::collections::HashMap; -use std::io::Read; use std::io; +use std::io::Read; +use std::io::Write; use error::*; use super::FlifReadExt; From 31328f8db1f059f2dcd6e2cb11407d771258d393 Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sun, 22 Oct 2017 00:25:32 -0700 Subject: [PATCH 16/16] remove permute_planes --- src/flif/components/transformations/permute_planes.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/flif/components/transformations/permute_planes.rs diff --git a/src/flif/components/transformations/permute_planes.rs b/src/flif/components/transformations/permute_planes.rs deleted file mode 100644 index e69de29b..00000000