@@ -1179,6 +1179,37 @@ class RasterFunctionsSpec extends TestEnvironment with RasterMatchers {
11791179 checker(" qa_cconf" , cirrus, 1 ) // low cloud conf
11801180 checker(" qa_circonf" , cirrus, 3 ) // high cirrus conf
11811181 }
1182+ it(" should extract bits from different cell types" ) {
1183+ import org .locationtech .rasterframes .expressions .transformers .ExtractBits
1184+
1185+ case class TestCase [N : Numeric ](cellType : CellType , cellValue : N , bitPosition : Int , numBits : Int , expectedValue : Int ) {
1186+ def testIt (): Unit = {
1187+ val tile = projectedRasterTile(3 , 3 , cellValue, TestData .extent, TestData .crs, cellType)
1188+ val extracted = ExtractBits (tile, bitPosition, numBits)
1189+ all(extracted.toArray()) should be (expectedValue)
1190+ }
1191+ }
1192+
1193+ Seq (
1194+ TestCase (BitCellType , 1 , 0 , 1 , 1 ),
1195+ TestCase (ByteCellType , 127 , 6 , 2 , 1 ), // 7th bit is sign
1196+ TestCase (ByteCellType , 127 , 5 , 2 , 3 ),
1197+ TestCase (ByteCellType , - 128 , 6 , 2 , 2 ), // 7th bit is sign
1198+ TestCase (UByteCellType , 255 , 6 , 2 , 3 ),
1199+ TestCase (UByteCellType , 255 , 10 , 2 , 0 ), // shifting beyond range of cell type results in 0
1200+ TestCase (ShortCellType , 32767 , 15 , 1 , 0 ),
1201+ TestCase (ShortCellType , 32767 , 14 , 2 , 1 ),
1202+ TestCase (ShortUserDefinedNoDataCellType (0 ), - 32768 , 14 , 2 , 2 ),
1203+ TestCase (UShortCellType , 65535 , 14 , 2 , 3 ),
1204+ TestCase (UShortCellType , 65535 , 18 , 2 , 0 ), // shifting beyond range of cell type results in 0
1205+ TestCase (IntCellType , 2147483647 , 30 , 2 , 1 ),
1206+ TestCase (IntCellType , 2147483647 , 29 , 2 , 3 )
1207+ ).foreach(_.testIt)
1208+
1209+ // floating point types
1210+ an [AssertionError ] should be thrownBy TestCase [Float ](FloatCellType , Float .MaxValue , 29 , 2 , 3 ).testIt()
1211+
1212+ }
11821213 it(" should mask by QA bits" ){
11831214 val result = df
11841215 .withColumn(" fill_no" , rf_mask_by_bit($" data" , $" mask" , 0 , true ))
0 commit comments