@@ -4,11 +4,12 @@ use crate::metadata::Metadata;
4
4
use crate :: raster:: { GDALDataType , GdalType } ;
5
5
use crate :: utils:: { _last_cpl_err, _last_null_pointer_err, _string} ;
6
6
use gdal_sys:: {
7
- self , CPLErr , GDALColorInterp , GDALMajorObjectH , GDALRWFlag , GDALRasterBandH ,
8
- GDALRasterIOExtraArg ,
7
+ self , CPLErr , GDALColorEntry , GDALColorInterp , GDALColorTableH , GDALMajorObjectH ,
8
+ GDALPaletteInterp , GDALRWFlag , GDALRasterBandH , GDALRasterIOExtraArg ,
9
9
} ;
10
10
use libc:: c_int;
11
11
use std:: ffi:: CString ;
12
+ use std:: marker:: PhantomData ;
12
13
13
14
#[ cfg( feature = "ndarray" ) ]
14
15
use ndarray:: Array2 ;
@@ -421,6 +422,15 @@ impl<'a> RasterBand<'a> {
421
422
Ok ( ( ) )
422
423
}
423
424
425
+ /// Get the color table for this band if it has one.
426
+ pub fn color_table ( & self ) -> Option < ColorTable > {
427
+ let c_color_table = unsafe { gdal_sys:: GDALGetRasterColorTable ( self . c_rasterband ) } ;
428
+ if c_color_table. is_null ( ) {
429
+ return None ;
430
+ }
431
+ Some ( ColorTable :: from_c_color_table ( c_color_table) )
432
+ }
433
+
424
434
/// Returns the scale of this band if set.
425
435
pub fn scale ( & self ) -> Option < f64 > {
426
436
let mut pb_success = 1 ;
@@ -612,3 +622,144 @@ impl ColorInterpretation {
612
622
_string ( rv)
613
623
}
614
624
}
625
+
626
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
627
+ pub enum PaletteInterpretation {
628
+ Gray ,
629
+ Rgba ,
630
+ Cmyk ,
631
+ Hls ,
632
+ }
633
+
634
+ impl PaletteInterpretation {
635
+ fn from_c_int ( palette_interpretation : GDALPaletteInterp :: Type ) -> Self {
636
+ match palette_interpretation {
637
+ GDALPaletteInterp :: GPI_Gray => Self :: Gray ,
638
+ GDALPaletteInterp :: GPI_RGB => Self :: Rgba ,
639
+ GDALPaletteInterp :: GPI_CMYK => Self :: Cmyk ,
640
+ GDALPaletteInterp :: GPI_HLS => Self :: Hls ,
641
+ _ => unreachable ! ( "GDAL has implemented a new type of `GDALPaletteInterp`" ) ,
642
+ }
643
+ }
644
+ }
645
+
646
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
647
+ pub struct GrayEntry {
648
+ pub g : i16 ,
649
+ }
650
+
651
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
652
+ pub struct RgbaEntry {
653
+ pub r : i16 ,
654
+ pub g : i16 ,
655
+ pub b : i16 ,
656
+ pub a : i16 ,
657
+ }
658
+
659
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
660
+ pub struct CmykEntry {
661
+ pub c : i16 ,
662
+ pub m : i16 ,
663
+ pub y : i16 ,
664
+ pub k : i16 ,
665
+ }
666
+
667
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
668
+ pub struct HlsEntry {
669
+ pub h : i16 ,
670
+ pub l : i16 ,
671
+ pub s : i16 ,
672
+ }
673
+
674
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
675
+ pub enum ColorEntry {
676
+ Gray ( GrayEntry ) ,
677
+ Rgba ( RgbaEntry ) ,
678
+ Cmyk ( CmykEntry ) ,
679
+ Hls ( HlsEntry ) ,
680
+ }
681
+
682
+ /// Color table for raster bands that use the PaletteIndex color interpretation.
683
+ ///
684
+ /// This object carries the lifetime of the raster band that
685
+ /// contains it. This is necessary to prevent the raster band
686
+ /// from being dropped before the color table.
687
+ pub struct ColorTable < ' a > {
688
+ palette_interpretation : PaletteInterpretation ,
689
+ c_color_table : GDALColorTableH ,
690
+ phantom_raster_band : PhantomData < & ' a RasterBand < ' a > > ,
691
+ }
692
+
693
+ impl < ' a > ColorTable < ' a > {
694
+ fn from_c_color_table ( c_color_table : GDALColorTableH ) -> Self {
695
+ let interp_index = unsafe { gdal_sys:: GDALGetPaletteInterpretation ( c_color_table) } ;
696
+ ColorTable {
697
+ palette_interpretation : PaletteInterpretation :: from_c_int ( interp_index) ,
698
+ c_color_table,
699
+ phantom_raster_band : PhantomData ,
700
+ }
701
+ }
702
+
703
+ /// How the values of this color table are interpreted.
704
+ pub fn palette_interpretation ( & self ) -> PaletteInterpretation {
705
+ self . palette_interpretation
706
+ }
707
+
708
+ /// Get the number of color entries in this color table.
709
+ pub fn entry_count ( & self ) -> usize {
710
+ unsafe { gdal_sys:: GDALGetColorEntryCount ( self . c_color_table ) as usize }
711
+ }
712
+
713
+ /// Get a color entry.
714
+ pub fn entry ( & self , index : usize ) -> Option < ColorEntry > {
715
+ let color_entry = unsafe {
716
+ let c_color_entry = gdal_sys:: GDALGetColorEntry ( self . c_color_table , index as i32 ) ;
717
+ if c_color_entry. is_null ( ) {
718
+ return None ;
719
+ }
720
+ * c_color_entry
721
+ } ;
722
+ match self . palette_interpretation {
723
+ PaletteInterpretation :: Gray => Some ( ColorEntry :: Gray ( GrayEntry { g : color_entry. c1 } ) ) ,
724
+ PaletteInterpretation :: Rgba => Some ( ColorEntry :: Rgba ( RgbaEntry {
725
+ r : color_entry. c1 ,
726
+ g : color_entry. c2 ,
727
+ b : color_entry. c3 ,
728
+ a : color_entry. c4 ,
729
+ } ) ) ,
730
+ PaletteInterpretation :: Cmyk => Some ( ColorEntry :: Cmyk ( CmykEntry {
731
+ c : color_entry. c1 ,
732
+ m : color_entry. c2 ,
733
+ y : color_entry. c3 ,
734
+ k : color_entry. c4 ,
735
+ } ) ) ,
736
+ PaletteInterpretation :: Hls => Some ( ColorEntry :: Hls ( HlsEntry {
737
+ h : color_entry. c1 ,
738
+ l : color_entry. c2 ,
739
+ s : color_entry. c3 ,
740
+ } ) ) ,
741
+ }
742
+ }
743
+
744
+ /// Get a color entry as RGB.
745
+ pub fn entry_as_rgb ( & self , index : usize ) -> Option < RgbaEntry > {
746
+ let mut color_entry = GDALColorEntry {
747
+ c1 : 0 ,
748
+ c2 : 0 ,
749
+ c3 : 0 ,
750
+ c4 : 0 ,
751
+ } ;
752
+ if unsafe {
753
+ gdal_sys:: GDALGetColorEntryAsRGB ( self . c_color_table , index as i32 , & mut color_entry)
754
+ } == 0
755
+ {
756
+ return None ;
757
+ }
758
+ Some ( RgbaEntry {
759
+ r : color_entry. c1 ,
760
+ g : color_entry. c2 ,
761
+ b : color_entry. c3 ,
762
+ a : color_entry. c4 ,
763
+ } )
764
+ }
765
+ }
0 commit comments