diff --git a/autotest/gcore/cog.py b/autotest/gcore/cog.py index b3046fb61825..d4176763f0e4 100755 --- a/autotest/gcore/cog.py +++ b/autotest/gcore/cog.py @@ -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)] == [ @@ -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(): @@ -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)] == [ @@ -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 ############################################################################### diff --git a/frmts/gtiff/gtiffdataset_write.cpp b/frmts/gtiff/gtiffdataset_write.cpp index 1829db745a35..31853e296242 100644 --- a/frmts/gtiff/gtiffdataset_write.cpp +++ b/frmts/gtiff/gtiffdataset_write.cpp @@ -6700,18 +6700,21 @@ CPLErr GTiffDataset::CopyImageryAndMask(GTiffDataset *poDstDS, { memset(pBlockBuffer, 0, static_cast(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(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++;