1#[cfg(not(feature = "std"))]
28#[allow(unused_imports)]
29use crate::compat::*;
30use crate::error::{OxiGdalError, Result};
31use crate::types::{ColorInterpretation, NoDataValue, PixelLayout, RasterDataType};
32
33use super::{BufferStatistics, RasterBuffer};
34
35#[derive(Debug, Clone)]
39pub struct MultiBandBuffer {
40 bands: Vec<RasterBuffer>,
42 colors: Vec<ColorInterpretation>,
44 nodata_overrides: Vec<Option<NoDataValue>>,
46 layout: PixelLayout,
48}
49
50impl MultiBandBuffer {
51 pub fn from_bands(bands: Vec<RasterBuffer>, colors: Vec<ColorInterpretation>) -> Result<Self> {
60 if bands.is_empty() {
61 return Err(OxiGdalError::InvalidParameter {
62 parameter: "bands",
63 message: "At least one band is required".to_string(),
64 });
65 }
66 if colors.len() != bands.len() {
67 return Err(OxiGdalError::InvalidParameter {
68 parameter: "colors",
69 message: format!(
70 "Color interpretation count ({}) must match band count ({})",
71 colors.len(),
72 bands.len()
73 ),
74 });
75 }
76
77 let w = bands[0].width();
78 let h = bands[0].height();
79 let dt = bands[0].data_type();
80
81 for (i, band) in bands.iter().enumerate().skip(1) {
82 if band.width() != w || band.height() != h {
83 return Err(OxiGdalError::InvalidParameter {
84 parameter: "bands",
85 message: format!(
86 "Band {} dimensions {}x{} differ from band 0 dimensions {}x{}",
87 i,
88 band.width(),
89 band.height(),
90 w,
91 h
92 ),
93 });
94 }
95 if band.data_type() != dt {
96 return Err(OxiGdalError::InvalidParameter {
97 parameter: "bands",
98 message: format!(
99 "Band {} data type {:?} differs from band 0 data type {:?}",
100 i,
101 band.data_type(),
102 dt
103 ),
104 });
105 }
106 }
107
108 let nodata_overrides = vec![None; bands.len()];
109
110 Ok(Self {
111 bands,
112 colors,
113 nodata_overrides,
114 layout: PixelLayout::BandSequential,
115 })
116 }
117
118 pub fn from_interleaved(
126 data: &[u8],
127 width: u64,
128 height: u64,
129 band_count: u32,
130 data_type: RasterDataType,
131 nodata: NoDataValue,
132 ) -> Result<Self> {
133 let pixel_size = data_type.size_bytes();
134 let expected = (width * height * band_count as u64 * pixel_size as u64) as usize;
135 if data.len() != expected {
136 return Err(OxiGdalError::InvalidParameter {
137 parameter: "data",
138 message: format!(
139 "Interleaved data size {} differs from expected {} ({}x{}x{}x{})",
140 data.len(),
141 expected,
142 width,
143 height,
144 band_count,
145 pixel_size
146 ),
147 });
148 }
149
150 let pixels = width * height;
151 let band_size = (pixels * pixel_size as u64) as usize;
152 let bc = band_count as usize;
153 let ps = pixel_size;
154
155 let mut band_buffers = Vec::with_capacity(bc);
156 for b in 0..bc {
157 let mut band_data = vec![0u8; band_size];
158 for pixel_idx in 0..(pixels as usize) {
159 let src_offset = pixel_idx * bc * ps + b * ps;
160 let dst_offset = pixel_idx * ps;
161 band_data[dst_offset..dst_offset + ps]
162 .copy_from_slice(&data[src_offset..src_offset + ps]);
163 }
164 band_buffers.push(RasterBuffer::new(
165 band_data, width, height, data_type, nodata,
166 )?);
167 }
168
169 let colors = default_color_interpretation(bc);
170
171 Ok(Self {
172 bands: band_buffers,
173 colors,
174 nodata_overrides: vec![None; bc],
175 layout: PixelLayout::BandInterleavedByPixel,
176 })
177 }
178
179 pub fn from_bsq(
185 data: &[u8],
186 width: u64,
187 height: u64,
188 band_count: u32,
189 data_type: RasterDataType,
190 nodata: NoDataValue,
191 ) -> Result<Self> {
192 let pixel_size = data_type.size_bytes();
193 let expected = (width * height * band_count as u64 * pixel_size as u64) as usize;
194 if data.len() != expected {
195 return Err(OxiGdalError::InvalidParameter {
196 parameter: "data",
197 message: format!(
198 "BSQ data size {} differs from expected {}",
199 data.len(),
200 expected
201 ),
202 });
203 }
204
205 let band_size = (width * height * pixel_size as u64) as usize;
206 let bc = band_count as usize;
207 let mut band_buffers = Vec::with_capacity(bc);
208
209 for b in 0..bc {
210 let start = b * band_size;
211 let band_data = data[start..start + band_size].to_vec();
212 band_buffers.push(RasterBuffer::new(
213 band_data, width, height, data_type, nodata,
214 )?);
215 }
216
217 let colors = default_color_interpretation(bc);
218
219 Ok(Self {
220 bands: band_buffers,
221 colors,
222 nodata_overrides: vec![None; bc],
223 layout: PixelLayout::BandSequential,
224 })
225 }
226
227 pub fn from_bil(
243 data: &[u8],
244 width: u64,
245 height: u64,
246 band_count: u32,
247 data_type: RasterDataType,
248 nodata: NoDataValue,
249 ) -> Result<Self> {
250 let pixel_size = data_type.size_bytes();
251 let bc = band_count as usize;
252 let w = width as usize;
253 let h = height as usize;
254 let expected = bc * h * w * pixel_size;
255 if data.len() != expected {
256 return Err(OxiGdalError::InvalidParameter {
257 parameter: "data",
258 message: format!(
259 "BIL data size {} differs from expected {} ({}x{}x{}x{})",
260 data.len(),
261 expected,
262 width,
263 height,
264 band_count,
265 pixel_size
266 ),
267 });
268 }
269
270 let band_byte_size = h * w * pixel_size;
272 let mut band_buffers: Vec<RasterBuffer> = Vec::with_capacity(bc);
273
274 for b in 0..bc {
275 let mut bsq_data = vec![0u8; band_byte_size];
276 for r in 0..h {
277 let bil_offset = (r * bc + b) * w * pixel_size;
279 let bsq_offset = r * w * pixel_size;
281 let row_bytes = w * pixel_size;
282 bsq_data[bsq_offset..bsq_offset + row_bytes]
283 .copy_from_slice(&data[bil_offset..bil_offset + row_bytes]);
284 }
285 band_buffers.push(RasterBuffer::new(
286 bsq_data, width, height, data_type, nodata,
287 )?);
288 }
289
290 let colors = default_color_interpretation(bc);
291
292 Ok(Self {
293 bands: band_buffers,
294 colors,
295 nodata_overrides: vec![None; bc],
296 layout: PixelLayout::BandInterleavedByLine,
297 })
298 }
299
300 #[must_use]
302 pub fn band_count(&self) -> u32 {
303 self.bands.len() as u32
304 }
305
306 #[must_use]
308 pub fn width(&self) -> u64 {
309 self.bands.first().map_or(0, |b| b.width())
310 }
311
312 #[must_use]
314 pub fn height(&self) -> u64 {
315 self.bands.first().map_or(0, |b| b.height())
316 }
317
318 #[must_use]
320 pub fn data_type(&self) -> RasterDataType {
321 self.bands
322 .first()
323 .map_or(RasterDataType::UInt8, |b| b.data_type())
324 }
325
326 #[must_use]
328 pub fn layout(&self) -> PixelLayout {
329 self.layout
330 }
331
332 pub fn set_band_nodata(&mut self, band: u32, nodata: NoDataValue) -> Result<()> {
334 let idx = band as usize;
335 if idx >= self.bands.len() {
336 return Err(OxiGdalError::InvalidParameter {
337 parameter: "band",
338 message: format!("Band index {} out of range (0..{})", band, self.bands.len()),
339 });
340 }
341 self.nodata_overrides[idx] = Some(nodata);
342 Ok(())
343 }
344
345 pub fn band(&self, band: u32) -> Result<BandRef<'_>> {
351 let idx = band as usize;
352 if idx >= self.bands.len() {
353 return Err(OxiGdalError::InvalidParameter {
354 parameter: "band",
355 message: format!("Band index {} out of range (0..{})", band, self.bands.len()),
356 });
357 }
358 Ok(BandRef {
359 index: band,
360 buffer: &self.bands[idx],
361 color: self.colors[idx],
362 nodata_override: self.nodata_overrides[idx],
363 })
364 }
365
366 pub fn band_mut(&mut self, band: u32) -> Result<&mut RasterBuffer> {
372 let idx = band as usize;
373 if idx >= self.bands.len() {
374 return Err(OxiGdalError::InvalidParameter {
375 parameter: "band",
376 message: format!("Band index {} out of range (0..{})", band, self.bands.len()),
377 });
378 }
379 Ok(&mut self.bands[idx])
380 }
381
382 #[must_use]
384 pub fn bands(&self) -> BandIterator<'_> {
385 BandIterator {
386 multi: self,
387 current: 0,
388 }
389 }
390
391 #[must_use]
395 pub fn to_interleaved(&self) -> Vec<u8> {
396 let ps = self.data_type().size_bytes();
397 let bc = self.bands.len();
398 let pixels = (self.width() * self.height()) as usize;
399 let mut out = vec![0u8; pixels * bc * ps];
400
401 for (b, band) in self.bands.iter().enumerate() {
402 let src = band.as_bytes();
403 for pixel_idx in 0..pixels {
404 let dst_off = pixel_idx * bc * ps + b * ps;
405 let src_off = pixel_idx * ps;
406 out[dst_off..dst_off + ps].copy_from_slice(&src[src_off..src_off + ps]);
407 }
408 }
409
410 out
411 }
412
413 #[must_use]
417 pub fn to_bsq(&self) -> Vec<u8> {
418 let mut out = Vec::with_capacity(self.bands.iter().map(|b| b.as_bytes().len()).sum());
419 for band in &self.bands {
420 out.extend_from_slice(band.as_bytes());
421 }
422 out
423 }
424
425 #[must_use]
434 pub fn to_bil(&self) -> Vec<u8> {
435 let bc = self.bands.len();
436 let pixel_size = self.data_type().size_bytes();
437 let h = self.height() as usize;
438 let w = self.width() as usize;
439 let total = bc * h * w * pixel_size;
440 let mut out = vec![0u8; total];
441
442 for (b, band) in self.bands.iter().enumerate() {
443 let src = band.as_bytes();
444 for r in 0..h {
445 let bil_offset = (r * bc + b) * w * pixel_size;
447 let bsq_offset = r * w * pixel_size;
449 let row_bytes = w * pixel_size;
450 out[bil_offset..bil_offset + row_bytes]
451 .copy_from_slice(&src[bsq_offset..bsq_offset + row_bytes]);
452 }
453 }
454
455 out
456 }
457
458 pub fn compute_all_statistics(&self) -> Result<Vec<BufferStatistics>> {
464 self.bands.iter().map(|b| b.compute_statistics()).collect()
465 }
466
467 #[must_use]
469 pub fn into_bands(self) -> Vec<RasterBuffer> {
470 self.bands
471 }
472}
473
474#[derive(Debug, Clone, Copy)]
476pub struct BandRef<'a> {
477 index: u32,
479 buffer: &'a RasterBuffer,
481 color: ColorInterpretation,
483 nodata_override: Option<NoDataValue>,
485}
486
487impl<'a> BandRef<'a> {
488 #[must_use]
490 pub fn index(&self) -> u32 {
491 self.index
492 }
493
494 #[must_use]
496 pub fn gdal_index(&self) -> u32 {
497 self.index + 1
498 }
499
500 #[must_use]
502 pub fn buffer(&self) -> &'a RasterBuffer {
503 self.buffer
504 }
505
506 #[must_use]
508 pub fn color(&self) -> ColorInterpretation {
509 self.color
510 }
511
512 #[must_use]
514 pub fn nodata(&self) -> NoDataValue {
515 self.nodata_override.unwrap_or(self.buffer.nodata())
516 }
517
518 pub fn as_slice<T: Copy + 'static>(&self) -> Result<&[T]> {
524 self.buffer.as_slice::<T>()
525 }
526}
527
528pub struct BandIterator<'a> {
533 multi: &'a MultiBandBuffer,
534 current: u32,
535}
536
537impl<'a> Iterator for BandIterator<'a> {
538 type Item = BandRef<'a>;
539
540 fn next(&mut self) -> Option<Self::Item> {
541 if self.current >= self.multi.band_count() {
542 return None;
543 }
544 let idx = self.current as usize;
545 let band = BandRef {
546 index: self.current,
547 buffer: &self.multi.bands[idx],
548 color: self.multi.colors[idx],
549 nodata_override: self.multi.nodata_overrides[idx],
550 };
551 self.current += 1;
552 Some(band)
553 }
554
555 fn size_hint(&self) -> (usize, Option<usize>) {
556 let remaining = (self.multi.band_count() - self.current) as usize;
557 (remaining, Some(remaining))
558 }
559}
560
561impl ExactSizeIterator for BandIterator<'_> {}
562
563fn default_color_interpretation(band_count: usize) -> Vec<ColorInterpretation> {
565 match band_count {
566 1 => vec![ColorInterpretation::Gray],
567 3 => vec![
568 ColorInterpretation::Red,
569 ColorInterpretation::Green,
570 ColorInterpretation::Blue,
571 ],
572 4 => vec![
573 ColorInterpretation::Red,
574 ColorInterpretation::Green,
575 ColorInterpretation::Blue,
576 ColorInterpretation::Alpha,
577 ],
578 _ => vec![ColorInterpretation::Undefined; band_count],
579 }
580}
581
582#[cfg(test)]
583mod tests {
584 use super::*;
585
586 #[test]
587 fn test_multi_band_from_bands() {
588 let r = RasterBuffer::zeros(100, 100, RasterDataType::UInt8);
589 let g = RasterBuffer::zeros(100, 100, RasterDataType::UInt8);
590 let b = RasterBuffer::zeros(100, 100, RasterDataType::UInt8);
591
592 let multi = MultiBandBuffer::from_bands(
593 vec![r, g, b],
594 vec![
595 ColorInterpretation::Red,
596 ColorInterpretation::Green,
597 ColorInterpretation::Blue,
598 ],
599 )
600 .expect("should create multi-band buffer");
601
602 assert_eq!(multi.band_count(), 3);
603 assert_eq!(multi.width(), 100);
604 assert_eq!(multi.height(), 100);
605 assert_eq!(multi.data_type(), RasterDataType::UInt8);
606 }
607
608 #[test]
609 fn test_band_iterator() {
610 let bands: Vec<_> = (0..4)
611 .map(|_| RasterBuffer::zeros(50, 50, RasterDataType::Float32))
612 .collect();
613 let colors = vec![
614 ColorInterpretation::Red,
615 ColorInterpretation::Green,
616 ColorInterpretation::Blue,
617 ColorInterpretation::Alpha,
618 ];
619
620 let multi = MultiBandBuffer::from_bands(bands, colors).expect("should create");
621
622 let collected: Vec<_> = multi.bands().collect();
623 assert_eq!(collected.len(), 4);
624 assert_eq!(collected[0].index(), 0);
625 assert_eq!(collected[0].gdal_index(), 1);
626 assert_eq!(collected[0].color(), ColorInterpretation::Red);
627 assert_eq!(collected[3].color(), ColorInterpretation::Alpha);
628 }
629
630 #[test]
631 fn test_band_iterator_exact_size() {
632 let multi = MultiBandBuffer::from_bands(
633 vec![
634 RasterBuffer::zeros(10, 10, RasterDataType::UInt8),
635 RasterBuffer::zeros(10, 10, RasterDataType::UInt8),
636 ],
637 vec![ColorInterpretation::Gray, ColorInterpretation::Alpha],
638 )
639 .expect("should create");
640
641 let iter = multi.bands();
642 assert_eq!(iter.len(), 2);
643 }
644
645 #[test]
646 fn test_multi_band_empty_error() {
647 let result = MultiBandBuffer::from_bands(vec![], vec![]);
648 assert!(result.is_err());
649 }
650
651 #[test]
652 fn test_multi_band_dimension_mismatch() {
653 let a = RasterBuffer::zeros(100, 100, RasterDataType::UInt8);
654 let b = RasterBuffer::zeros(50, 50, RasterDataType::UInt8);
655
656 let result = MultiBandBuffer::from_bands(
657 vec![a, b],
658 vec![ColorInterpretation::Gray, ColorInterpretation::Alpha],
659 );
660 assert!(result.is_err());
661 }
662
663 #[test]
664 fn test_multi_band_type_mismatch() {
665 let a = RasterBuffer::zeros(100, 100, RasterDataType::UInt8);
666 let b = RasterBuffer::zeros(100, 100, RasterDataType::Float32);
667
668 let result = MultiBandBuffer::from_bands(
669 vec![a, b],
670 vec![ColorInterpretation::Gray, ColorInterpretation::Alpha],
671 );
672 assert!(result.is_err());
673 }
674
675 #[test]
676 fn test_multi_band_color_count_mismatch() {
677 let a = RasterBuffer::zeros(100, 100, RasterDataType::UInt8);
678
679 let result = MultiBandBuffer::from_bands(
680 vec![a],
681 vec![ColorInterpretation::Red, ColorInterpretation::Green],
682 );
683 assert!(result.is_err());
684 }
685
686 #[test]
687 fn test_band_access() {
688 let mut buf = RasterBuffer::zeros(10, 10, RasterDataType::UInt8);
689 buf.set_pixel(5, 5, 42.0).expect("should set");
690
691 let multi = MultiBandBuffer::from_bands(vec![buf], vec![ColorInterpretation::Gray])
692 .expect("should create");
693
694 let band = multi.band(0).expect("should get band");
695 assert_eq!(band.buffer().get_pixel(5, 5).expect("should get"), 42.0);
696 }
697
698 #[test]
699 fn test_band_out_of_range() {
700 let multi = MultiBandBuffer::from_bands(
701 vec![RasterBuffer::zeros(10, 10, RasterDataType::UInt8)],
702 vec![ColorInterpretation::Gray],
703 )
704 .expect("should create");
705
706 assert!(multi.band(1).is_err());
707 }
708
709 #[test]
710 fn test_from_interleaved_roundtrip() {
711 let data = vec![
713 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, ];
718
719 let multi = MultiBandBuffer::from_interleaved(
720 &data,
721 2,
722 2,
723 3,
724 RasterDataType::UInt8,
725 NoDataValue::None,
726 )
727 .expect("should create from interleaved");
728
729 assert_eq!(multi.band_count(), 3);
730 assert_eq!(multi.width(), 2);
731 assert_eq!(multi.height(), 2);
732 assert_eq!(multi.layout(), PixelLayout::BandInterleavedByPixel);
733
734 let r_band = multi.band(0).expect("should get");
736 assert_eq!(r_band.as_slice::<u8>().expect("slice"), &[10, 40, 70, 100]);
737
738 let g_band = multi.band(1).expect("should get");
740 assert_eq!(g_band.as_slice::<u8>().expect("slice"), &[20, 50, 80, 110]);
741
742 let b_band = multi.band(2).expect("should get");
744 assert_eq!(b_band.as_slice::<u8>().expect("slice"), &[30, 60, 90, 120]);
745
746 let interleaved = multi.to_interleaved();
748 assert_eq!(interleaved, data);
749 }
750
751 #[test]
752 fn test_from_bsq_roundtrip() {
753 let data = vec![
755 10, 40, 70, 100, 20, 50, 80, 110, 30, 60, 90, 120, ];
759
760 let multi =
761 MultiBandBuffer::from_bsq(&data, 2, 2, 3, RasterDataType::UInt8, NoDataValue::None)
762 .expect("should create from BSQ");
763
764 assert_eq!(multi.band_count(), 3);
765 assert_eq!(multi.layout(), PixelLayout::BandSequential);
766
767 let r_band = multi.band(0).expect("should get");
768 assert_eq!(r_band.as_slice::<u8>().expect("slice"), &[10, 40, 70, 100]);
769
770 let bsq = multi.to_bsq();
771 assert_eq!(bsq, data);
772 }
773
774 #[test]
775 fn test_compute_all_statistics() {
776 let mut r = RasterBuffer::zeros(2, 2, RasterDataType::Float32);
777 r.set_pixel(0, 0, 1.0).expect("set");
778 r.set_pixel(1, 0, 2.0).expect("set");
779 r.set_pixel(0, 1, 3.0).expect("set");
780 r.set_pixel(1, 1, 4.0).expect("set");
781
782 let multi = MultiBandBuffer::from_bands(vec![r], vec![ColorInterpretation::Gray])
783 .expect("should create");
784
785 let stats = multi.compute_all_statistics().expect("should compute");
786 assert_eq!(stats.len(), 1);
787 assert!((stats[0].min - 1.0).abs() < 1e-6);
788 assert!((stats[0].max - 4.0).abs() < 1e-6);
789 assert!((stats[0].mean - 2.5).abs() < 1e-6);
790 }
791
792 #[test]
793 fn test_band_nodata_override() {
794 let buf = RasterBuffer::zeros(5, 5, RasterDataType::Float32);
795 let mut multi = MultiBandBuffer::from_bands(vec![buf], vec![ColorInterpretation::Gray])
796 .expect("should create");
797
798 let band = multi.band(0).expect("get");
800 assert_eq!(band.nodata(), NoDataValue::None);
801
802 multi
804 .set_band_nodata(0, NoDataValue::Float(-9999.0))
805 .expect("should set");
806
807 let band = multi.band(0).expect("get");
808 assert_eq!(band.nodata(), NoDataValue::Float(-9999.0));
809 }
810
811 #[test]
812 fn test_band_mut() {
813 let buf = RasterBuffer::zeros(10, 10, RasterDataType::UInt8);
814 let mut multi = MultiBandBuffer::from_bands(vec![buf], vec![ColorInterpretation::Gray])
815 .expect("should create");
816
817 let band = multi.band_mut(0).expect("should get mut");
818 band.set_pixel(0, 0, 99.0).expect("should set");
819
820 let band = multi.band(0).expect("should get");
821 assert_eq!(band.buffer().get_pixel(0, 0).expect("should get"), 99.0);
822 }
823
824 #[test]
825 fn test_into_bands() {
826 let r = RasterBuffer::zeros(10, 10, RasterDataType::UInt8);
827 let g = RasterBuffer::zeros(10, 10, RasterDataType::UInt8);
828
829 let multi = MultiBandBuffer::from_bands(
830 vec![r, g],
831 vec![ColorInterpretation::Gray, ColorInterpretation::Alpha],
832 )
833 .expect("should create");
834
835 let bands = multi.into_bands();
836 assert_eq!(bands.len(), 2);
837 }
838
839 #[test]
840 fn test_from_bil_roundtrip() {
841 let bands = 2usize;
844 let height = 3usize;
845 let width = 4usize;
846 let mut bil: Vec<u8> = Vec::new();
848 for row in 0..height {
849 for band in 0..bands {
850 for col in 0..width {
851 bil.push(((band * 100 + row * 10 + col) & 0xFF) as u8);
852 }
853 }
854 }
855 let buf = MultiBandBuffer::from_bil(
856 &bil,
857 width as u64,
858 height as u64,
859 bands as u32,
860 RasterDataType::UInt8,
861 NoDataValue::None,
862 )
863 .expect("should create from BIL");
864 let back = buf.to_bil();
865 assert_eq!(bil, back, "BIL roundtrip failed");
866 }
867
868 #[test]
869 fn test_from_bil_to_bsq_equivalence() {
870 let (bands, height, width) = (2usize, 2usize, 3usize);
872 let mut bsq_data: Vec<u8> = Vec::new();
873 for band in 0..bands {
874 for row in 0..height {
875 for col in 0..width {
876 bsq_data.push((band * 10 + row * 3 + col) as u8);
877 }
878 }
879 }
880 let mut bil_data: Vec<u8> = vec![0; bands * height * width];
881 for band in 0..bands {
882 for row in 0..height {
883 for col in 0..width {
884 let bsq_idx = band * height * width + row * width + col;
885 let bil_idx = row * bands * width + band * width + col;
886 bil_data[bil_idx] = bsq_data[bsq_idx];
887 }
888 }
889 }
890 let from_bil = MultiBandBuffer::from_bil(
891 &bil_data,
892 width as u64,
893 height as u64,
894 bands as u32,
895 RasterDataType::UInt8,
896 NoDataValue::None,
897 )
898 .expect("should create from BIL");
899 let bsq_out = from_bil.to_bsq();
900 assert_eq!(bsq_data, bsq_out, "BSQ equivalence failed");
901 }
902
903 #[test]
904 fn test_from_bil_mismatched_size() {
905 let data: Vec<u8> = vec![0; 5];
907 let result =
908 MultiBandBuffer::from_bil(&data, 4, 3, 2, RasterDataType::UInt8, NoDataValue::None);
909 assert!(result.is_err(), "expected error for size mismatch");
910 }
911
912 #[test]
913 fn test_from_bil_various_types() {
914 for &(bands, height, width) in &[(2usize, 3usize, 4usize), (3usize, 2usize, 5usize)] {
916 let mut bil_u8: Vec<u8> = Vec::new();
918 for row in 0..height {
919 for band in 0..bands {
920 for col in 0..width {
921 bil_u8.push(((band * 100 + row * 10 + col) & 0xFF) as u8);
922 }
923 }
924 }
925 let buf = MultiBandBuffer::from_bil(
926 &bil_u8,
927 width as u64,
928 height as u64,
929 bands as u32,
930 RasterDataType::UInt8,
931 NoDataValue::None,
932 )
933 .expect("u8 from_bil should succeed");
934 let back = buf.to_bil();
935 assert_eq!(
936 bil_u8, back,
937 "u8 BIL roundtrip failed for {}x{}x{}",
938 bands, height, width
939 );
940
941 let mut bil_u16_raw: Vec<u8> = Vec::new();
943 for row in 0..height {
944 for band in 0..bands {
945 for col in 0..width {
946 let v: u16 = (band * 1000 + row * 10 + col) as u16;
947 bil_u16_raw.extend_from_slice(&v.to_ne_bytes());
948 }
949 }
950 }
951 let buf_u16 = MultiBandBuffer::from_bil(
952 &bil_u16_raw,
953 width as u64,
954 height as u64,
955 bands as u32,
956 RasterDataType::UInt16,
957 NoDataValue::None,
958 )
959 .expect("u16 from_bil should succeed");
960 let back_u16 = buf_u16.to_bil();
961 assert_eq!(
962 bil_u16_raw, back_u16,
963 "u16 BIL roundtrip failed for {}x{}x{}",
964 bands, height, width
965 );
966
967 let mut bil_f32_raw: Vec<u8> = Vec::new();
969 for row in 0..height {
970 for band in 0..bands {
971 for col in 0..width {
972 let v: f32 = (band * 100 + row * 10 + col) as f32 + 0.5;
973 bil_f32_raw.extend_from_slice(&v.to_ne_bytes());
974 }
975 }
976 }
977 let buf_f32 = MultiBandBuffer::from_bil(
978 &bil_f32_raw,
979 width as u64,
980 height as u64,
981 bands as u32,
982 RasterDataType::Float32,
983 NoDataValue::None,
984 )
985 .expect("f32 from_bil should succeed");
986 let back_f32 = buf_f32.to_bil();
987 assert_eq!(
988 bil_f32_raw, back_f32,
989 "f32 BIL roundtrip failed for {}x{}x{}",
990 bands, height, width
991 );
992 }
993 }
994
995 #[test]
996 fn test_default_color_interpretation() {
997 let colors_1 = default_color_interpretation(1);
998 assert_eq!(colors_1, vec![ColorInterpretation::Gray]);
999
1000 let colors_3 = default_color_interpretation(3);
1001 assert_eq!(
1002 colors_3,
1003 vec![
1004 ColorInterpretation::Red,
1005 ColorInterpretation::Green,
1006 ColorInterpretation::Blue,
1007 ]
1008 );
1009
1010 let colors_4 = default_color_interpretation(4);
1011 assert_eq!(
1012 colors_4,
1013 vec![
1014 ColorInterpretation::Red,
1015 ColorInterpretation::Green,
1016 ColorInterpretation::Blue,
1017 ColorInterpretation::Alpha,
1018 ]
1019 );
1020
1021 let colors_5 = default_color_interpretation(5);
1022 assert!(
1023 colors_5
1024 .iter()
1025 .all(|c| *c == ColorInterpretation::Undefined)
1026 );
1027 }
1028}