Raster Bit Masks: Making Sense of the Numbers

Liz Sanderson
Liz Sanderson
  • Updated

FME Version

  • FME 2021.2

Introduction

This exercise is fairly advanced. It will cover bit masks, bitshift and logical operations. Here we will take a look at some of the supplementary information which is collected and calculated by Landsat to help with the data quality assessment (QA). You can read more about working with Landsat's QA in this guide from Landsat.

 

What is the QA Band?

From the Landsat Quality Assessment (QA) Tools User Guide
Each pixel In the quality assessment band (BQA) contains a decimal value that represents bit-packed combinations of surface, atmosphere and sensor conditions that can affect the overall usefulness of a given pixel. 

Knowing this, we can color the image based on these values. The integer numbers here are really just representations of binary strings where each 0 or 1 (or pair) has a specific meaning.

The integer numbers here are really just representations of binary strings where each 0 or 1 (or pair) has a specific meaning.

Using a simple 4-bit example:

Integer - Binary String
     0 	- 0000  
     1 	- 0001
     2 	- 0010
     3	- 0011
     4 	- 0100	

We can say, for the example, that the first bit (0 or 1) from the right represents:

Data Present: 0 = nodata, 1 = data, the second bit can mean snow, the third - cloud, the fourth - water.

If we look at the integer '3' above we can say the following based on the 0011 binary sting: Going from right to left - Yes we have data (1), yes, there is snow detected (1), no clouds (0) and no water (0).

Here is a handy online service which can convert decimal to binary and back

 

Step-by-step Instructions

1. Add Landsat Data
Open FME Workbench and start a blank workspace. Add a GeoTiff reader to the canvas and browse to the LC80470252014258LGN00_BQA.TIF dataset which is available for download from the Files section on this article. This is a quality assessment band. 
GeoTiffReader.png

2. Inspect Cell Values
Before we go any further, let’s explore the data. Inspect the GEOTIFF reader feature type by single-clicking on it to open the popup menu, then click on View Source Data. With the data open in Visual Preview, explore the properties using the Feature Information window. 
InitialVP.png
 
Notice that there is only a single GRAY16 band and no palette. 

3. Convert GREY16 to UINT16
Let’s convert the GREY16 band to UINT16 so that we can use the UINTasBINPaletteAdder custom transformer to manipulate the binary values. Add a RasterInterpretationCoercer to the canvas and connect it to the GEOTIFF reader feature type. In the parameters, change the Destination Interpretation Type to UINT16. 
RasterInterpretationCoercer.png

If we inspect the raster right now, it will appear like nothing has changed yet except for the band interpretation. 

4. Add a UINTasBINPaletteAdder
Add a UINTasBINPaletteAdder custom transformer to the canvas and connect it to the RasterInterpretationCoercer. Before we run the workspace, let’s investigate what this transformer is doing. Right-click on the UINTasBINPaletteAdder and click Edit. This is a large workspace, but find the AttributeCreator_7 and open the parameters. 
AttributeCreator_7.png

This equation seems very intimidating, but it is actually a concatenation of very simple expressions which use bit-wise operations.

@Evaluate(@Evaluate((@int64(@Value(_elevation))>>15)&1)@Evaluate((@int64(@Value(_elevation))>>14)&1)@Evaluate((@int64(@Value(_elevation))>>13)&1)@Evaluate((@int64(@Value(_elevation))>>12)&1)@Evaluate((@int64(@Value(_elevation))>>11)&1)@Evaluate((@int64(@Value(_elevation))>>10)&1)@Evaluate((@int64(@Value(_elevation))>>9)&1)@Evaluate((@int64(@Value(_elevation))>>8)&1)@Evaluate((@int64(@Value(_elevation))>>7)&1)@Evaluate((@int64(@Value(_elevation))>>6)&1)@Evaluate((@int64(@Value(_elevation))>>5)&1)@Evaluate((@int64(@Value(_elevation))>>4)&1)@Evaluate((@int64(@Value(_elevation))>>3)&1)@Evaluate((@int64(@Value(_elevation))>>2)&1)@Evaluate((@int64(@Value(_elevation))>>1)&1)@Evaluate((@int64(@Value(_elevation))&1)))

Taking one part of this as an example we can find the following:

@Value(_elevation))>>3)&1

_elevation, in this case, is our pixel value for this example let’s say we have 216. This corresponds to a binary value of ‘11011000’ (You can check this with the converter above).

The next part (216 >> 3) performs a logical bitwise right shift operation which shifts the binary to the right three places so 11011000 (or decimal 216) becomes 00011011 (or decimal 27).

The final part (27 & 1) compares the binary strings of each using the bit-wise Logical AND operation. We compare 11011 (27 without the leading 0’s) to 00001. This results in a value of 00001 (or just 1 without the leading 0’s).

Putting all of the expressions together we get either a 0 or a 1 for each of the 16 expressions, the concatenated result is the binary string of the original pixel value. The binary number is then passed into a StingFormatter which pads the number out to 16 digits by creating leading 0's where needed.

Each bit represents the following:

makingsense.png

You can also check out this pdf guide from Landsat for more information on how to interpret the bits.

5. Inspect Mask with Palette
Close the UINTasBINPaletteAdder edit, then add an Inspector to the UINTasBINPaletteAdder output port. Run the workspace and view the output in Visual Preview. In the Feature Information window, you will see that there is now a palette as well the values have been converted to binary. 
BinaryVP.png
 
6. Add Color
Finally, let’s add some color to this raster. Add an AttributeCreator to the canvas and connect it to the output port of the UINTasBINPaletteAdder. Create a new attribute called _palette then for Value open the text editor by clicking on the ellipsis. We can create a palette by copying and pasting the RGB triads below: 

RGB24
1 0,0,0
20480 0,0,0
20512 0,255,0
20516 200,200,255
23552 127,127,127
28672 255,127,255
28704 255,127,255
36864 127,127,127
36896 0,255,0
39936 127,127,127
45056 255,127,255
53248 255,127,0
53280 255,127,0
61440 255,127,0

RGBAttributeCreator.png

7. Add Palette
The final step before we can view the results is to add the newly created palette to the raster image. Add a RasterPaletteAdder to the canvas and connect it to the AttributeCreator. In the parameters, set the Palette Attribute to _palette. 
RasterPaletteAdder.png

8. Run the Workspace and View Results
Add or move the Inspector to connect it to the RasterPaletteAdder, then run the workspace. View the output in Visual Preview. 
Output.png
In the Feature Information window, we can see that the raster has two palettes, one containing the binary string and once with the RGB colors we created. The majority of the image is green which corresponds to a high confidence of vegetation, we also see some detection of snow or ice represented by the greys and in the top right region, we can see some pink which represents the presence of Cirrus clouds. 

Was this article helpful?

Comments

0 comments

Please sign in to leave a comment.