Take into account GDAL >= 3.7 GDT_Int8 signed int8 datatype (fixes #2635) (#2656)

This commit is contained in:
Even Rouault 2022-11-21 05:30:33 +01:00 committed by GitHub
parent 50db10b7c1
commit e4ecc02b9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 27 additions and 8 deletions

View File

@ -160,8 +160,10 @@ cdef _band_dtype(GDALRasterBandH band):
"""Resolve dtype of a given band, deals with signed/unsigned byte ambiguity"""
cdef const char * ptype
cdef int gdal_dtype = GDALGetRasterDataType(band)
if gdal_dtype == GDT_Byte:
# Can be uint8 or int8, need to check PIXELTYPE property
if gdal_dtype == GDT_Byte and dtypes.dtype_rev["int8"] == 1:
# Before GDAL 3.7, int8 was dealt by GDAL as a GDT_Byte (1)
# with PIXELTYPE=SIGNEDBYTE metadata item in IMAGE_STRUCTURE
# metadata domain.
ptype = GDALGetMetadataItem(band, 'PIXELTYPE', 'IMAGE_STRUCTURE')
if ptype and strncmp(ptype, 'SIGNEDBYTE', 10) == 0:
return 'int8'

View File

@ -1437,7 +1437,9 @@ cdef class DatasetWriterBase(DatasetReaderBase):
# if we can crosswalk those.
gdal_dtype = _get_gdal_dtype(self._init_dtype)
if _getnpdtype(self._init_dtype) == _getnpdtype('int8'):
# Before GDAL 3.7, int8 was dealt by GDAL as a GDT_Byte (1)
# with PIXELTYPE=SIGNEDBYTE creation option.
if _getnpdtype(self._init_dtype) == _getnpdtype('int8') and gdal_dtype == 1:
options = CSLSetNameValue(options, 'PIXELTYPE', 'SIGNEDBYTE')
# Create a GDAL dataset handle.

View File

@ -10,6 +10,7 @@ import numpy
from rasterio.env import GDALVersion
_GDAL_AT_LEAST_35 = GDALVersion.runtime().at_least("3.5")
_GDAL_AT_LEAST_37 = GDALVersion.runtime().at_least("3.7")
bool_ = 'bool'
ubyte = uint8 = 'uint8'
@ -47,10 +48,15 @@ if _GDAL_AT_LEAST_35:
dtype_fwd[12] = int64 # GDT_Int64
dtype_fwd[13] = uint64 # GDT_UInt64
if _GDAL_AT_LEAST_37:
dtype_fwd[14] = sbyte # GDT_Int8
dtype_rev = dict((v, k) for k, v in dtype_fwd.items())
dtype_rev["uint8"] = 1
dtype_rev["int8"] = 1
if not _GDAL_AT_LEAST_37:
dtype_rev["int8"] = 1
dtype_rev["complex"] = 11
dtype_rev["complex_int16"] = 8
@ -82,6 +88,9 @@ if _GDAL_AT_LEAST_35:
typename_fwd[12] = 'Int64'
typename_fwd[13] = 'UInt64'
if _GDAL_AT_LEAST_37:
typename_fwd[14] = 'Int8'
typename_rev = dict((v, k) for k, v in typename_fwd.items())
dtype_ranges = {

View File

@ -221,6 +221,7 @@ cdef extern from "gdal.h" nogil:
ctypedef enum GDALDataType:
GDT_Unknown
GDT_Byte
GDT_Int8
GDT_UInt16
GDT_Int16
GDT_UInt32

View File

@ -3,9 +3,12 @@ import numpy
import pytest
import rasterio
from rasterio.env import GDALVersion
gdal_version = GDALVersion.runtime()
@pytest.mark.xfail(reason="Likely upstream bug")
@pytest.mark.xfail(gdal_version < GDALVersion(3, 7), reason="GDAL < 3.7 doesn't handle signed int8 correctly")
@pytest.mark.parametrize("nodata", [-1, -128])
def test_write_int8_mem(nodata):
profile = {

View File

@ -12,10 +12,9 @@ from .conftest import requires_gdal35, gdal_version
import rasterio
from rasterio.drivers import blacklist
from rasterio.enums import MaskFlags, Resampling
from rasterio.env import Env
from rasterio.env import Env, GDALVersion
from rasterio.errors import RasterioIOError
def test_validate_dtype_None(tmpdir):
"""Raise TypeError if there is no dtype"""
name = str(tmpdir.join("lol.tif"))
@ -118,7 +117,10 @@ def test_write_sbyte(tmpdir):
info = subprocess.check_output(["gdalinfo", "-stats", name]).decode('utf-8')
assert "Minimum=-33.000, Maximum=-33.000, Mean=-33.000, StdDev=0.000" in info
assert 'SIGNEDBYTE' in info
if GDALVersion.runtime() < GDALVersion(3, 7):
assert 'SIGNEDBYTE' in info
else:
assert 'Int8' in info
@pytest.mark.gdalbin