13#ifndef GDAL_CACHED_PIXEL_ACCESSOR_INCLUDED
14#define GDAL_CACHED_PIXEL_ACCESSOR_INCLUDED
36template <
class Type,
int TILE_SIZE,
int CACHED_TILE_COUNT = 4>
37class GDALCachedPixelAccessor
43 std::vector<Type> m_data{};
46 bool m_bModified =
false;
49 int m_nCachedTileCount = 0;
50 std::array<CachedTile, CACHED_TILE_COUNT> m_aCachedTiles{};
52 bool LoadTile(
int nTileX,
int nTileY);
53 bool FlushTile(
int iSlot);
55 Type GetSlowPath(
int nTileX,
int nTileY,
int nXInTile,
int nYInTile,
57 bool SetSlowPath(
int nTileX,
int nTileY,
int nXInTile,
int nYInTile,
60 GDALCachedPixelAccessor(
const GDALCachedPixelAccessor &) =
delete;
61 GDALCachedPixelAccessor &
62 operator=(
const GDALCachedPixelAccessor &) =
delete;
74 Type
Get(
int nX,
int nY,
bool *pbSuccess =
nullptr);
75 bool Set(
int nX,
int nY, Type val);
97template <
class Type,
int TILE_SIZE,
int CACHED_TILE_COUNT>
98GDALCachedPixelAccessor<Type, TILE_SIZE, CACHED_TILE_COUNT>::
112template <
class Type,
int TILE_SIZE,
int CACHED_TILE_COUNT>
132template <
class Type,
int TILE_SIZE,
int CACHED_TILE_COUNT>
134 int nX,
int nY,
bool *pbSuccess)
136 const int nTileX = nX / TILE_SIZE;
137 const int nTileY = nY / TILE_SIZE;
138 const int nXInTile = nX % TILE_SIZE;
139 const int nYInTile = nY % TILE_SIZE;
140 if (m_aCachedTiles[0].m_nTileX == nTileX &&
141 m_aCachedTiles[0].m_nTileY == nTileY)
145 return m_aCachedTiles[0].m_data[nYInTile * TILE_SIZE + nXInTile];
147 return GetSlowPath(nTileX, nTileY, nXInTile, nYInTile, pbSuccess);
154template <
class Type,
int TILE_SIZE,
int CACHED_TILE_COUNT>
155Type GDALCachedPixelAccessor<Type, TILE_SIZE, CACHED_TILE_COUNT>::GetSlowPath(
156 int nTileX,
int nTileY,
int nXInTile,
int nYInTile,
bool *pbSuccess)
158 for (
int i = 1; i < m_nCachedTileCount; ++i)
160 const auto &cachedTile = m_aCachedTiles[i];
161 if (cachedTile.m_nTileX == nTileX && cachedTile.m_nTileY == nTileY)
163 const auto ret = cachedTile.m_data[nYInTile * TILE_SIZE + nXInTile];
164 CachedTile tmp = std::move(m_aCachedTiles[i]);
165 for (
int j = i; j >= 1; --j)
166 m_aCachedTiles[j] = std::move(m_aCachedTiles[j - 1]);
167 m_aCachedTiles[0] = std::move(tmp);
173 if (!LoadTile(nTileX, nTileY))
181 return m_aCachedTiles[0].m_data[nYInTile * TILE_SIZE + nXInTile];
204template <
class Type,
int TILE_SIZE,
int CACHED_TILE_COUNT>
209 const int nTileX = nX / TILE_SIZE;
210 const int nTileY = nY / TILE_SIZE;
211 const int nXInTile = nX % TILE_SIZE;
212 const int nYInTile = nY % TILE_SIZE;
213 if (m_aCachedTiles[0].m_nTileX == nTileX &&
214 m_aCachedTiles[0].m_nTileY == nTileY)
216 m_aCachedTiles[0].m_data[nYInTile * TILE_SIZE + nXInTile] = val;
217 m_aCachedTiles[0].m_bModified =
true;
220 return SetSlowPath(nTileX, nTileY, nXInTile, nYInTile, val);
227template <
class Type,
int TILE_SIZE,
int CACHED_TILE_COUNT>
228bool GDALCachedPixelAccessor<Type, TILE_SIZE, CACHED_TILE_COUNT>::SetSlowPath(
229 int nTileX,
int nTileY,
int nXInTile,
int nYInTile, Type val)
231 for (
int i = 1; i < m_nCachedTileCount; ++i)
233 auto &cachedTile = m_aCachedTiles[i];
234 if (cachedTile.m_nTileX == nTileX && cachedTile.m_nTileY == nTileY)
236 cachedTile.m_data[nYInTile * TILE_SIZE + nXInTile] = val;
237 cachedTile.m_bModified =
true;
240 CachedTile tmp = std::move(m_aCachedTiles[i]);
241 for (
int j = i; j >= 1; --j)
242 m_aCachedTiles[j] = std::move(m_aCachedTiles[j - 1]);
243 m_aCachedTiles[0] = std::move(tmp);
248 if (!LoadTile(nTileX, nTileY))
252 m_aCachedTiles[0].m_data[nYInTile * TILE_SIZE + nXInTile] = val;
253 m_aCachedTiles[0].m_bModified =
true;
265template <
class Type,
int TILE_SIZE,
int CACHED_TILE_COUNT>
269 for (
int i = 0; i < m_nCachedTileCount; ++i)
273 m_aCachedTiles[i].m_nTileX = -1;
274 m_aCachedTiles[i].m_nTileY = -1;
285template <
class Type,
int TILE_SIZE,
int CACHED_TILE_COUNT>
289 for (
int i = 0; i < m_nCachedTileCount; ++i)
291 m_aCachedTiles[i].m_bModified =
false;
300template <
class T>
struct GDALCachedPixelAccessorGetDataType
304template <>
struct GDALCachedPixelAccessorGetDataType<
GByte>
309template <>
struct GDALCachedPixelAccessorGetDataType<
GInt8>
314template <>
struct GDALCachedPixelAccessorGetDataType<
GUInt16>
319template <>
struct GDALCachedPixelAccessorGetDataType<
GInt16>
324template <>
struct GDALCachedPixelAccessorGetDataType<
GUInt32>
329template <>
struct GDALCachedPixelAccessorGetDataType<
GInt32>
333#if SIZEOF_UNSIGNED_LONG == 8
335template <>
struct GDALCachedPixelAccessorGetDataType<unsigned long>
340template <>
struct GDALCachedPixelAccessorGetDataType<long>
345template <>
struct GDALCachedPixelAccessorGetDataType<
GUInt64>
350template <>
struct GDALCachedPixelAccessorGetDataType<
GInt64>
355template <>
struct GDALCachedPixelAccessorGetDataType<GFloat16>
360template <>
struct GDALCachedPixelAccessorGetDataType<float>
365template <>
struct GDALCachedPixelAccessorGetDataType<double>
376template <
class Type,
int TILE_SIZE,
int CACHED_TILE_COUNT>
377bool GDALCachedPixelAccessor<Type, TILE_SIZE, CACHED_TILE_COUNT>::LoadTile(
378 int nTileX,
int nTileY)
380 if (m_nCachedTileCount == CACHED_TILE_COUNT)
382 if (!FlushTile(CACHED_TILE_COUNT - 1))
384 CachedTile tmp = std::move(m_aCachedTiles[CACHED_TILE_COUNT - 1]);
385 for (
int i = CACHED_TILE_COUNT - 1; i >= 1; --i)
386 m_aCachedTiles[i] = std::move(m_aCachedTiles[i - 1]);
387 m_aCachedTiles[0] = std::move(tmp);
391 if (m_nCachedTileCount > 0)
392 std::swap(m_aCachedTiles[0], m_aCachedTiles[m_nCachedTileCount]);
393 m_aCachedTiles[0].m_data.resize(TILE_SIZE * TILE_SIZE);
394 m_nCachedTileCount++;
398 CPLDebug(
"GDAL",
"Load tile(%d, %d) of band %d of dataset %s",
399 nTileX, nTileY, m_poBand->GetBand(),
400 m_poBand->GetDataset() ? m_poBand->GetDataset()->GetDescription() :
"(unknown)");
402 CPLAssert(!m_aCachedTiles[0].m_bModified);
403 const int nXOff = nTileX * TILE_SIZE;
404 const int nYOff = nTileY * TILE_SIZE;
405 const int nReqXSize = std::min(m_poBand->GetXSize() - nXOff, TILE_SIZE);
406 const int nReqYSize = std::min(m_poBand->GetYSize() - nYOff, TILE_SIZE);
407 if (m_poBand->RasterIO(
408 GF_Read, nXOff, nYOff, nReqXSize, nReqYSize,
409 m_aCachedTiles[0].m_data.data(), nReqXSize, nReqYSize,
410 GDALCachedPixelAccessorGetDataType<Type>::DataType,
sizeof(Type),
411 TILE_SIZE *
sizeof(Type),
nullptr) != CE_None)
413 m_aCachedTiles[0].m_nTileX = -1;
414 m_aCachedTiles[0].m_nTileY = -1;
417 m_aCachedTiles[0].m_nTileX = nTileX;
418 m_aCachedTiles[0].m_nTileY = nTileY;
426template <
class Type,
int TILE_SIZE,
int CACHED_TILE_COUNT>
427bool GDALCachedPixelAccessor<Type, TILE_SIZE, CACHED_TILE_COUNT>::FlushTile(
430 if (!m_aCachedTiles[iSlot].m_bModified)
433 m_aCachedTiles[iSlot].m_bModified =
false;
434 const int nXOff = m_aCachedTiles[iSlot].m_nTileX * TILE_SIZE;
435 const int nYOff = m_aCachedTiles[iSlot].m_nTileY * TILE_SIZE;
436 const int nReqXSize = std::min(m_poBand->GetXSize() - nXOff, TILE_SIZE);
437 const int nReqYSize = std::min(m_poBand->GetYSize() - nYOff, TILE_SIZE);
438 return m_poBand->RasterIO(
439 GF_Write, nXOff, nYOff, nReqXSize, nReqYSize,
440 m_aCachedTiles[iSlot].m_data.data(), nReqXSize, nReqYSize,
441 GDALCachedPixelAccessorGetDataType<Type>::DataType,
sizeof(Type),
442 TILE_SIZE *
sizeof(Type),
nullptr) == CE_None;
Class to have reasonably fast random pixel access to a raster band, when accessing multiple pixels th...
Definition gdalcachedpixelaccessor.h:38
bool Set(int nX, int nY, Type val)
Set the value of a pixel.
Definition gdalcachedpixelaccessor.h:206
bool FlushCache()
Flush content of modified tiles and drop caches.
Definition gdalcachedpixelaccessor.h:266
void SetBand(GDALRasterBand *poBand)
Assign the raster band if not known at construction time.
Definition gdalcachedpixelaccessor.h:69
void ResetModifiedFlag()
Reset the modified flag for cached tiles.
Definition gdalcachedpixelaccessor.h:287
Type Get(int nX, int nY, bool *pbSuccess=nullptr)
Get the value of a pixel.
Definition gdalcachedpixelaccessor.h:133
~GDALCachedPixelAccessor()
Destructor.
Definition gdalcachedpixelaccessor.h:114
A single raster band (or channel).
Definition gdal_rasterband.h:105
CPL error handling services.
#define CPLAssert(expr)
Assert on an expression.
Definition cpl_error.h:330
short GInt16
Int16 type.
Definition cpl_port.h:171
GIntBig GInt64
Signed 64 bit integer type.
Definition cpl_port.h:226
unsigned int GUInt32
Unsigned int32 type.
Definition cpl_port.h:167
GUIntBig GUInt64
Unsigned 64 bit integer type.
Definition cpl_port.h:228
unsigned short GUInt16
Unsigned int16 type.
Definition cpl_port.h:173
unsigned char GByte
Unsigned byte type.
Definition cpl_port.h:175
int GInt32
Int32 type.
Definition cpl_port.h:165
signed char GInt8
Signed int8 type.
Definition cpl_port.h:177
GDALDataType
Definition gdal.h:48
@ GDT_UInt32
Definition gdal.h:54
@ GDT_UInt64
Definition gdal.h:56
@ GDT_Int64
Definition gdal.h:57
@ GDT_Byte
Definition gdal.h:50
@ GDT_Int8
Definition gdal.h:51
@ GDT_Float64
Definition gdal.h:60
@ GDT_Float16
Definition gdal.h:58
@ GDT_UInt16
Definition gdal.h:52
@ GDT_Int16
Definition gdal.h:53
@ GDT_Int32
Definition gdal.h:55
@ GDT_Float32
Definition gdal.h:59
@ GF_Write
Definition gdal.h:127
@ GF_Read
Definition gdal.h:126
This file is legacy since GDAL 3.12, but will be kept at least in the whole GDAL 3....