What is the valid range for the TCI product?

tldr: what’s the valid range for values in the TCI product? Is it 0-255, with no value for nodata? Or 1-255, with 0 being used for nodata?

I’m investigating an issue reported by a user at Problems with COG images downloaded from the Planetary Computer API - Data - Pangeo. That’s comparing a Cloud Optimized GeoTIFF created from the sen2cor output to the original TCI image from Copernicus.

Those white pixels in the water are values where one or more of the bands in the TCI output by sen2cor have a value of zero. As part of our COG conversion, we call gdal_translate with -a_nodata 0. We set that based on the text from User Guides - Sentinel-2 MSI - Definitions - Sentinel Online - Sentinel Online

The TCI is an RGB image built from the B02 (Blue), B03 (Green), and B04 (Red) Bands. The reflectances are coded between 1 and 255, 0 being reserved for ‘No Data’.

That makes it sound like the valid output values should be between 1 and 255. I checked the SCL output, and all those pixels in the top-left are (correctly) classified as water. So sen2cor thinks they’re valid pixels, but outputs a value of 0 for the darkest pixels. This shows reading the output of sen2cor (so before I add the nodata metadata), and shows that the red band is 0 at this pixel.

In [39]: ds = rasterio.open("data/l2a/jp2000/S2B_MSIL2A_20230111T121649_N0400_R066_T27PTS_20230117T211543.SAFE/GRANULE/L2A_T27PTS_A030551_20230111T121647/IMG_DATA/R10m/T27PTS_20230111T121649_TCI_10m.jp2")

In [40]: ds.read(window=rasterio.windows.Window(0, 4, 1, 1))


       [[9]]], dtype=uint8)

This can be reproduced locally with:

gdal_translate data/l2a/jp2000/S2B_MSIL2A_20230111T121649_N0400_R066_T27PTS_20230117T211543.SAFE/GRANULE/L2A_T27PTS_A030551_20230111T121647/IMG_DATA/R10m/T27PTS_20230111T121649_TCI_10m.jp2 ../T27PTS_20230111T121649_TCI_10m.tif -of COG -a_nodata 0 -co COMPRESS=DEFLATE -co OVERVIEW_RESAMPLING=cubic


I received a reply from ESA support about this:

Indeed, a change occurs with Processing Baseline 04.00 in January 2022 with the introduction of a radiometric offset allowing to keep these negative surface reflectance values.

It appears that this change has not been handled correctly for the generation of the TCI in the standalone version of Sen2Cor. The Sen2Cor team has reproduced the issue observed by the user, and a fix will be proposed soon in a future version of Sen2Cor.

On the other hand, the issue does not appear in the official ESA products as the TCI is generated in another way.

To conclude, it is true to say that the reflectances in the TCI are coded between 1 and 255, 0 being reserved for ‘No Data’. So far, using the standalone version of Sen2Cor, a 0 in the TCI could also depict a negative reflectance in the B02, B03 or B04 band. But this is a wrong behaviour that will be fix soon.

Dear user,

Yes we have reproduced the issue observed and a fix will be proposed in the next version of Sen2Cor. The issue only affects the TCI creation in the standalone version of Sen2Cor. The bands B04, B03, B02 located in the IMG_DATA folder are not affected.


1 Like