Skip to content

Commit c37a125

Browse files
author
Grok Compression
committed
ImageFormat: stack based interleavers
1 parent 6b64324 commit c37a125

7 files changed

Lines changed: 112 additions & 62 deletions

File tree

.vscode/launch.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,11 @@
139139
"name": "SPOT6",
140140
"type": "cppdbg",
141141
"request": "launch",
142-
"program": "/usr/bin/time",
142+
//"program": "/usr/bin/time",
143+
"program": "${workspaceFolder}/build/bin/core_decompress",
143144
"args": [
144-
"-v",
145-
"${workspaceFolder}/build/bin/core_decompress",
145+
// "-v",
146+
// "${workspaceFolder}/build/bin/core_decompress",
146147
"-i",
147148
"$HOME/temp/IMG_SPOT6_PMS_201305251604372_ORT_816009101_R1C1.JP2",
148149
// "-o",

src/lib/codec/apps/GrkDecompress.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,8 +1122,7 @@ int GrkDecompress::preProcess(grk_plugin_decompress_callback_info* info)
11221122
// during decompress.
11231123
incrementalWriteActive_ = false;
11241124
if(storeToDisk && !parameters->single_tile_decompress && !info->init_decompressors_func &&
1125-
grk_image_is_post_process_no_op(info->image) &&
1126-
parameters->dw_y1 == 0)
1125+
grk_image_is_post_process_no_op(info->image) && parameters->dw_y1 == 0)
11271126
{
11281127
if(!writeInit(info))
11291128
goto cleanup;

src/lib/codec/formats/JPEGFormat.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class JPEGFormat : public ImageFormat
9292
{
9393
public:
9494
JPEGFormat(void);
95+
~JPEGFormat() override;
9596
bool writeHeader(void) override;
9697
bool writeImage() override;
9798
bool writeImageBand(uint32_t yBegin, uint32_t yEnd) override;
@@ -122,6 +123,7 @@ class JPEGFormat : public ImageFormat
122123
*/
123124
struct jpeg_compress_struct cinfo;
124125
T const* planes[4];
126+
grk::PlanarToInterleaved<T>* interleaver_;
125127
};
126128

127129
template<typename T>
@@ -382,9 +384,15 @@ grk_image* JPEGFormat<T>::jpegtoimage(const char* filename, grk_cparameters* par
382384
template<typename T>
383385
JPEGFormat<T>::JPEGFormat(void)
384386
: success(true), buffer(nullptr), buffer32s(nullptr), color_space(JCS_UNKNOWN), adjust(0),
385-
readFromStdin(false), planes{0, 0, 0}
387+
readFromStdin(false), planes{0, 0, 0}, interleaver_(nullptr)
386388
{}
387389

390+
template<typename T>
391+
JPEGFormat<T>::~JPEGFormat()
392+
{
393+
delete interleaver_;
394+
}
395+
388396
template<typename T>
389397
bool JPEGFormat<T>::writeHeader(void)
390398
{
@@ -602,22 +610,24 @@ bool JPEGFormat<T>::writeImageBand(uint32_t yBegin, uint32_t yEnd)
602610
cinfo.next_scanline);
603611
return false;
604612
}
605-
auto iter = grk::InterleaverFactory<T>::makeInterleaver(8);
606-
if(!iter)
607-
return false;
613+
if(!interleaver_)
614+
{
615+
interleaver_ = grk::InterleaverFactory<T>::makeInterleaver(8);
616+
if(!interleaver_)
617+
return false;
618+
}
608619
auto stride = image_->comps[0].stride;
609620
T* bandPlanes[4];
610621
for(uint16_t i = 0; i < image_->decompress_num_comps; ++i)
611622
bandPlanes[i] = (T*)image_->comps[i].data + (uint64_t)yBegin * stride;
612623
while(cinfo.next_scanline < yEnd)
613624
{
614-
iter->interleave(bandPlanes, image_->decompress_num_comps, (uint8_t*)buffer,
615-
image_->decompress_width, stride, image_->decompress_width, 1, adjust);
625+
interleaver_->interleave(bandPlanes, image_->decompress_num_comps, (uint8_t*)buffer,
626+
image_->decompress_width, stride, image_->decompress_width, 1, adjust);
616627
JSAMPROW row_pointer[1];
617628
row_pointer[0] = buffer;
618629
jpeg_write_scanlines(&cinfo, row_pointer, 1);
619630
}
620-
delete iter;
621631

622632
return true;
623633
}

