3

I'm trying to change dtype of a .jp2 Sentinel 2 image, with this code:

    with rasterio.open(tmp_file) as src:
    meta = src.meta
    meta.update(dtype=rasterio.uint16)
    array = src.read()
with rasterio.open(filename, 'w', **meta) as dst:
    dst.write_band(array.astype(rasterio.uint16), 1)

But once is stored, if I check the values of the array they have changed.

Original array: 

[[[10 10 10 ...  6  6  6]
  [10 10 10 ...  6  6  6]
  [10 10 10 ...  6  6  6]
  ...
  [10 10 10 ...  0  0  0]
  [10 10 10 ...  0  0  0]
  [ 4 10 10 ...  0  0  0]]]

Array when open new image: [[[21  8  8 ...  3 16 11]
  [ 8  0  0 ...  0  4  0]
  [ 8  0  0 ...  0  3  0]
  ...
  [ 7  0  0 ...  0  0  0]
  [20  7  7 ...  0  9  4]
  [ 9  3  1 ...  0  4  0]]]

And as you can see the transformation is not even consistent.

If I do the same but storing the image as a GTiff, then the values are preserved.

Do you why? Is there any way to avoid this?

1 Answer 1

3

The problem that you're encountering can be traced back to lossy compression.

have a look at https://gdal.org/drivers/raster/jp2openjpeg.html#lossless-compression. Lossless compression can be achieved if all the following creation options are defined.

QUALITY=100
REVERSIBLE=YES
YCBCR420=NO (which is the default)

The following script should work and create reproducible result:

# Read
with rasterio.open(f_in) as src:
    img = src.read(1)
    profile = src.profile

# Update
profile.update(dtype='uint16', driver='JP2OpenJPEG')
img = img.astype('uint16')

# Write
with rasterio.open(f_out, 'w', QUALITY='100', REVERSIBLE='YES',YCBCR420='NO', **profile) as dst:
    dst.write(img, 1)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.