1 use crate::color::Rgb;
2 use crate::error::ImageResult;
3 use crate::hdr::{rgbe8, RGBE8Pixel, SIGNATURE};
4 use std::io::{Result, Write};
5 use std::cmp::Ordering;
6 
7 /// Radiance HDR encoder
8 pub struct HDREncoder<W: Write> {
9     w: W,
10 }
11 
12 impl<W: Write> HDREncoder<W> {
13     /// Creates encoder
new(w: W) -> HDREncoder<W>14     pub fn new(w: W) -> HDREncoder<W> {
15         HDREncoder { w }
16     }
17 
18     /// Encodes the image ```data```
19     /// that has dimensions ```width``` and ```height```
encode(mut self, data: &[Rgb<f32>], width: usize, height: usize) -> ImageResult<()>20     pub fn encode(mut self, data: &[Rgb<f32>], width: usize, height: usize) -> ImageResult<()> {
21         assert!(data.len() >= width * height);
22         let w = &mut self.w;
23         w.write_all(SIGNATURE)?;
24         w.write_all(b"\n")?;
25         w.write_all(b"# Rust HDR encoder\n")?;
26         w.write_all(b"FORMAT=32-bit_rle_rgbe\n\n")?;
27         w.write_all(format!("-Y {} +X {}\n", height, width).as_bytes())?;
28 
29         if width < 8 || width > 32_768 {
30             for &pix in data {
31                 write_rgbe8(w, to_rgbe8(pix))?;
32             }
33         } else {
34             // new RLE marker contains scanline width
35             let marker = rgbe8(2, 2, (width / 256) as u8, (width % 256) as u8);
36             // buffers for encoded pixels
37             let mut bufr = vec![0; width];
38             let mut bufg = vec![0; width];
39             let mut bufb = vec![0; width];
40             let mut bufe = vec![0; width];
41             let mut rle_buf = vec![0; width];
42             for scanline in data.chunks(width) {
43                 for ((((r, g), b), e), &pix) in bufr.iter_mut()
44                     .zip(bufg.iter_mut())
45                     .zip(bufb.iter_mut())
46                     .zip(bufe.iter_mut())
47                     .zip(scanline.iter())
48                 {
49                     let cp = to_rgbe8(pix);
50                     *r = cp.c[0];
51                     *g = cp.c[1];
52                     *b = cp.c[2];
53                     *e = cp.e;
54                 }
55                 write_rgbe8(w, marker)?; // New RLE encoding marker
56                 rle_buf.clear();
57                 rle_compress(&bufr[..], &mut rle_buf);
58                 w.write_all(&rle_buf[..])?;
59                 rle_buf.clear();
60                 rle_compress(&bufg[..], &mut rle_buf);
61                 w.write_all(&rle_buf[..])?;
62                 rle_buf.clear();
63                 rle_compress(&bufb[..], &mut rle_buf);
64                 w.write_all(&rle_buf[..])?;
65                 rle_buf.clear();
66                 rle_compress(&bufe[..], &mut rle_buf);
67                 w.write_all(&rle_buf[..])?;
68             }
69         }
70         Ok(())
71     }
72 }
73 
74 #[derive(Debug, PartialEq, Eq)]
75 enum RunOrNot {
76     Run(u8, usize),
77     Norun(usize, usize),
78 }
79 use self::RunOrNot::{Norun, Run};
80 
81 const RUN_MAX_LEN: usize = 127;
82 const NORUN_MAX_LEN: usize = 128;
83 
84 struct RunIterator<'a> {
85     data: &'a [u8],
86     curidx: usize,
87 }
88 
89 impl<'a> RunIterator<'a> {
new(data: &'a [u8]) -> RunIterator<'a>90     fn new(data: &'a [u8]) -> RunIterator<'a> {
91         RunIterator { data, curidx: 0 }
92     }
93 }
94 
95 impl<'a> Iterator for RunIterator<'a> {
96     type Item = RunOrNot;
97 
next(&mut self) -> Option<Self::Item>98     fn next(&mut self) -> Option<Self::Item> {
99         if self.curidx == self.data.len() {
100             None
101         } else {
102             let cv = self.data[self.curidx];
103             let crun = self.data[self.curidx..]
104                 .iter()
105                 .take_while(|&&v| v == cv)
106                 .take(RUN_MAX_LEN)
107                 .count();
108             let ret = if crun > 2 {
109                 Run(cv, crun)
110             } else {
111                 Norun(self.curidx, crun)
112             };
113             self.curidx += crun;
114             Some(ret)
115         }
116     }
117 }
118 
119 struct NorunCombineIterator<'a> {
120     runiter: RunIterator<'a>,
121     prev: Option<RunOrNot>,
122 }
123 
124 impl<'a> NorunCombineIterator<'a> {
new(data: &'a [u8]) -> NorunCombineIterator<'a>125     fn new(data: &'a [u8]) -> NorunCombineIterator<'a> {
126         NorunCombineIterator {
127             runiter: RunIterator::new(data),
128             prev: None,
129         }
130     }
131 }
132 
133 // Combines sequential noruns produced by RunIterator
134 impl<'a> Iterator for NorunCombineIterator<'a> {
135     type Item = RunOrNot;
next(&mut self) -> Option<Self::Item>136     fn next(&mut self) -> Option<Self::Item> {
137         loop {
138             match self.prev.take() {
139                 Some(Run(c, len)) => {
140                     // Just return stored run
141                     return Some(Run(c, len));
142                 }
143                 Some(Norun(idx, len)) => {
144                     // Let's see if we need to continue norun
145                     match self.runiter.next() {
146                         Some(Norun(_, len1)) => {
147                             // norun continues
148                             let clen = len + len1; // combined length
149                             match clen.cmp(&NORUN_MAX_LEN) {
150                                 Ordering::Equal => return Some(Norun(idx, clen)),
151                                 Ordering::Greater => {
152                                     // combined norun exceeds maximum length. store extra part of norun
153                                     self.prev = Some(Norun(idx + NORUN_MAX_LEN, clen - NORUN_MAX_LEN));
154                                     // then return maximal norun
155                                     return Some(Norun(idx, NORUN_MAX_LEN));
156                                 }
157                                 Ordering::Less => {
158                                     // len + len1 < NORUN_MAX_LEN
159                                     self.prev = Some(Norun(idx, len + len1));
160                                     // combine and continue loop
161                                 }
162                             }
163                         }
164                         Some(Run(c, len1)) => {
165                             // Run encountered. Store it
166                             self.prev = Some(Run(c, len1));
167                             return Some(Norun(idx, len)); // and return combined norun
168                         }
169                         None => {
170                             // End of sequence
171                             return Some(Norun(idx, len)); // return combined norun
172                         }
173                     }
174                 } // End match self.prev.take() == Some(NoRun())
175                 None => {
176                     // No norun to combine
177                     match self.runiter.next() {
178                         Some(Norun(idx, len)) => {
179                             self.prev = Some(Norun(idx, len));
180                             // store for combine and continue the loop
181                         }
182                         Some(Run(c, len)) => {
183                             // Some run. Just return it
184                             return Some(Run(c, len));
185                         }
186                         None => {
187                             // That's all, folks
188                             return None;
189                         }
190                     }
191                 } // End match self.prev.take() == None
192             } // End match
193         } // End loop
194     }
195 }
196 
197 // Appends RLE compressed ```data``` to ```rle```
rle_compress(data: &[u8], rle: &mut Vec<u8>)198 fn rle_compress(data: &[u8], rle: &mut Vec<u8>) {
199     rle.clear();
200     if data.is_empty() {
201         rle.push(0); // Technically correct. It means read next 0 bytes.
202         return;
203     }
204     // Task: split data into chunks of repeating (max 127) and non-repeating bytes (max 128)
205     // Prepend non-repeating chunk with its length
206     // Replace repeating byte with (run length + 128) and the byte
207     for rnr in NorunCombineIterator::new(data) {
208         match rnr {
209             Run(c, len) => {
210                 assert!(len <= 127);
211                 rle.push(128u8 + len as u8);
212                 rle.push(c);
213             }
214             Norun(idx, len) => {
215                 assert!(len <= 128);
216                 rle.push(len as u8);
217                 rle.extend_from_slice(&data[idx..idx + len]);
218             }
219         }
220     }
221 }
222 
write_rgbe8<W: Write>(w: &mut W, v: RGBE8Pixel) -> Result<()>223 fn write_rgbe8<W: Write>(w: &mut W, v: RGBE8Pixel) -> Result<()> {
224     w.write_all(&[v.c[0], v.c[1], v.c[2], v.e])
225 }
226 
227 /// Converts ```Rgb<f32>``` into ```RGBE8Pixel```
to_rgbe8(pix: Rgb<f32>) -> RGBE8Pixel228 pub fn to_rgbe8(pix: Rgb<f32>) -> RGBE8Pixel {
229     let pix = pix.0;
230     let mx = f32::max(pix[0], f32::max(pix[1], pix[2]));
231     if mx <= 0.0 {
232         RGBE8Pixel { c: [0, 0, 0], e: 0 }
233     } else {
234         // let (frac, exp) = mx.frexp(); // unstable yet
235         let exp = mx.log2().floor() as i32 + 1;
236         let mul = f32::powi(2.0, exp);
237         let mut conv = [0u8; 3];
238         for (cv, &sv) in conv.iter_mut().zip(pix.iter()) {
239             *cv = f32::trunc(sv / mul * 256.0) as u8;
240         }
241         RGBE8Pixel {
242             c: conv,
243             e: (exp + 128) as u8,
244         }
245     }
246 }
247 
248 #[test]
to_rgbe8_test()249 fn to_rgbe8_test() {
250     use crate::hdr::rgbe8;
251     let test_cases = vec![rgbe8(0, 0, 0, 0), rgbe8(1, 1, 128, 128)];
252     for &pix in &test_cases {
253         assert_eq!(pix, to_rgbe8(pix.to_hdr()));
254     }
255     for mc in 128..255 {
256         // TODO: use inclusive range when stable
257         let pix = rgbe8(mc, mc, mc, 100);
258         assert_eq!(pix, to_rgbe8(pix.to_hdr()));
259         let pix = rgbe8(mc, 0, mc, 130);
260         assert_eq!(pix, to_rgbe8(pix.to_hdr()));
261         let pix = rgbe8(0, 0, mc, 140);
262         assert_eq!(pix, to_rgbe8(pix.to_hdr()));
263         let pix = rgbe8(1, 0, mc, 150);
264         assert_eq!(pix, to_rgbe8(pix.to_hdr()));
265         let pix = rgbe8(1, mc, 10, 128);
266         assert_eq!(pix, to_rgbe8(pix.to_hdr()));
267         for c in 0..255 {
268             // Radiance HDR seems to be pre IEEE 754.
269             // exponent can be -128 (represented as 0u8), so some colors cannot be represented in normalized f32
270             // Let's exclude exponent value of -128 (0u8) from testing
271             let pix = rgbe8(1, mc, c, if c == 0 { 1 } else { c });
272             assert_eq!(pix, to_rgbe8(pix.to_hdr()));
273         }
274     }
275     fn relative_dist(a: Rgb<f32>, b: Rgb<f32>) -> f32 {
276         // maximal difference divided by maximal value
277         let max_diff = a.0
278             .iter()
279             .zip(b.0.iter())
280             .fold(0.0, |diff, (&a, &b)| f32::max(diff, (a - b).abs()));
281         let max_val = a.0
282             .iter()
283             .chain(b.0.iter())
284             .fold(0.0, |maxv, &a| f32::max(maxv, a));
285         if max_val == 0.0 {
286             0.0
287         } else {
288             max_diff / max_val
289         }
290     }
291     let test_values = vec![
292         0.000_001, 0.000_02, 0.000_3, 0.004, 0.05, 0.6, 7.0, 80.0, 900.0, 1_000.0, 20_000.0,
293         300_000.0,
294     ];
295     for &r in &test_values {
296         for &g in &test_values {
297             for &b in &test_values {
298                 let c1 = Rgb([r, g, b]);
299                 let c2 = to_rgbe8(c1).to_hdr();
300                 let rel_dist = relative_dist(c1, c2);
301                 // Maximal value is normalized to the range 128..256, thus we have 1/128 precision
302                 assert!(
303                     rel_dist <= 1.0 / 128.0,
304                     "Relative distance ({}) exceeds 1/128 for {:?} and {:?}",
305                     rel_dist,
306                     c1,
307                     c2
308                 );
309             }
310         }
311     }
312 }
313 
314 #[test]
runiterator_test()315 fn runiterator_test() {
316     let data = [];
317     let mut run_iter = RunIterator::new(&data[..]);
318     assert_eq!(run_iter.next(), None);
319     let data = [5];
320     let mut run_iter = RunIterator::new(&data[..]);
321     assert_eq!(run_iter.next(), Some(Norun(0, 1)));
322     assert_eq!(run_iter.next(), None);
323     let data = [1, 1];
324     let mut run_iter = RunIterator::new(&data[..]);
325     assert_eq!(run_iter.next(), Some(Norun(0, 2)));
326     assert_eq!(run_iter.next(), None);
327     let data = [0, 0, 0];
328     let mut run_iter = RunIterator::new(&data[..]);
329     assert_eq!(run_iter.next(), Some(Run(0u8, 3)));
330     assert_eq!(run_iter.next(), None);
331     let data = [0, 0, 1, 1];
332     let mut run_iter = RunIterator::new(&data[..]);
333     assert_eq!(run_iter.next(), Some(Norun(0, 2)));
334     assert_eq!(run_iter.next(), Some(Norun(2, 2)));
335     assert_eq!(run_iter.next(), None);
336     let data = [0, 0, 0, 1, 1];
337     let mut run_iter = RunIterator::new(&data[..]);
338     assert_eq!(run_iter.next(), Some(Run(0u8, 3)));
339     assert_eq!(run_iter.next(), Some(Norun(3, 2)));
340     assert_eq!(run_iter.next(), None);
341     let data = [1, 2, 2, 2];
342     let mut run_iter = RunIterator::new(&data[..]);
343     assert_eq!(run_iter.next(), Some(Norun(0, 1)));
344     assert_eq!(run_iter.next(), Some(Run(2u8, 3)));
345     assert_eq!(run_iter.next(), None);
346     let data = [1, 1, 2, 2, 2];
347     let mut run_iter = RunIterator::new(&data[..]);
348     assert_eq!(run_iter.next(), Some(Norun(0, 2)));
349     assert_eq!(run_iter.next(), Some(Run(2u8, 3)));
350     assert_eq!(run_iter.next(), None);
351     let data = [2; 128];
352     let mut run_iter = RunIterator::new(&data[..]);
353     assert_eq!(run_iter.next(), Some(Run(2u8, 127)));
354     assert_eq!(run_iter.next(), Some(Norun(127, 1)));
355     assert_eq!(run_iter.next(), None);
356     let data = [2; 129];
357     let mut run_iter = RunIterator::new(&data[..]);
358     assert_eq!(run_iter.next(), Some(Run(2u8, 127)));
359     assert_eq!(run_iter.next(), Some(Norun(127, 2)));
360     assert_eq!(run_iter.next(), None);
361     let data = [2; 130];
362     let mut run_iter = RunIterator::new(&data[..]);
363     assert_eq!(run_iter.next(), Some(Run(2u8, 127)));
364     assert_eq!(run_iter.next(), Some(Run(2u8, 3)));
365     assert_eq!(run_iter.next(), None);
366 }
367 
368 #[test]
noruncombine_test()369 fn noruncombine_test() {
370     fn a<T>(mut v: Vec<T>, mut other: Vec<T>) -> Vec<T> {
371         v.append(&mut other);
372         v
373     }
374 
375     let v = vec![];
376     let mut rsi = NorunCombineIterator::new(&v[..]);
377     assert_eq!(rsi.next(), None);
378 
379     let v = vec![1];
380     let mut rsi = NorunCombineIterator::new(&v[..]);
381     assert_eq!(rsi.next(), Some(Norun(0, 1)));
382     assert_eq!(rsi.next(), None);
383 
384     let v = vec![2, 2];
385     let mut rsi = NorunCombineIterator::new(&v[..]);
386     assert_eq!(rsi.next(), Some(Norun(0, 2)));
387     assert_eq!(rsi.next(), None);
388 
389     let v = vec![3, 3, 3];
390     let mut rsi = NorunCombineIterator::new(&v[..]);
391     assert_eq!(rsi.next(), Some(Run(3, 3)));
392     assert_eq!(rsi.next(), None);
393 
394     let v = vec![4, 4, 3, 3, 3];
395     let mut rsi = NorunCombineIterator::new(&v[..]);
396     assert_eq!(rsi.next(), Some(Norun(0, 2)));
397     assert_eq!(rsi.next(), Some(Run(3, 3)));
398     assert_eq!(rsi.next(), None);
399 
400     let v = vec![40; 400];
401     let mut rsi = NorunCombineIterator::new(&v[..]);
402     assert_eq!(rsi.next(), Some(Run(40, 127)));
403     assert_eq!(rsi.next(), Some(Run(40, 127)));
404     assert_eq!(rsi.next(), Some(Run(40, 127)));
405     assert_eq!(rsi.next(), Some(Run(40, 19)));
406     assert_eq!(rsi.next(), None);
407 
408     let v = a(a(vec![5; 3], vec![6; 129]), vec![7, 3, 7, 10, 255]);
409     let mut rsi = NorunCombineIterator::new(&v[..]);
410     assert_eq!(rsi.next(), Some(Run(5, 3)));
411     assert_eq!(rsi.next(), Some(Run(6, 127)));
412     assert_eq!(rsi.next(), Some(Norun(130, 7)));
413     assert_eq!(rsi.next(), None);
414 
415     let v = a(a(vec![5; 2], vec![6; 129]), vec![7, 3, 7, 7, 255]);
416     let mut rsi = NorunCombineIterator::new(&v[..]);
417     assert_eq!(rsi.next(), Some(Norun(0, 2)));
418     assert_eq!(rsi.next(), Some(Run(6, 127)));
419     assert_eq!(rsi.next(), Some(Norun(129, 7)));
420     assert_eq!(rsi.next(), None);
421 
422     let v: Vec<_> = ::std::iter::repeat(())
423         .flat_map(|_| (0..2))
424         .take(257)
425         .collect();
426     let mut rsi = NorunCombineIterator::new(&v[..]);
427     assert_eq!(rsi.next(), Some(Norun(0, 128)));
428     assert_eq!(rsi.next(), Some(Norun(128, 128)));
429     assert_eq!(rsi.next(), Some(Norun(256, 1)));
430     assert_eq!(rsi.next(), None);
431 }
432