src/lib/codec/formats/PNGFormat.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class PNGFormat : public ImageFormat
4040
{
4141
public:
4242
PNGFormat();
43+
~PNGFormat() override;
4344
bool writeHeader(void) override;
4445
bool writeImage() override;
4546
bool writeImageBand(uint32_t yBegin, uint32_t yEnd) override;
@@ -62,6 +63,7 @@ class PNGFormat : public ImageFormat
6263
GRK_COLOR_SPACE colorSpace_;
6364
uint8_t prec_;
6465
uint16_t nr_comp_;
66+
grk::PlanarToInterleaved<int32_t>* interleaver_;
6567
};
6668

6769
static bool pngWarningHandlerVerbose = true;
@@ -91,9 +93,15 @@ static inline void user_error_fn([[maybe_unused]] png_structp png_ptr, png_const
9193
template<typename T>
9294
PNGFormat<T>::PNGFormat()
9395
: info_(nullptr), png_(nullptr), row_buf_(nullptr), row_buf_array_(nullptr), row32s_(nullptr),
94-
colorSpace_(GRK_CLRSPC_UNKNOWN), prec_(0), nr_comp_(0)
96+
colorSpace_(GRK_CLRSPC_UNKNOWN), prec_(0), nr_comp_(0), interleaver_(nullptr)
9597
{}
9698

99+
template<typename T>
100+
PNGFormat<T>::~PNGFormat()
101+
{
102+
delete interleaver_;
103+
}
104+
97105
template<typename T>
98106
bool PNGFormat<T>::writeHeader(void)
99107
{
@@ -332,18 +340,20 @@ bool PNGFormat<T>::writeImageBand(uint32_t yBegin, uint32_t yEnd)
332340
png_bytep row_buf_cpy = row_buf_;
333341
int32_t adjust = image_->comps[0].sgnd ? 1 << (prec_ - 1) : 0;
334342
uint32_t max = std::min<uint32_t>(yEnd, maxY(image_->comps->h));
335-
auto iter =
336-
grk::InterleaverFactory<int32_t>::makeInterleaver(prec_ == 16 ? grk::packer16BitBE : prec_);
337-
if(!iter)
338-
return false;
343+
if(!interleaver_)
344+
{
345+
interleaver_ =
346+
grk::InterleaverFactory<int32_t>::makeInterleaver(prec_ == 16 ? grk::packer16BitBE : prec_);
347+
if(!interleaver_)
348+
return false;
349+
}
339350
for(uint32_t y = yBegin; y < max; ++y)
340351
{
341-
iter->interleave((T**)planes, nr_comp_, row_buf_, image_->comps[0].w, stride,
342-
image_->comps[0].w, 1, adjust);
352+
interleaver_->interleave((T**)planes, nr_comp_, row_buf_, image_->comps[0].w, stride,
353+
image_->comps[0].w, 1, adjust);
343354

344355
png_write_row(png_, row_buf_cpy);
345356
}
346-
delete iter;
347357

348358
return true;
349359
}

src/lib/codec/formats/PNMFormat.h

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class PNMFormat : public ImageFormat
4949
{
5050
public:
5151
explicit PNMFormat(bool split);
52+
~PNMFormat() override;
5253
bool writeHeader(void) override;
5354
bool writeImage() override;
5455
bool writeImageBand(uint32_t yBegin, uint32_t yEnd) override;
@@ -65,6 +66,7 @@ class PNMFormat : public ImageFormat
6566

6667
private:
6768
bool forceSplit;
69+
grk::PlanarToInterleaved<int32_t>* interleaver_;
6870
bool hasAlpha(void);
6971
bool isOpacity(uint16_t compno);
7072
bool hasOpacity(void);
@@ -83,9 +85,15 @@ class PNMFormat : public ImageFormat
8385
};
8486

8587
template<typename T>
86-
PNMFormat<T>::PNMFormat(bool split) : forceSplit(split)
88+
PNMFormat<T>::PNMFormat(bool split) : forceSplit(split), interleaver_(nullptr)
8789
{}
8890

91+
template<typename T>
92+
PNMFormat<T>::~PNMFormat()
93+
{
94+
delete interleaver_;
95+
}
96+
8997
template<typename T>
9098
bool PNMFormat<T>::writeHeader(void)
9199
{
@@ -226,37 +234,48 @@ bool PNMFormat<T>::writeImageBand(uint32_t yBegin, uint32_t yEnd)
226234
}
227235
// Non-split (PPM/PAM) interleaved path
228236
uint16_t decompress_num_comps = image_->decompress_num_comps;
229-
auto planes = std::make_unique<T*[]>(decompress_num_comps);
237+
constexpr uint16_t kMaxStackComps = 4;
238+
T* stackPlanes[kMaxStackComps];
239+
std::unique_ptr<T*[]> heapPlanes;
240+
T** planes;
241+
if(decompress_num_comps <= kMaxStackComps)
242+
planes = stackPlanes;
243+
else
244+
{
245+
heapPlanes = std::make_unique<T*[]>(decompress_num_comps);
246+
planes = heapPlanes.get();
247+
}
230248
for(uint32_t i = 0U; i < decompress_num_comps; ++i)
231249
planes[i] = (T*)image_->comps[i].data + (uint64_t)yBegin * image_->comps[0].stride;
232250
GrkIOBuf packedBuf;
233251
T adjust = (image_->comps[0].sgnd ? 1 << (image_->decompress_prec - 1) : 0);
234-
auto iter = grk::InterleaverFactory<int32_t>::makeInterleaver(
235-
image_->decompress_prec > 8U ? grk::packer16BitBE : 8);
236-
if(!iter)
237-
return false;
252+
if(!interleaver_)
253+
{
254+
interleaver_ = grk::InterleaverFactory<int32_t>::makeInterleaver(
255+
image_->decompress_prec > 8U ? grk::packer16BitBE : 8);
256+
if(!interleaver_)
257+
return false;
258+
}
238259
uint32_t h = yBegin;
239260
while(h < yEnd)
240261
{
241262
uint32_t stripRows = (std::min)(image_->rows_per_strip, yEnd - h);
242263
packedBuf = pool.get(image_->packed_row_bytes * stripRows);
243-
iter->interleave(((T**)planes.get()), decompress_num_comps, packedBuf.data,
244-
image_->decompress_width, image_->comps[0].stride, image_->packed_row_bytes,
245-
stripRows, adjust);
264+
interleaver_->interleave(((T**)planes), decompress_num_comps, packedBuf.data,
265+
image_->decompress_width, image_->comps[0].stride,
266+
image_->packed_row_bytes, stripRows, adjust);
246267
packedBuf.pooled = true;
247268
packedBuf.offset = orchestrator.getOffset();
248269
packedBuf.len = image_->packed_row_bytes * stripRows;
249270
packedBuf.index = orchestrator.getNumPooledRequests();
250271
if(!writeStripCore(0, packedBuf))
251272
{
252-
delete iter;
253273
applicationOrchestratedReclaim(packedBuf);
254274
return false;
255275
}
256276
h += stripRows;
257277
applicationOrchestratedReclaim(packedBuf);
258278
}
259-
delete iter;
260279
return true;
261280
}
262281

