1use crate::error::DecodeError;
18
19fn compute_row_stride(width: u32, comps: u8, bpc: u8) -> usize {
23 (width as usize * comps as usize * bpc as usize).div_ceil(8)
24}
25
26pub trait ScanlineDecoder {
36 fn width(&self) -> u32;
38
39 #[inline]
41 fn get_width(&self) -> u32 {
42 self.width()
43 }
44
45 fn height(&self) -> u32;
47
48 #[inline]
50 fn get_height(&self) -> u32 {
51 self.height()
52 }
53
54 fn comps_count(&self) -> u8;
57
58 #[inline]
60 fn count_comps(&self) -> u8 {
61 self.comps_count()
62 }
63
64 fn bpc(&self) -> u8;
66
67 #[inline]
69 fn get_bpc(&self) -> u8 {
70 self.bpc()
71 }
72
73 fn row_stride(&self) -> usize;
75
76 fn decode_scanline(&mut self) -> Result<Option<&[u8]>, DecodeError>;
81
82 fn reset(&mut self) -> Result<(), DecodeError>;
84
85 fn current_line(&self) -> Option<usize>;
87
88 fn skip_to_scanline(&mut self, target: usize) {
96 loop {
97 match self.current_line() {
98 Some(n) if n >= target => break,
99 _ => {}
100 }
101 if let Ok(None) | Err(_) = self.decode_scanline() {
102 break;
103 }
104 }
105 }
106
107 fn src_offset(&self) -> Option<usize> {
112 None
113 }
114
115 #[inline]
117 fn get_src_offset(&self) -> Option<usize> {
118 self.src_offset()
119 }
120}
121
122pub struct RandomAccessDecoder<D: ScanlineDecoder> {
128 inner: D,
129 next_line: i32,
130 last_scanline: Vec<u8>,
131}
132
133impl<D: ScanlineDecoder> RandomAccessDecoder<D> {
134 pub fn new(inner: D) -> Self {
136 Self {
137 inner,
138 next_line: -1,
139 last_scanline: Vec::new(),
140 }
141 }
142
143 pub fn skip_to_scanline(&mut self, target: usize) {
153 let _ = self.scanline(target);
154 }
155
156 pub fn scanline(&mut self, line: usize) -> Result<Option<&[u8]>, DecodeError> {
165 let line_i32 = line as i32;
166
167 if self.next_line == line_i32 + 1 && !self.last_scanline.is_empty() {
169 return Ok(Some(&self.last_scanline));
170 }
171
172 if self.next_line < 0 || self.next_line > line_i32 {
174 self.inner.reset()?;
175 self.next_line = 0;
176 }
177
178 while self.next_line < line_i32 {
180 if self.inner.decode_scanline()?.is_none() {
181 return Ok(None);
182 }
183 self.next_line += 1;
184 }
185
186 match self.inner.decode_scanline()? {
188 Some(data) => {
189 self.last_scanline.clear();
190 self.last_scanline.extend_from_slice(data);
191 self.next_line += 1;
192 Ok(Some(&self.last_scanline))
193 }
194 None => Ok(None),
195 }
196 }
197
198 #[inline]
200 pub fn get_scanline(&mut self, line: usize) -> Result<Option<&[u8]>, DecodeError> {
201 self.scanline(line)
202 }
203
204 pub fn inner(&self) -> &D {
206 &self.inner
207 }
208
209 pub fn width(&self) -> u32 {
211 self.inner.width()
212 }
213
214 #[inline]
216 pub fn get_width(&self) -> u32 {
217 self.width()
218 }
219
220 pub fn height(&self) -> u32 {
222 self.inner.height()
223 }
224
225 #[inline]
227 pub fn get_height(&self) -> u32 {
228 self.height()
229 }
230
231 pub fn comps_count(&self) -> u8 {
233 self.inner.comps_count()
234 }
235
236 #[inline]
238 pub fn count_comps(&self) -> u8 {
239 self.comps_count()
240 }
241
242 pub fn bpc(&self) -> u8 {
244 self.inner.bpc()
245 }
246
247 #[inline]
249 pub fn get_bpc(&self) -> u8 {
250 self.bpc()
251 }
252
253 pub fn row_stride(&self) -> usize {
255 self.inner.row_stride()
256 }
257}
258
259pub struct FlateScanlineDecoder {
264 data: Vec<u8>,
265 width: u32,
266 height: u32,
267 comps: u8,
268 bpc: u8,
269 row_stride: usize,
270 offset: usize,
271}
272
273impl FlateScanlineDecoder {
274 pub fn new(
279 compressed: &[u8],
280 width: u32,
281 height: u32,
282 comps: u8,
283 bpc: u8,
284 ) -> Result<Self, DecodeError> {
285 let data = crate::flate::decode(compressed, None, None, None, None)?;
286 let row_stride = compute_row_stride(width, comps, bpc);
287 Ok(Self {
288 data,
289 width,
290 height,
291 comps,
292 bpc,
293 row_stride,
294 offset: 0,
295 })
296 }
297
298 pub fn from_decoded(data: Vec<u8>, width: u32, height: u32, comps: u8, bpc: u8) -> Self {
300 let row_stride = compute_row_stride(width, comps, bpc);
301 Self {
302 data,
303 width,
304 height,
305 comps,
306 bpc,
307 row_stride,
308 offset: 0,
309 }
310 }
311}
312
313impl ScanlineDecoder for FlateScanlineDecoder {
314 fn width(&self) -> u32 {
315 self.width
316 }
317
318 fn height(&self) -> u32 {
319 self.height
320 }
321
322 fn comps_count(&self) -> u8 {
323 self.comps
324 }
325
326 fn bpc(&self) -> u8 {
327 self.bpc
328 }
329
330 fn row_stride(&self) -> usize {
331 self.row_stride
332 }
333
334 fn decode_scanline(&mut self) -> Result<Option<&[u8]>, DecodeError> {
335 if self.row_stride == 0 || self.offset >= self.data.len() {
336 return Ok(None);
337 }
338 let end = (self.offset + self.row_stride).min(self.data.len());
339 let row = &self.data[self.offset..end];
340 self.offset = end;
341 Ok(Some(row))
342 }
343
344 fn reset(&mut self) -> Result<(), DecodeError> {
345 self.offset = 0;
346 Ok(())
347 }
348
349 fn current_line(&self) -> Option<usize> {
350 if self.row_stride == 0 || self.offset == 0 {
351 None
352 } else {
353 Some(self.offset / self.row_stride - 1)
354 }
355 }
356}
357
358pub struct DctScanlineDecoder {
363 data: Vec<u8>,
364 width: u32,
365 height: u32,
366 comps: u8,
367 bpc: u8,
368 row_stride: usize,
369 offset: usize,
370}
371
372impl DctScanlineDecoder {
373 pub fn new(
378 jpeg_data: &[u8],
379 width: u32,
380 height: u32,
381 comps: u8,
382 bpc: u8,
383 ) -> Result<Self, DecodeError> {
384 let data = crate::jpeg::decode(jpeg_data)?;
385 let row_stride = compute_row_stride(width, comps, bpc);
386 Ok(Self {
387 data,
388 width,
389 height,
390 comps,
391 bpc,
392 row_stride,
393 offset: 0,
394 })
395 }
396
397 pub fn from_decoded(data: Vec<u8>, width: u32, height: u32, comps: u8, bpc: u8) -> Self {
399 let row_stride = compute_row_stride(width, comps, bpc);
400 Self {
401 data,
402 width,
403 height,
404 comps,
405 bpc,
406 row_stride,
407 offset: 0,
408 }
409 }
410}
411
412impl ScanlineDecoder for DctScanlineDecoder {
413 fn width(&self) -> u32 {
414 self.width
415 }
416
417 fn height(&self) -> u32 {
418 self.height
419 }
420
421 fn comps_count(&self) -> u8 {
422 self.comps
423 }
424
425 fn bpc(&self) -> u8 {
426 self.bpc
427 }
428
429 fn row_stride(&self) -> usize {
430 self.row_stride
431 }
432
433 fn decode_scanline(&mut self) -> Result<Option<&[u8]>, DecodeError> {
434 if self.row_stride == 0 || self.offset >= self.data.len() {
435 return Ok(None);
436 }
437 let end = (self.offset + self.row_stride).min(self.data.len());
438 let row = &self.data[self.offset..end];
439 self.offset = end;
440 Ok(Some(row))
441 }
442
443 fn reset(&mut self) -> Result<(), DecodeError> {
444 self.offset = 0;
445 Ok(())
446 }
447
448 fn current_line(&self) -> Option<usize> {
449 if self.row_stride == 0 || self.offset == 0 {
450 None
451 } else {
452 Some(self.offset / self.row_stride - 1)
453 }
454 }
455}
456
457#[cfg(test)]
458mod tests {
459 use super::*;
460 use flate2::Compression;
461 use flate2::write::ZlibEncoder;
462 use std::io::Write;
463
464 fn zlib_compress(data: &[u8]) -> Vec<u8> {
465 let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
466 encoder.write_all(data).unwrap();
467 encoder.finish().unwrap()
468 }
469
470 #[test]
471 fn test_flate_scanline_basic() {
472 let raw = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
474 let compressed = zlib_compress(&raw);
475 let mut decoder = FlateScanlineDecoder::new(&compressed, 4, 3, 1, 8).unwrap();
476
477 assert_eq!(decoder.row_stride(), 4);
478 assert_eq!(decoder.width(), 4);
479 assert_eq!(decoder.height(), 3);
480 assert_eq!(decoder.comps_count(), 1);
481 assert_eq!(decoder.bpc(), 8);
482
483 let row1 = decoder.decode_scanline().unwrap().unwrap();
484 assert_eq!(row1, &[1, 2, 3, 4]);
485
486 let row2 = decoder.decode_scanline().unwrap().unwrap();
487 assert_eq!(row2, &[5, 6, 7, 8]);
488
489 let row3 = decoder.decode_scanline().unwrap().unwrap();
490 assert_eq!(row3, &[9, 10, 11, 12]);
491
492 assert!(decoder.decode_scanline().unwrap().is_none());
494 }
495
496 #[test]
497 fn test_flate_scanline_count() {
498 let raw = vec![0u8; 100];
500 let compressed = zlib_compress(&raw);
501 let mut decoder = FlateScanlineDecoder::new(&compressed, 10, 10, 1, 8).unwrap();
502
503 let mut count = 0;
504 while decoder.decode_scanline().unwrap().is_some() {
505 count += 1;
506 }
507 assert_eq!(count, 10);
508 }
509
510 #[test]
511 fn test_flate_scanline_matches_batch() {
512 let raw: Vec<u8> = (0..120).map(|i| (i % 256) as u8).collect();
514 let compressed = zlib_compress(&raw);
515 let mut decoder = FlateScanlineDecoder::new(&compressed, 10, 12, 1, 8).unwrap();
516
517 let mut collected = Vec::new();
518 while let Some(row) = decoder.decode_scanline().unwrap() {
519 collected.extend_from_slice(row);
520 }
521 assert_eq!(collected, raw);
522 }
523
524 #[test]
525 fn test_flate_scanline_none_after_last() {
526 let raw = vec![1u8; 4];
528 let compressed = zlib_compress(&raw);
529 let mut decoder = FlateScanlineDecoder::new(&compressed, 4, 1, 1, 8).unwrap();
530
531 assert!(decoder.decode_scanline().unwrap().is_some());
532 assert!(decoder.decode_scanline().unwrap().is_none());
533 assert!(decoder.decode_scanline().unwrap().is_none());
534 }
535
536 #[test]
537 fn test_flate_scanline_reset() {
538 let raw = vec![1, 2, 3, 4, 5, 6, 7, 8];
540 let compressed = zlib_compress(&raw);
541 let mut decoder = FlateScanlineDecoder::new(&compressed, 4, 2, 1, 8).unwrap();
542
543 let row1 = decoder.decode_scanline().unwrap().unwrap().to_vec();
544 decoder.decode_scanline().unwrap(); assert!(decoder.decode_scanline().unwrap().is_none());
546
547 decoder.reset().unwrap();
548 let row1_again = decoder.decode_scanline().unwrap().unwrap();
549 assert_eq!(row1, row1_again);
550 }
551
552 #[test]
553 fn test_flate_scanline_row_stride_calc() {
554 let raw = vec![0u8; 1920 * 2];
556 let compressed = zlib_compress(&raw);
557 let decoder = FlateScanlineDecoder::new(&compressed, 640, 2, 3, 8).unwrap();
558 assert_eq!(decoder.row_stride(), 1920);
559 assert_eq!(decoder.width(), 640);
560 assert_eq!(decoder.comps_count(), 3);
561 }
562
563 #[test]
564 fn test_flate_scanline_zero_stride() {
565 let decoder = FlateScanlineDecoder::from_decoded(vec![1, 2, 3], 0, 1, 1, 8);
567 let mut decoder: Box<dyn ScanlineDecoder> = Box::new(decoder);
568 assert!(decoder.decode_scanline().unwrap().is_none());
569 }
570
571 #[test]
572 fn test_dct_scanline_from_decoded() {
573 let raw = vec![10, 20, 30, 40, 50, 60];
575 let mut decoder = DctScanlineDecoder::from_decoded(raw.clone(), 1, 2, 3, 8);
576
577 assert_eq!(decoder.width(), 1);
578 assert_eq!(decoder.height(), 2);
579 assert_eq!(decoder.comps_count(), 3);
580 assert_eq!(decoder.bpc(), 8);
581 assert_eq!(decoder.row_stride(), 3);
582
583 let row1 = decoder.decode_scanline().unwrap().unwrap();
584 assert_eq!(row1, &[10, 20, 30]);
585
586 let row2 = decoder.decode_scanline().unwrap().unwrap();
587 assert_eq!(row2, &[40, 50, 60]);
588
589 assert!(decoder.decode_scanline().unwrap().is_none());
590 }
591
592 #[test]
593 fn test_dct_scanline_reset() {
594 let raw = vec![1, 2, 3, 4, 5, 6];
596 let mut decoder = DctScanlineDecoder::from_decoded(raw, 1, 2, 3, 8);
597
598 decoder.decode_scanline().unwrap();
599 decoder.decode_scanline().unwrap();
600 assert!(decoder.decode_scanline().unwrap().is_none());
601
602 decoder.reset().unwrap();
603 let first = decoder.decode_scanline().unwrap().unwrap();
604 assert_eq!(first, &[1, 2, 3]);
605 }
606
607 #[test]
608 fn test_scanline_decoder_trait_object_safety() {
609 fn assert_obj_safe(_: &dyn ScanlineDecoder) {}
610 let decoder = FlateScanlineDecoder::from_decoded(vec![0; 4], 2, 1, 1, 8);
612 assert_obj_safe(&decoder);
613 }
614
615 #[test]
616 fn test_partial_last_row() {
617 let raw = vec![1, 2, 3, 4, 5];
620 let mut decoder = FlateScanlineDecoder::from_decoded(raw, 3, 2, 1, 8);
621
622 let row1 = decoder.decode_scanline().unwrap().unwrap();
623 assert_eq!(row1, &[1, 2, 3]);
624
625 let row2 = decoder.decode_scanline().unwrap().unwrap();
626 assert_eq!(row2, &[4, 5]); assert!(decoder.decode_scanline().unwrap().is_none());
629 }
630
631 #[test]
632 fn test_metadata_getters_flate() {
633 let raw = vec![0u8; 8 * 6 * 2]; let compressed = zlib_compress(&raw);
636 let decoder = FlateScanlineDecoder::new(&compressed, 8, 6, 1, 16).unwrap();
638 assert_eq!(decoder.width(), 8);
639 assert_eq!(decoder.height(), 6);
640 assert_eq!(decoder.comps_count(), 1);
641 assert_eq!(decoder.bpc(), 16);
642 assert_eq!(decoder.row_stride(), 16);
643 }
644
645 #[test]
646 fn test_metadata_getters_dct() {
647 let data = vec![0u8; 10 * 4]; let decoder = DctScanlineDecoder::from_decoded(data, 10, 4, 1, 8);
650 assert_eq!(decoder.width(), 10);
651 assert_eq!(decoder.height(), 4);
652 assert_eq!(decoder.comps_count(), 1);
653 assert_eq!(decoder.bpc(), 8);
654 assert_eq!(decoder.row_stride(), 10);
655 }
656
657 #[test]
658 fn test_compute_row_stride_1bpc() {
659 let d8 = FlateScanlineDecoder::from_decoded(vec![0; 1], 8, 1, 1, 1);
661 assert_eq!(d8.row_stride(), 1);
662 let d9 = FlateScanlineDecoder::from_decoded(vec![0; 2], 9, 1, 1, 1);
663 assert_eq!(d9.row_stride(), 2);
664 }
665
666 #[test]
667 fn test_compute_row_stride_16bpc() {
668 let decoder = FlateScanlineDecoder::from_decoded(vec![0; 24], 4, 1, 3, 16);
670 assert_eq!(decoder.row_stride(), 24);
671 }
672
673 #[test]
678 fn test_random_access_sequential() {
679 let raw = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
681 let decoder = FlateScanlineDecoder::from_decoded(raw, 4, 3, 1, 8);
682 let mut ra = RandomAccessDecoder::new(decoder);
683
684 let row0 = ra.get_scanline(0).unwrap().unwrap().to_vec();
685 assert_eq!(row0, &[1, 2, 3, 4]);
686
687 let row1 = ra.get_scanline(1).unwrap().unwrap().to_vec();
688 assert_eq!(row1, &[5, 6, 7, 8]);
689
690 let row2 = ra.get_scanline(2).unwrap().unwrap().to_vec();
691 assert_eq!(row2, &[9, 10, 11, 12]);
692 }
693
694 #[test]
695 fn test_random_access_cached() {
696 let raw = vec![10, 20, 30, 40, 50, 60];
698 let decoder = FlateScanlineDecoder::from_decoded(raw, 1, 2, 3, 8);
699 let mut ra = RandomAccessDecoder::new(decoder);
700
701 let row0 = ra.get_scanline(0).unwrap().unwrap().to_vec();
702 assert_eq!(row0, &[10, 20, 30]);
703
704 let row0_again = ra.get_scanline(0).unwrap().unwrap().to_vec();
706 assert_eq!(row0_again, &[10, 20, 30]);
707 }
708
709 #[test]
710 fn test_random_access_rewind() {
711 let raw = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
713 let decoder = FlateScanlineDecoder::from_decoded(raw, 3, 3, 1, 8);
714 let mut ra = RandomAccessDecoder::new(decoder);
715
716 let row2 = ra.get_scanline(2).unwrap().unwrap().to_vec();
718 assert_eq!(row2, &[7, 8, 9]);
719
720 let row0 = ra.get_scanline(0).unwrap().unwrap().to_vec();
722 assert_eq!(row0, &[1, 2, 3]);
723
724 let row1 = ra.get_scanline(1).unwrap().unwrap().to_vec();
725 assert_eq!(row1, &[4, 5, 6]);
726 }
727
728 #[test]
729 fn test_random_access_skip_forward() {
730 let raw: Vec<u8> = (0..40).collect();
732 let decoder = FlateScanlineDecoder::from_decoded(raw, 10, 4, 1, 8);
733 let mut ra = RandomAccessDecoder::new(decoder);
734
735 let row3 = ra.get_scanline(3).unwrap().unwrap().to_vec();
737 assert_eq!(row3, &[30, 31, 32, 33, 34, 35, 36, 37, 38, 39]);
738 }
739
740 #[test]
741 fn test_random_access_out_of_bounds() {
742 let raw = vec![1, 2, 3];
744 let decoder = FlateScanlineDecoder::from_decoded(raw, 3, 1, 1, 8);
745 let mut ra = RandomAccessDecoder::new(decoder);
746
747 let result = ra.get_scanline(1).unwrap();
749 assert!(result.is_none());
750 }
751
752 #[test]
753 fn test_random_access_inner_ref() {
754 let raw = vec![1, 2, 3, 4];
756 let decoder = FlateScanlineDecoder::from_decoded(raw, 2, 1, 1, 8);
757 let ra = RandomAccessDecoder::new(decoder);
758 assert_eq!(ra.inner().row_stride(), 2);
759 assert_eq!(ra.row_stride(), 2);
760 assert_eq!(ra.width(), 2);
761 assert_eq!(ra.height(), 1);
762 assert_eq!(ra.comps_count(), 1);
763 assert_eq!(ra.bpc(), 8);
764 }
765
766 #[test]
767 fn test_current_line_before_read() {
768 let decoder = FlateScanlineDecoder::from_decoded(vec![1, 2, 3, 4], 2, 2, 1, 8);
770 assert_eq!(decoder.current_line(), None);
771 }
772
773 #[test]
774 fn test_current_line_after_read() {
775 let mut decoder = FlateScanlineDecoder::from_decoded(vec![1, 2, 3, 4], 2, 2, 1, 8);
776 decoder.decode_scanline().unwrap();
777 assert_eq!(decoder.current_line(), Some(0));
778 decoder.decode_scanline().unwrap();
779 assert_eq!(decoder.current_line(), Some(1));
780 }
781
782 #[test]
783 fn test_current_line_after_reset() {
784 let mut decoder = FlateScanlineDecoder::from_decoded(vec![1, 2, 3, 4], 2, 2, 1, 8);
785 decoder.decode_scanline().unwrap();
786 decoder.reset().unwrap();
787 assert_eq!(decoder.current_line(), None);
788 }
789
790 #[test]
795 fn test_skip_to_scanline_advances_position() {
796 let raw: Vec<u8> = (0..12).collect();
798 let compressed = zlib_compress(&raw);
799 let mut decoder = FlateScanlineDecoder::new(&compressed, 2, 6, 1, 8).unwrap();
800
801 decoder.skip_to_scanline(3);
803
804 assert!(
806 decoder.current_line().map(|l| l >= 3).unwrap_or(false),
807 "expected current_line() >= 3 after skip_to_scanline(3), got {:?}",
808 decoder.current_line()
809 );
810 }
811
812 #[test]
813 fn test_get_src_offset_returns_none() {
814 let decoder = FlateScanlineDecoder::from_decoded(vec![1, 2, 3, 4], 2, 2, 1, 8);
816 let trait_obj: &dyn ScanlineDecoder = &decoder;
818 assert_eq!(trait_obj.get_src_offset(), None);
819 }
820}