41 virtual ~ISparseCanvas() =
default;
45 virtual bool read(uint8_t
resno, grk_rect32 window, int32_t* dest,
const uint32_t destChunkY,
46 const uint32_t destChunkX) = 0;
50 virtual bool write(uint8_t
resno, grk_rect32 window,
const int32_t* src,
51 const uint32_t srcChunkY,
const uint32_t srcChunkX) = 0;
53 virtual bool alloc(grk_rect32 window,
bool zeroOutBuffer) = 0;
57 SparseBlock(
void) :
data(nullptr) {}
62 void alloc(uint32_t block_area,
bool zeroOutBuffer)
64 data =
new int32_t[block_area];
66 memset(
data, 0, block_area *
sizeof(int32_t));
70template<u
int32_t LBW, u
int32_t LBH>
71class SparseCanvas :
public ISparseCanvas
78 throw std::runtime_error(
"invalid window for sparse canvas");
85 SparseCanvas(uint32_t width, uint32_t height) : SparseCanvas(
grk_rect32(0, 0, width, height)) {}
90 for(uint64_t i = 0; i < (uint64_t)
grid.width() *
grid.height(); i++)
98 bool read(uint8_t
resno, grk_rect32 window, int32_t* dest,
const uint32_t destChunkY,
99 const uint32_t destChunkX)
101 return readWrite(
resno, window, dest, destChunkY, destChunkX,
true);
103 bool write(uint8_t
resno, grk_rect32 window,
const int32_t* src,
const uint32_t srcChunkY,
104 const uint32_t srcChunkX)
106 return readWrite(
resno, window, (int32_t*)src, srcChunkY, srcChunkX,
false);
108 bool alloc(grk_rect32 win,
bool zeroOutBuffer)
110 if(!SparseCanvas::isWindowValid(win))
112 uint32_t blockWinHeight = 0;
113 uint32_t gridY = win.y0 >> LBH;
114 for(uint32_t
y = win.y0;
y < win.y1; gridY++,
y += blockWinHeight)
118 blockWinHeight = (std::min<uint32_t>)(blockWinHeight, win.y1 -
y);
119 uint32_t gridX = win.x0 >> LBW;
120 uint32_t blockWinWidth = 0;
121 for(uint32_t
x = win.x0;
x < win.x1; gridX++,
x += blockWinWidth)
125 blockWinWidth = (std::min<uint32_t>)(blockWinWidth, win.x1 -
x);
126 if(!
grid.contains(gridX, gridY))
128 GRK_WARN(
"sparse canvas : attempt to allocate a block (%u,%u) outside block "
129 "grid bounds (%u,%u,%u,%u)",
133 auto srcBlock = getBlock(gridX, gridY);
136 auto b =
new SparseBlock();
138 assert(
grid.contains(gridX, gridY));
141 (uint64_t)(gridY -
grid.y0) *
grid.width() + (gridX -
grid.x0);
150 inline SparseBlock* getBlock(uint32_t block_x, uint32_t block_y)
152 uint64_t index = (uint64_t)(block_y -
grid.y0) *
grid.width() + (block_x -
grid.x0);
155 bool isWindowValid(grk_rect32 win)
157 return !(win.x0 >=
bounds.x1 || win.x1 <= win.x0 || win.x1 >
bounds.x1 ||
158 win.y0 >=
bounds.y1 || win.y1 <= win.y0 || win.y1 >
bounds.y1);
160 bool readWrite(uint8_t
resno, grk_rect32 win, int32_t*
buf,
const uint32_t spacingX,
161 const uint32_t spacingY,
bool isReadOperation)
165 assert(!isReadOperation ||
buf);
167 if(!isWindowValid(win))
169 GRK_WARN(
"Sparse canvas @ res %u, attempt to read/write invalid window (%u,%u,%u,%u) "
170 "for bounds (%u,%u,%u,%u).",
175 assert(spacingY != 0 || win.height() == 1);
176 assert((spacingY <= 1 && spacingX >= 1) || (spacingY >= 1 && spacingX == 1));
178 uint32_t gridY = win.y0 >> LBH;
179 uint32_t blockWinHeight = 0;
180 for(uint32_t
y = win.y0;
y < win.y1; gridY++,
y += blockWinHeight)
184 uint32_t blockOffsetY =
blockHeight - blockWinHeight;
185 blockWinHeight = (std::min<uint32_t>)(blockWinHeight, win.y1 -
y);
186 uint32_t gridX = win.x0 >> LBW;
187 uint32_t blockWinWidth = 0;
188 for(uint32_t
x = win.x0;
x < win.x1; gridX++,
x += blockWinWidth)
192 uint32_t blockOffsetX =
blockWidth - blockWinWidth;
193 blockWinWidth = (std::min<uint32_t>)(blockWinWidth, win.x1 -
x);
194 if(!
grid.contains(gridX, gridY))
196 GRK_WARN(
"sparse canvas @ resno %u, Attempt to access a block (%u,%u) outside "
198 resno, gridX, gridY);
201 auto srcBlock = getBlock(gridX, gridY);
204 GRK_WARN(
"sparse canvas @ resno %u, %s op: missing block (%u,%u,%u,%u) for %s "
205 "(%u,%u,%u,%u). Skipping.",
206 resno, isReadOperation ?
"read" :
"write",
210 isReadOperation ?
"read" :
"write", win.x0, win.y0, win.x1, win.y1);
215 auto src = srcBlock->data + ((uint64_t)blockOffsetY << LBW) + blockOffsetX;
216 auto dest =
buf + (
y - win.y0) * spacingY + (
x - win.x0) * spacingX;
217 for(uint32_t blockY = 0; blockY < blockWinHeight; blockY++)
219 uint64_t destInd = 0;
220 for(uint32_t blockX = 0; blockX < blockWinWidth; blockX++)
222#ifdef GRK_DEBUG_VALGRIND
223 size_t val = grk_memcheck<int32_t>(src + blockX, 1);
224 if(
val != grk_mem_ok)
225 GRK_ERROR(
"sparse canvas @resno %u, read block(%u,%u) : "
226 "uninitialized at location (%u,%u)",
227 resno, gridX, gridY,
x + blockX, y_);
229 dest[destInd] = src[blockX];
238 const int32_t* src =
nullptr;
240 src =
buf + (
y - win.y0) * spacingY + (
x - win.x0) * spacingX;
241 auto dest = srcBlock->data + ((uint64_t)blockOffsetY << LBW) + blockOffsetX;
242 for(uint32_t blockY = 0; blockY < blockWinHeight; blockY++)
245 for(uint32_t blockX = 0; blockX < blockWinWidth; blockX++)
247#ifdef GRK_DEBUG_VALGRIND
251 size_t val = grk_memcheck<int32_t>(src + srcInd, 1);
252 if(
val != grk_mem_ok)
253 GRK_ERROR(
"sparse canvas @ resno %u, write block(%u,%u): "
254 "uninitialized at location (%u,%u)",
255 resno, gridX, gridY,
x + blockX, y_);
258 dest[blockX] = src ? src[srcInd] : 0;
uint8_t buf
Definition BitIO.h:84
uint8_t resno
Definition BlockExec.h:53
uint32_t y
Definition BlockExec.h:39
uint32_t x
Definition BlockExec.h:38
uint8_t * data
Definition Codeblock.h:61
std::atomic< int64_t > blockCount
Definition CompressScheduler.h:39
grk_rect32 grid
Definition SparseCanvas.h:276
const uint32_t blockWidth
Definition SparseCanvas.h:272
grk_rect32 bounds
Definition SparseCanvas.h:275
SparseBlock ** blocks
Definition SparseCanvas.h:274
const uint32_t blockHeight
Definition SparseCanvas.h:273
T val[N]
Definition WaveletCommon.h:65
grk_rect< uint32_t > grk_rect32
Definition TileCache.h:61
void GRK_WARN(const char *fmt,...)
grk_pt< uint32_t > grk_pt32
Definition TileCache.h:40
void GRK_ERROR(const char *fmt,...)
Copyright (C) 2016-2023 Grok Image Compression Inc.
Definition ICacheable.h:20