Skip to content

Commit 1a41348

Browse files
author
Grok Compression
committed
decompress: option to only process user selected components
1 parent 67eca36 commit 1a41348

12 files changed

Lines changed: 119 additions & 1 deletion

File tree

src/lib/codec/apps/GrkDecompress.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#endif /* _WIN32 */
3030
#include <climits>
3131
#include <string>
32+
#include <sstream>
3233
#include <chrono>
3334
#include <thread>
3435
#include <algorithm>
@@ -340,7 +341,8 @@ GrkRC GrkDecompress::parseCommandLine(int argc, const char* argv[],
340341
CLI::App cmd("grk_decompress command line", grk_version());
341342

342343
std::string outDir, compression, decodeRegion, pluginPathStr, inputFile, outputFile, outFor,
343-
precision, logfile, inDir;
344+
precision, logfile, inDir, components;
345+
auto& compIndices = initParams->compIndices;
344346
uint32_t repetitions = 0, numThreads = 0, kernelBuildOptions = 0,
345347
compressionLevel = std::numeric_limits<uint32_t>::max(), disableRandomAccess = 0,
346348
tile = 0, duration = 0;
@@ -369,6 +371,9 @@ GrkRC GrkDecompress::parseCommandLine(int argc, const char* argv[],
369371
cmd.add_option("-L,--compression-level", compressionLevel, "Output compression Level");
370372
auto randomAccessOpt = cmd.add_option("-m,--random-access", disableRandomAccess,
371373
"Toggle support for random access into code stream");
374+
auto componentsOpt = cmd.add_option(
375+
"-n,--components", components,
376+
"Comma-separated list of 0-based component indices to decode (e.g. '0' or '0,2')");
372377
auto outputFileOpt = cmd.add_option("-o,--out-file", outputFile, "Output file");
373378
auto outForOpt = cmd.add_option("-O,--out-fmt", outFor, "Output Format");
374379
auto precisionOpt = cmd.add_option("-p,--precision", precision, "Force precision");
@@ -563,6 +568,34 @@ GrkRC GrkDecompress::parseCommandLine(int argc, const char* argv[],
563568
parameters->core.reduce = reduce;
564569
if(layerOpt->count() > 0)
565570
parameters->core.layers_to_decompress = layer;
571+
if(componentsOpt->count() > 0)
572+
{
573+
std::istringstream iss(components);
574+
std::string token;
575+
while(std::getline(iss, token, ','))
576+
{
577+
try
578+
{
579+
int val = std::stoi(token);
580+
if(val < 0 || val > 16383)
581+
{
582+
spdlog::error("Component index {} out of range [0, 16383]", val);
583+
return GrkRCParseArgsFailed;
584+
}
585+
compIndices.push_back((uint16_t)val);
586+
}
587+
catch(...)
588+
{
589+
spdlog::error("Invalid component index: {}", token);
590+
return GrkRCParseArgsFailed;
591+
}
592+
}
593+
if(!compIndices.empty())
594+
{
595+
parameters->core.comps_to_decode = compIndices.data();
596+
parameters->core.num_comps_to_decode = (uint16_t)compIndices.size();
597+
}
598+
}
566599
if(randomAccessOpt->count() > 0)
567600
parameters->core.disable_random_access_flags = disableRandomAccess;
568601
parameters->single_tile_decompress = tileOpt->count() > 0;

src/lib/codec/apps/GrkDecompress.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "common.h"
2020
#include "IImageFormat.h"
2121
#include "CLI/CLI.hpp"
22+
#include <vector>
2223

2324
namespace grk
2425
{
@@ -38,6 +39,7 @@ struct DecompressInitParams
3839
}
3940
bool initialized;
4041
grk_decompress_parameters parameters;
42+
std::vector<uint16_t> compIndices;
4143
char pluginPath[GRK_PATH_LEN];
4244
grk_img_fol inputFolder;
4345
grk_img_fol outFolder;

src/lib/core/codestream/CodingParams.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,11 @@ void CodingParams::init(grk_decompress_parameters* parameters,
195195
tileCache->setDirty(true);
196196
}
197197
codingParams_.dec_.layersToDecompress_ = core->layers_to_decompress;
198+
if(core->num_comps_to_decode > 0 && core->comps_to_decode)
199+
compsToDecompress_.assign(core->comps_to_decode,
200+
core->comps_to_decode + core->num_comps_to_decode);
201+
else
202+
compsToDecompress_.clear();
198203
}
199204

200205
bool CodingParams::hasTLM(void) const noexcept

src/lib/core/codestream/CodingParams.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,8 @@ struct CodingParams
448448
DecodingParams dec_;
449449
EncodingParams enc_;
450450
} codingParams_;
451+
/** Component indices to decode during decompression. Empty = decode all. */
452+
std::vector<uint16_t> compsToDecompress_;
451453
std::unique_ptr<TLMMarker> tlmMarkers_;
452454
std::unique_ptr<PLMarker> plmMarkers_;
453455
bool asynchronous_;

src/lib/core/codestream/decompress/CodeStreamDecompress.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,7 @@ bool CodeStreamDecompress::postProcess(GrkImage* img)
834834
{
835835
if(!img->postProcess())
836836
return false;
837+
img->filterComponents(cp_.compsToDecompress_);
837838
return postPostProcess_ ? postPostProcess_(img) : true;
838839
}
839840

src/lib/core/grok.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,15 @@ typedef struct _grk_decompress_core_params
645645
grk_io_pixels_callback io_buffer_callback; /* IO buffer callback */
646646
void* io_user_data; /* IO user data */
647647
grk_io_register_reclaim_callback io_register_client_callback; /* IO register client callback */
648+
/**
649+
* Array of 0-based component indices to decode.
650+
* Only these components will be fully decoded (T1, DWT, etc.).
651+
* When MCT is active, components 0-2 will always be decoded if any of them is requested.
652+
* If num_comps_to_decode is 0 or comps_to_decode is nullptr, all components are decoded.
653+
* Memory is owned by the caller.
654+
*/
655+
uint16_t* comps_to_decode;
656+
uint16_t num_comps_to_decode;
648657
} grk_decompress_core_params;
649658