src/lib/codec/formats/TIFFFormat.h

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ class TIFFFormat : public ImageFormat
687687
size_t units;
688688
grk_io_callback grkReclaimCallback_;
689689
void* grkReclaimUserData_;
690+
grk::PlanarToInterleaved<T>* interleaver_;
690691
};
691692

692693
#ifdef GRK_CUSTOM_TIFF_IO
@@ -756,13 +757,14 @@ TIFF* TIFFFormat<T>::MyTIFFOpen(const char* name, const char* mode)
756757
template<typename T>
757758
TIFFFormat<T>::TIFFFormat()
758759
: tif_(nullptr), chroma_subsample_x(1), chroma_subsample_y(1), units(0),
759-
grkReclaimCallback_(nullptr), grkReclaimUserData_(nullptr)
760+
grkReclaimCallback_(nullptr), grkReclaimUserData_(nullptr), interleaver_(nullptr)
760761

761762
{}
762763

763764
template<typename T>
764765
TIFFFormat<T>::~TIFFFormat()
765766
{
767+
delete interleaver_;
766768
if(tif_)
767769
TIFFClose(tif_);
768770
}
@@ -1085,8 +1087,25 @@ bool TIFFFormat<T>::writeImageBand(uint32_t yBegin, uint32_t yEnd)
10851087
}
10861088
bool success = false;
10871089
uint16_t numcomps = image_->decompress_num_comps;
1088-
auto planes = std::make_unique<T*[]>(numcomps);
1089-
auto planesBegin = std::make_unique<T*[]>(numcomps);
1090+
constexpr uint16_t kMaxStackComps = 4;
1091+
T* stackPlanes[kMaxStackComps];
1092+
T* stackPlanesBegin[kMaxStackComps];
1093+
std::unique_ptr<T*[]> heapPlanes;
1094+
std::unique_ptr<T*[]> heapPlanesBegin;
1095+
T** planes;
1096+
T** planesBegin;
1097+
if(numcomps <= kMaxStackComps)
1098+
{
1099+
planes = stackPlanes;
1100+
planesBegin = stackPlanesBegin;
1101+
}
1102+
else
1103+
{
1104+
heapPlanes = std::make_unique<T*[]>(numcomps);
1105+
heapPlanesBegin = std::make_unique<T*[]>(numcomps);
1106+
planes = heapPlanes.get();
1107+
planesBegin = heapPlanesBegin.get();
1108+
}
10901109
GrkIOBuf packedBuf;
10911110

