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}