Sentinel-2 L2A saturation: different values for different resolutions

We are struggling how to deal with (mask out) saturated values over bright targets in Sentinel-2 L2A images.
An example can be seen in product S2A_MSIL2A_20200615T024551_N0500_R132_T50SNC_20230403T155614: Copernicus Browser. The issue is not visible in L1C: Copernicus Browser.
The figure below shows L2A - SCL - L1C.


What is puzzling is the DN of the affected pixels. According to the metadata, 0=NODATA, 65535=SATURATED:

But the data show up as 0 in 10m bands, and 32767 in 60m bands:

Why do we see this difference between the resolutions, and how to deal with this? Should we discard all pixels with DN == 0 and with DN >= 32767?
Thanks for your advice.

To complement @cartot question:

In the same product, after applying the -1000 offset we see that the nodata and saturated pixels become 0. But we also see shadow/dark pixels at 0 intensity.
In baseline <4, 0 was used as nodata value for sentinel-2 bands, which was useful as a user does not need to open also the SCL just to check the nodata.

Is this intended? wouldn’t be better to reserve -1000 (or 0 after offset) for NODATA? This would be consistent with the behavior in the older baselines.

Lastly, why is the saturation value 32767 when the data is stored in uint16? not crucial as it’s anyway bright cloudy pixels usually, but the values could go up to (65536-1000) which could be used as a special value for saturated pixels.

Dear @cartot ,

Thank you for your message.

There are several aspects to be discussed.

The issue you observed seems limited to the 10 m bands. It is related to a memory optimisation that can lead to a bad clipping of the reflectance data at a value of 32768, further propagated to a 0 value in JP2 file when the JPEG2000 encoding is performed on the Sen2Cor raw data outputs.

The current nominal behaviour is the one of the 20 m bands and 60 m bands which “saturate” at a value of 32767, to cope with the 32767 limitation of the JPEG2000 encoding. You can filter out the values == 32767 as saturated. There should not be any value > 32767 due to the JPEG2000 encoding configuration.

For 10 m bands, the recommendation to mask out those saturated values over bright clouds is to rely on the Scene Classification (SCL) map available at 20 m that requires to be resampled to 10 m using nearest neighbour method. Those pixels are mostly classified as clouds with a SCL value of 9 (more rarely 8 value). You can obtain the corresponding saturation mask by combining these conditions: (value == 0) & (SCL == 9).
Including the 8 value: saturated = (value == 0) AND ((SCL == 9) OR (SCL == 8)).

A parallel investigation is on-going on the JPEG2000 encoding limitation to 32767 and a fix could be prepared to cope with the issue of the different behaviour for 10 m and 20/60 m bands.

Cheers,
@Sen2cor_dev_team

1 Like

Thanks for your reply, @Sen2cor_dev_team, all clear now!

Your are welcome!