10921111
if(isFinalOutputSubsampled(image_))
@@ -1169,28 +1188,27 @@ bool TIFFFormat<T>::writeImageBand(uint32_t yBegin, uint32_t yEnd)
11691188
{
11701189
planes[i] = (T*)image_->comps[i].data + (uint64_t)yBegin * image_->comps[0].stride;
11711190
}
1172-
auto iter = grk::InterleaverFactory<T>::makeInterleaver(image_->decompress_prec);
1173-
if(!iter)
1174-
goto cleanup;
1191+
if(!interleaver_)
1192+
{
1193+
interleaver_ = grk::InterleaverFactory<T>::makeInterleaver(image_->decompress_prec);
1194+
if(!interleaver_)
1195+
goto cleanup;
1196+
}
11751197
uint32_t h = yBegin;
11761198
while(h < yEnd)
11771199
{
11781200
uint32_t stripRows = (std::min)(image_->rows_per_strip, yEnd - h);
11791201
packedBuf = pool.get(image_->packed_row_bytes * stripRows);
1180-
iter->interleave(((T**)planes.get()), numcomps, packedBuf.data, image_->decompress_width,
1181-
image_->comps[0].stride, image_->packed_row_bytes, stripRows, 0);
1202+
interleaver_->interleave(planes, numcomps, packedBuf.data, image_->decompress_width,
1203+
image_->comps[0].stride, image_->packed_row_bytes, stripRows, 0);
11821204
packedBuf.pooled = true;
11831205
packedBuf.offset = orchestrator.getOffset();
11841206
packedBuf.len = image_->packed_row_bytes * stripRows;
11851207
packedBuf.index = orchestrator.getNumPooledRequests();
11861208
if(!writeStripCore(0, packedBuf))
1187-
{
1188-
delete iter;
11891209
goto cleanup;
1190-
}
11911210
h += stripRows;
11921211
}
1193-
delete iter;
11941212
}
11951213
success = true;
11961214
cleanup:

0 commit comments

Comments
 (0)