Skip to content

Commit

Permalink
Merge pull request OSGeo#11857 from rouault/fix_11851
Browse files Browse the repository at this point in the history
GTiff: CreateCopy(): fix incorrect writing of mask band when COPY_SRC_OVERVIEWS=YES and INTERLEAVE=BAND (master only)
  • Loading branch information
rouault authored Feb 17, 2025
2 parents 4121bb8 + 3960fc8 commit 6773dd0
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 55 deletions.
71 changes: 23 additions & 48 deletions autotest/gcore/cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -1996,46 +1996,19 @@ def test_cog_preserve_ALPHA_PREMULTIPLIED_on_copy(tmp_vsimem):


@gdaltest.enable_exceptions()
def test_cog_write_interleave_tile(tmp_vsimem):
@pytest.mark.parametrize("INTERLEAVE", ["TILE", "BAND"])
def test_cog_write_interleave_tile_or_band(tmp_vsimem, INTERLEAVE):
out_filename = str(tmp_vsimem / "out.tif")

with gdal.quiet_errors():
gdal.GetDriverByName("COG").CreateCopy(
out_filename,
gdal.Open("data/rgbsmall.tif"),
options=["INTERLEAVE=TILE", "BLOCKSIZE=32"],
options=["INTERLEAVE=" + INTERLEAVE, "BLOCKSIZE=32"],
)

ds = gdal.Open(out_filename)
assert ds.GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE") == "TILE"
assert ds.GetMetadataItem("LAYOUT", "IMAGE_STRUCTURE") == "COG"

assert [ds.GetRasterBand(band + 1).Checksum() for band in range(3)] == [
21212,
21053,
21349,
]

_check_cog(out_filename)


###############################################################################
#


@gdaltest.enable_exceptions()
def test_cog_write_interleave_band(tmp_vsimem):
out_filename = str(tmp_vsimem / "out.tif")

with gdal.quiet_errors():
gdal.GetDriverByName("COG").CreateCopy(
out_filename,
gdal.Open("data/rgbsmall.tif"),
options=["INTERLEAVE=BAND", "BLOCKSIZE=32"],
)

ds = gdal.Open(out_filename)
assert ds.GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE") == "BAND"
assert ds.GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE") == INTERLEAVE
assert ds.GetMetadataItem("LAYOUT", "IMAGE_STRUCTURE") == "COG"

assert [ds.GetRasterBand(band + 1).Checksum() for band in range(3)] == [
Expand All @@ -2052,7 +2025,8 @@ def test_cog_write_interleave_band(tmp_vsimem):


@gdaltest.enable_exceptions()
def test_cog_write_interleave_tile_with_mask(tmp_vsimem):
@pytest.mark.parametrize("INTERLEAVE", ["TILE", "BAND"])
def test_cog_write_interleave_with_mask(tmp_vsimem, INTERLEAVE):
out_filename = str(tmp_vsimem / "out.tif")

with gdal.quiet_errors():
Expand All @@ -2061,11 +2035,11 @@ def test_cog_write_interleave_tile_with_mask(tmp_vsimem):
gdal.Translate(
"", "data/stefan_full_rgba.tif", options="-f MEM -b 1 -b 2 -b 3 -mask 4"
),
options=["INTERLEAVE=TILE", "BLOCKSIZE=32"],
options=["INTERLEAVE=" + INTERLEAVE, "BLOCKSIZE=32"],
)

ds = gdal.Open(out_filename)
assert ds.GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE") == "TILE"
assert ds.GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE") == INTERLEAVE
assert ds.GetMetadataItem("LAYOUT", "IMAGE_STRUCTURE") == "COG"

assert [ds.GetRasterBand(band + 1).Checksum() for band in range(3)] == [
Expand All @@ -2078,24 +2052,25 @@ def test_cog_write_interleave_tile_with_mask(tmp_vsimem):
_check_cog(out_filename)

# Check that the tiles are in the expected order in the file
last_offset = 0
for y in range(2):
for x in range(2):
for band in range(3):
offset = int(
ds.GetRasterBand(band + 1).GetMetadataItem(
f"BLOCK_OFFSET_{x}_{y}", "TIFF"
if INTERLEAVE == "TILE":
last_offset = 0
for y in range(2):
for x in range(2):
for band in range(3):
offset = int(
ds.GetRasterBand(band + 1).GetMetadataItem(
f"BLOCK_OFFSET_{x}_{y}", "TIFF"
)
)
assert offset > last_offset
last_offset = offset
offset = int(
ds.GetRasterBand(1)
.GetMaskBand()
.GetMetadataItem(f"BLOCK_OFFSET_{x}_{y}", "TIFF")
)
assert offset > last_offset
last_offset = offset
offset = int(
ds.GetRasterBand(1)
.GetMaskBand()
.GetMetadataItem(f"BLOCK_OFFSET_{x}_{y}", "TIFF")
)
assert offset > last_offset
last_offset = offset


###############################################################################
Expand Down
17 changes: 10 additions & 7 deletions frmts/gtiff/gtiffdataset_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6700,18 +6700,21 @@ CPLErr GTiffDataset::CopyImageryAndMask(GTiffDataset *poDstDS,
{
memset(pBlockBuffer, 0,
static_cast<size_t>(poDstDS->m_nBlockXSize) *
poDstDS->m_nBlockYSize * nDataTypeSize);
poDstDS->m_nBlockYSize);
}
eErr = poSrcMaskBand->RasterIO(
GF_Read, iX, iY, nReqXSize, nReqYSize, pBlockBuffer,
nReqXSize, nReqYSize, eType, nDataTypeSize,
static_cast<GSpacing>(nDataTypeSize) *
poDstDS->m_nBlockXSize,
nullptr);
nReqXSize, nReqYSize, GDT_Byte, 1,
poDstDS->m_nBlockXSize, nullptr);
if (eErr == CE_None)
{
eErr = poDstDS->m_poMaskDS->WriteEncodedTileOrStrip(
iBlockMask, pBlockBuffer, false);
// Avoid any attempt to load from disk
poDstDS->m_poMaskDS->m_nLoadedBlock = iBlockMask;
eErr =
poDstDS->m_poMaskDS->GetRasterBand(1)->WriteBlock(
nXBlock, nYBlock, pBlockBuffer);
if (eErr == CE_None)
eErr = poDstDS->m_poMaskDS->FlushBlockBuf();
}

iBlockMask++;
Expand Down

0 comments on commit 6773dd0

Please sign in to comment.