650659
/**

src/lib/core/scheduling/standard/DecompressScheduler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ bool DecompressScheduler::scheduleT1(ITileProcessor* tileProcessor)
129129

130130
for(uint16_t compno = 0; compno < numcomps_; ++compno)
131131
{
132+
// skip components not selected for decoding
133+
if(!tileProcessor->shouldDecodeComponent(compno))
134+
continue;
135+
132136
// schedule blocks
133137
auto tccp = tcp->tccps_ + compno;
134138
// nominal code block dimensions

src/lib/core/tile_processor/ITileProcessor.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,14 @@ struct ITileProcessor
279279
*/
280280
virtual bool needsMctDecompress(void) = 0;
281281

282+
/**
283+
* @brief Check if a component should be decoded based on user selection.
284+
* When MCT=1 is active and any of components 0-2 is requested, all three are decoded.
285+
* @param compno 0-based component index
286+
* @return true if the component should be decoded
287+
*/
288+
virtual bool shouldDecodeComponent(uint16_t compno) = 0;
289+
282290
/**
283291
* @brief Gets the MCT (Multi-Component Transform) object
284292
* @return Pointer to Mct

src/lib/core/tile_processor/TileProcessor.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "GrkObjectWrapper.h"
2525
#include "Quantizer.h"
2626

27+
#include <algorithm>
2728
#include "ImageComponentFlow.h"
2829
#include "TileFutureManager.h"
2930

@@ -1149,6 +1150,10 @@ void TileProcessor::scheduleAndRunDecompress(CoderPool* coderPool, Rect32 unredu
11491150
return;
11501151
for(uint16_t compno = 0; compno < tile_->numcomps_; ++compno)
11511152
{
1153+
// skip allocation for components not selected for decoding
1154+
if(!shouldDecodeComponent(compno))
1155+
continue;
1156+
11521157
auto tilec = tile_->comps_ + compno;
11531158

11541159
if(Scheduling::isExcalibur())
@@ -1278,5 +1283,28 @@ bool TileProcessor::needsMctDecompress(uint16_t compno)
12781283
{
12791284
return needsMctDecompress() && (compno <= 2);
12801285
}
1286+
bool TileProcessor::shouldDecodeComponent(uint16_t compno)
1287+
{
1288+
auto& comps = cp_->compsToDecompress_;
1289+
if(comps.empty())
1290+
return true; // decode all
1291+
1292+
// Check if this component is directly requested
1293+
bool requested = std::find(comps.begin(), comps.end(), compno) != comps.end();
1294+
if(requested)
1295+
return true;
1296+
1297+
// If MCT=1 is active and any of components 0-2 is requested, decode all three
1298+
if(needsMctDecompress() && compno <= 2)
1299+
{
1300+
for(auto c : comps)
1301+
{
1302+
if(c <= 2)
1303+
return true;
1304+
}
1305+
}
1306+
1307+
return false;
1308+
}
12811309

12821310
} // namespace grk

src/lib/core/tile_processor/TileProcessor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ struct TileProcessor : virtual public ITileProcessor
288288
*/
289289
bool needsMctDecompress(void) override;
290290

291+
bool shouldDecodeComponent(uint16_t compno) override;
292+
291293
/**
292294
* @brief gets @ref Mct
293295
*

0 commit comments

Comments
 (0)