ricecomp/
read.rs

1use std::ffi::{c_uchar, c_uint, c_ushort};
2
3use crate::log_noop;
4
5/// nonzero_count is lookup table giving number of bits in 8-bit values not including
6/// leading zeros used in fits_rdecomp, fits_rdecomp_short and fits_rdecomp_byte
7const NONZERO_COUNT: [i32; 256] = [
8    0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
9    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
10    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
11    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
12    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
13    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
14    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
15    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
16];
17
18#[derive(Debug)]
19pub enum DecodeError {
20    EndOfBuffer,
21    ZeroSizeInput,
22    NotProperlyAllocated,
23}
24
25pub struct RCDecoder {
26    log_fn: fn(&str),
27}
28
29impl Default for RCDecoder {
30    fn default() -> Self {
31        Self::new()
32    }
33}
34
35impl RCDecoder {
36    pub fn new() -> RCDecoder {
37        RCDecoder { log_fn: log_noop }
38    }
39
40    pub fn set_log_fn(&mut self, log_fn: fn(&str)) {
41        self.log_fn = log_fn;
42    }
43
44    pub fn decode(
45        &self,
46        input: &[u8], /* input buffer			*/
47        nx: usize,    /* number of output pixels	*/
48        nblock: usize,
49        output: &mut [c_uint],
50    ) -> Result<(), DecodeError> /* coding block size		*/ {
51        /* int bsize;  */
52
53        let mut k: i32;
54        let mut imax: usize;
55
56        let mut nzero: i32;
57        let mut fs: i32;
58
59        let mut diff: u32;
60
61        assert_eq!(output.len(), nx);
62        output.fill(0);
63
64        /*
65         * Original size of each pixel (bsize, bytes) and coding block
66         * size (nblock, pixels)
67         * Could make bsize a parameter to allow more efficient
68         * compression of short & byte images.
69         */
70        /*    bsize = 4; */
71
72        /*
73         * From bsize derive:
74         * FSBITS = # bits required to store FS
75         * FSMAX = maximum value for FS
76         * BBITS = bits/pixel for direct coding
77         */
78
79        /* move out of switch block, to tweak performance */
80        let fsbits: i32 = 5;
81        let fsmax: i32 = 25;
82
83        let bbits: i32 = 1 << fsbits;
84
85        /*
86         * Decode in blocks of nblock pixels
87         */
88
89        /* first 4 bytes of input buffer contain the value of the first */
90        /* 4 byte integer value, without any encoding */
91
92        if (input.len() < 4) {
93            (self.log_fn)("decompression error: input buffer not properly allocated");
94            return Err(DecodeError::NotProperlyAllocated);
95        }
96
97        let mut lastpix: u32 = 0;
98        let mut bytevalue: u8 = input[0];
99        lastpix |= (bytevalue as u32) << 24;
100        bytevalue = input[1];
101        lastpix |= (bytevalue as u32) << 16;
102        bytevalue = input[2];
103        lastpix |= (bytevalue as u32) << 8;
104        bytevalue = input[3];
105        lastpix |= bytevalue as u32;
106
107        let mut c_current: usize = 4;
108
109        // cend = c + clen - 4;
110
111        let mut b: u32 = input[c_current] as u32; /* bit buffer			*/
112        c_current += 1;
113        let mut nbits: i32 = 8; /* number of bits remaining in b	*/
114
115        let mut i: usize = 0;
116        while i < nx {
117            /* get the FS value from first fsbits */
118            nbits -= fsbits;
119            while nbits < 0 {
120                b = (b << 8) | input[c_current] as u32;
121                c_current += 1;
122                nbits += 8;
123            }
124            fs = ((b >> nbits).wrapping_sub(1)) as i32;
125
126            b &= (1 << nbits) - 1;
127            /* loop over the next block */
128            imax = i + nblock;
129            if imax > nx {
130                imax = nx;
131            }
132            if fs < 0 {
133                /* low-entropy case, all zero differences */
134                while i < imax {
135                    output[i] = lastpix;
136                    i += 1;
137                }
138            } else if fs == fsmax {
139                /* high-entropy case, directly coded pixel values */
140                while i < imax {
141                    k = bbits - nbits;
142                    diff = b.wrapping_shl(k as u32);
143                    k -= 8;
144                    while k >= 0 {
145                        b = input[c_current] as u32;
146                        c_current += 1;
147                        diff |= b << k;
148                        k -= 8
149                    }
150                    if nbits > 0 {
151                        b = input[c_current] as u32;
152                        c_current += 1;
153                        diff |= b >> (-k);
154                        b &= (1 << nbits) - 1;
155                    } else {
156                        b = 0;
157                    }
158                    /*
159                     * undo mapping and differencing
160                     * Note that some of these operations will overflow the
161                     * unsigned int arithmetic -- that's OK, it all works
162                     * out to give the right answers in the output file.
163                     */
164                    if (diff & 1) == 0 {
165                        diff >>= 1;
166                    } else {
167                        diff = !(diff >> 1);
168                    }
169                    output[i] = diff.wrapping_add(lastpix);
170                    lastpix = output[i];
171                    i += 1;
172                }
173            } else {
174                /* normal case, Rice coding */
175                while i < imax {
176                    /* count number of leading zeros */
177                    while b == 0 {
178                        nbits += 8;
179
180                        b = input[c_current] as u32;
181                        c_current += 1;
182                    }
183                    nzero = nbits - NONZERO_COUNT[b as usize];
184                    nbits -= nzero + 1;
185                    /* flip the leading one-bit */
186                    b ^= 1 << nbits;
187                    /* get the FS trailing bits */
188                    nbits -= fs;
189                    while nbits < 0 {
190                        b = (b << 8) | (input[c_current] as u32);
191
192                        c_current += 1;
193                        nbits += 8;
194                    }
195                    diff = ((nzero as u32) << fs) | (b >> nbits);
196                    b &= (1 << nbits) - 1;
197
198                    /* undo mapping and differencing */
199                    if (diff & 1) == 0 {
200                        diff >>= 1;
201                    } else {
202                        diff = !(diff >> 1);
203                    }
204                    output[i] = diff.wrapping_add(lastpix);
205                    lastpix = output[i];
206                    i += 1;
207                }
208            }
209            if c_current > input.len() {
210                (self.log_fn)("decompression error: hit end of compressed byte stream");
211                return Err(DecodeError::EndOfBuffer);
212            }
213        }
214        if c_current < input.len() {
215            (self.log_fn)("decompression warning: unused bytes at end of compressed buffer");
216        }
217
218        Ok(())
219    }
220
221    pub fn decode_short(
222        &self,
223        input: &[u8], /* input buffer			*/
224        nx: usize,    /* number of output pixels	*/
225        nblock: usize,
226        output: &mut [c_ushort],
227    ) -> Result<(), DecodeError> /* coding block size		*/ {
228        /* int bsize;  */
229
230        let mut k: i32;
231        let mut imax: usize;
232
233        let mut nzero: i32;
234        let mut fs: i32;
235
236        let mut diff: u32;
237
238        assert_eq!(output.len(), nx);
239        output.fill(0);
240
241        /*
242         * Original size of each pixel (bsize, bytes) and coding block
243         * size (nblock, pixels)
244         * Could make bsize a parameter to allow more efficient
245         * compression of short & byte images.
246         */
247        /*    bsize = 2; */
248
249        /*
250         * From bsize derive:
251         * FSBITS = # bits required to store FS
252         * FSMAX = maximum value for FS
253         * BBITS = bits/pixel for direct coding
254         */
255
256        /* move out of switch block, to tweak performance */
257        let fsbits: i32 = 4;
258        let fsmax: i32 = 14;
259
260        let bbits: i32 = 1 << fsbits;
261
262        /*
263         * Decode in blocks of nblock pixels
264         */
265
266        /* first 2 bytes of input buffer contain the value of the first */
267        /* 2 byte integer value, without any encoding */
268
269        let mut lastpix: u32 = 0;
270        let mut bytevalue: u8 = input[0];
271        lastpix |= (bytevalue as u32) << 8;
272        bytevalue = input[1];
273        lastpix |= bytevalue as u32;
274
275        let mut c_current: usize = 2;
276
277        // cend = c + clen - 2;
278
279        let mut b: u32 = input[c_current] as u32; /* bit buffer			*/
280        c_current += 1;
281        let mut nbits: i32 = 8; /* number of bits remaining in b	*/
282
283        let mut i: usize = 0;
284        while i < nx {
285            /* get the FS value from first fsbits */
286            nbits -= fsbits;
287            while nbits < 0 {
288                b = (b << 8) | input[c_current] as u32;
289                c_current += 1;
290                nbits += 8;
291            }
292            fs = ((b >> nbits).wrapping_sub(1)) as i32;
293
294            b &= (1 << nbits) - 1;
295            /* loop over the next block */
296            imax = i + nblock;
297            if imax > nx {
298                imax = nx;
299            }
300            if fs < 0 {
301                /* low-entropy case, all zero differences */
302                while i < imax {
303                    output[i] = lastpix as c_ushort;
304                    i += 1;
305                }
306            } else if fs == fsmax {
307                /* high-entropy case, directly coded pixel values */
308                while i < imax {
309                    k = bbits - nbits;
310                    diff = b.wrapping_shl(k as u32);
311                    k -= 8;
312                    while k >= 0 {
313                        b = input[c_current] as u32;
314                        c_current += 1;
315                        diff |= b << k;
316                        k -= 8
317                    }
318                    if nbits > 0 {
319                        b = input[c_current] as u32;
320                        c_current += 1;
321                        diff |= b >> (-k);
322                        b &= (1 << nbits) - 1;
323                    } else {
324                        b = 0;
325                    }
326                    /*
327                     * undo mapping and differencing
328                     * Note that some of these operations will overflow the
329                     * unsigned int arithmetic -- that's OK, it all works
330                     * out to give the right answers in the output file.
331                     */
332                    if (diff & 1) == 0 {
333                        diff >>= 1;
334                    } else {
335                        diff = !(diff >> 1);
336                    }
337                    output[i] = diff.wrapping_add(lastpix) as c_ushort;
338                    lastpix = output[i] as u32;
339                    i += 1;
340                }
341            } else {
342                /* normal case, Rice coding */
343                while i < imax {
344                    /* count number of leading zeros */
345                    while b == 0 {
346                        nbits += 8;
347
348                        b = input[c_current] as u32;
349                        c_current += 1;
350                    }
351                    nzero = nbits - NONZERO_COUNT[b as usize];
352                    nbits -= nzero + 1;
353                    /* flip the leading one-bit */
354                    b ^= 1 << nbits;
355                    /* get the FS trailing bits */
356                    nbits -= fs;
357                    while nbits < 0 {
358                        b = (b << 8) | (input[c_current] as u32);
359
360                        c_current += 1;
361                        nbits += 8;
362                    }
363                    diff = ((nzero as u32) << fs) | (b >> nbits);
364                    b &= (1 << nbits) - 1;
365
366                    /* undo mapping and differencing */
367                    if (diff & 1) == 0 {
368                        diff >>= 1;
369                    } else {
370                        diff = !(diff >> 1);
371                    }
372                    output[i] = diff.wrapping_add(lastpix) as c_ushort;
373                    lastpix = output[i] as u32;
374                    i += 1;
375                }
376            }
377            if c_current > input.len() {
378                (self.log_fn)("decompression error: hit end of compressed byte stream");
379                return Err(DecodeError::EndOfBuffer);
380            }
381        }
382        if c_current < input.len() {
383            (self.log_fn)("decompression warning: unused bytes at end of compressed buffer");
384        }
385
386        Ok(())
387    }
388
389    pub fn decode_byte(
390        &self,
391        input: &[u8], /* input buffer			*/
392        nx: usize,    /* number of output pixels	*/
393        nblock: usize,
394        output: &mut [c_uchar],
395    ) -> Result<(), DecodeError> /* coding block size		*/ {
396        /* int bsize;  */
397
398        let mut k: i32;
399        let mut imax: usize;
400
401        let mut nzero: i32;
402        let mut fs: i32;
403
404        let mut diff: u32;
405
406        assert_eq!(output.len(), nx);
407        output.fill(0);
408
409        /*
410         * Original size of each pixel (bsize, bytes) and coding block
411         * size (nblock, pixels)
412         * Could make bsize a parameter to allow more efficient
413         * compression of short & byte images.
414         */
415        /*    bsize = 1; */
416
417        /*
418         * From bsize derive:
419         * FSBITS = # bits required to store FS
420         * FSMAX = maximum value for FS
421         * BBITS = bits/pixel for direct coding
422         */
423
424        /* move out of switch block, to tweak performance */
425        let fsbits: i32 = 3;
426        let fsmax: i32 = 6;
427
428        let bbits: i32 = 1 << fsbits;
429
430        /*
431         * Decode in blocks of nblock pixels
432         */
433
434        /* first byte of input buffer contain the value of the first */
435        /* byte integer value, without any encoding */
436
437        let mut lastpix: u32 = input[0] as u32;
438
439        let mut c_current: usize = 1;
440
441        // cend = c + clen - 2;
442
443        let mut b: u32 = input[c_current] as u32; /* bit buffer			*/
444        c_current += 1;
445        let mut nbits: i32 = 8; /* number of bits remaining in b	*/
446
447        let mut i: usize = 0;
448        while i < nx {
449            /* get the FS value from first fsbits */
450            nbits -= fsbits;
451            while nbits < 0 {
452                b = (b << 8) | input[c_current] as u32;
453                c_current += 1;
454                nbits += 8;
455            }
456            fs = ((b >> nbits).wrapping_sub(1)) as i32;
457
458            b &= (1 << nbits) - 1;
459            /* loop over the next block */
460            imax = i + nblock;
461            if imax > nx {
462                imax = nx;
463            }
464            if fs < 0 {
465                /* low-entropy case, all zero differences */
466                while i < imax {
467                    output[i] = lastpix as c_uchar;
468                    i += 1;
469                }
470            } else if fs == fsmax {
471                /* high-entropy case, directly coded pixel values */
472                while i < imax {
473                    k = bbits - nbits;
474                    diff = b.wrapping_shl(k as u32);
475                    k -= 8;
476                    while k >= 0 {
477                        b = input[c_current] as u32;
478                        c_current += 1;
479                        diff |= b << k;
480                        k -= 8
481                    }
482                    if nbits > 0 {
483                        b = input[c_current] as u32;
484                        c_current += 1;
485                        diff |= b >> (-k);
486                        b &= (1 << nbits) - 1;
487                    } else {
488                        b = 0;
489                    }
490                    /*
491                     * undo mapping and differencing
492                     * Note that some of these operations will overflow the
493                     * unsigned int arithmetic -- that's OK, it all works
494                     * out to give the right answers in the output file.
495                     */
496                    if (diff & 1) == 0 {
497                        diff >>= 1;
498                    } else {
499                        diff = !(diff >> 1);
500                    }
501                    output[i] = diff.wrapping_add(lastpix) as c_uchar;
502                    lastpix = output[i] as u32;
503                    i += 1;
504                }
505            } else {
506                /* normal case, Rice coding */
507                while i < imax {
508                    /* count number of leading zeros */
509                    while b == 0 {
510                        nbits += 8;
511
512                        b = input[c_current] as u32;
513                        c_current += 1;
514                    }
515                    nzero = nbits - NONZERO_COUNT[b as usize];
516                    nbits -= nzero + 1;
517                    /* flip the leading one-bit */
518                    b ^= 1 << nbits;
519                    /* get the FS trailing bits */
520                    nbits -= fs;
521                    while nbits < 0 {
522                        b = (b << 8) | (input[c_current] as u32);
523
524                        c_current += 1;
525                        nbits += 8;
526                    }
527                    diff = ((nzero as u32) << fs) | (b >> nbits);
528                    b &= (1 << nbits) - 1;
529
530                    /* undo mapping and differencing */
531                    if (diff & 1) == 0 {
532                        diff >>= 1;
533                    } else {
534                        diff = !(diff >> 1);
535                    }
536                    output[i] = diff.wrapping_add(lastpix) as c_uchar;
537                    lastpix = output[i] as u32;
538                    i += 1;
539                }
540            }
541            if c_current > input.len() {
542                (self.log_fn)("decompression error: hit end of compressed byte stream");
543                return Err(DecodeError::EndOfBuffer);
544            }
545        }
546        if c_current < input.len() {
547            (self.log_fn)("decompression warning: unused bytes at end of compressed buffer");
548        }
549
550        Ok(())
551    }
552}