@@ -81,3 +81,83 @@ def apply(self, img: ImageData) -> ImageData:
8181 crs = img .crs ,
8282 bounds = img .bounds ,
8383 )
84+
85+
86+ class Terrarium (BaseAlgorithm ):
87+ """Encode DEM into RGB (Mapzen Terrarium)."""
88+
89+ input_nbands : int = 1
90+
91+ output_nbands : int = 3
92+ output_dtype : str = "uint8"
93+
94+ def apply (self , img : ImageData ) -> ImageData :
95+ """Encode DEM into RGB."""
96+ data = numpy .clip (img .data [0 ] + 32768.0 , 0.0 , 65535.0 )
97+ r = data / 256
98+ g = data % 256
99+ b = (data * 256 ) % 256
100+ arr = numpy .stack ([r , g , b ]).astype (numpy .uint8 )
101+ print (arr .shape )
102+ return ImageData (
103+ arr ,
104+ img .mask ,
105+ assets = img .assets ,
106+ crs = img .crs ,
107+ bounds = img .bounds ,
108+ )
109+
110+
111+ class TerrainRGB (BaseAlgorithm ):
112+ """Encode DEM into RGB (Mapbox Terrain RGB)."""
113+
114+ interval : int = 1
115+ baseval : int = - 10000
116+
117+ input_nbands : int = 1
118+
119+ output_nbands : int = 3
120+ output_dtype : str = "uint8"
121+
122+ def apply (self , img : ImageData ) -> ImageData :
123+ """Encode DEM into RGB (Mapbox Terrain RGB).
124+
125+ Code from https://github.com/mapbox/rio-rgbify/blob/master/rio_rgbify/encoders.py (MIT)
126+
127+ """
128+
129+ def _range_check (datarange ):
130+ """
131+ Utility to check if data range is outside of precision for 3 digit base 256
132+ """
133+ maxrange = 256 ** 3
134+
135+ return datarange > maxrange
136+
137+ round_digits = 0
138+
139+ data = img .data [0 ].astype (numpy .float64 )
140+ data -= self .baseval
141+ data /= self .interval
142+
143+ data = numpy .around (data / 2 ** round_digits ) * 2 ** round_digits
144+
145+ rows , cols = data .shape
146+ datarange = data .max () - data .min ()
147+ if _range_check (datarange ):
148+ raise ValueError ("Data of {} larger than 256 ** 3" .format (datarange ))
149+
150+ rgb = numpy .zeros ((3 , rows , cols ), dtype = numpy .uint8 )
151+ rgb [2 ] = ((data / 256 ) - (data // 256 )) * 256
152+ rgb [1 ] = (((data // 256 ) / 256 ) - ((data // 256 ) // 256 )) * 256
153+ rgb [0 ] = (
154+ (((data // 256 ) // 256 ) / 256 ) - (((data // 256 ) // 256 ) // 256 )
155+ ) * 256
156+
157+ return ImageData (
158+ rgb ,
159+ img .mask ,
160+ assets = img .assets ,
161+ crs = img .crs ,
162+ bounds = img .bounds ,
163+ )
0 commit comments