13. Transcode API - GrokImageCompression/grok GitHub Wiki
grk_transcode -i <input> -o <output> [options]
Transcode a JPEG 2000 file, rewriting boxes or markers and optionally modifying the codestream without full decompression.
Supported formats:
-
JP2 (
.jp2) — ISO 15444-1 container -
JPH (
.jph) — ISO 15444-15 High-Throughput JPEG 2000 container -
J2K / J2C / JPC (
.j2k,.j2c,.jpc) — raw codestream
Format conversion: When the input is a container (JP2/JPH) and the output
is a raw codestream (J2K/J2C/JPC), all box metadata (XMP, ICC profile, GeoTIFF
UUID, etc.) is stripped and only the codestream is written. Any requested
codestream modifications are applied before extraction. Converting from raw
codestream to container (J2K → JP2) is not supported — use grk_compress.
The input format is detected automatically from file content (magic bytes), not the file extension.
| Option | Description |
|---|---|
-i, --input <file> |
Input file — JP2, JPH, or raw J2K/J2C/JPC (required) |
-o, --output <file> |
Output file — JP2, JPH, or raw J2K/J2C/JPC (required) |
-X, --tlm |
Insert TLM markers |
-L, --plt |
Insert PLT markers |
-S, --sop |
Inject SOP markers before each packet |
-E, --eph |
Inject EPH markers after each packet header |
-n, --max-layers <N> |
Keep at most N quality layers (0 = all) |
-R, --max-res <N> |
Keep at most N resolution levels (0 = all) |
-p, --progression <P> |
Reorder to progression (LRCP, RLCP, RPCL, PCRL, CPRL) |
-h, --help |
Print help message |
-v, --version |
Print library version |
Insert TLM and PLT markers into a JP2 file:
grk_transcode -i input.jp2 -o output.jp2 -X -L
Add SOP/EPH markers and change progression to RLCP:
grk_transcode -i input.jp2 -o output.jp2 -S -E -p RLCP
Keep only 3 quality layers and 4 resolution levels:
grk_transcode -i input.jp2 -o output.jp2 -n 3 -R 4
Transcode a JPH (High-Throughput JPEG 2000) file:
grk_transcode -i input.jph -o output.jph -X -L
Extract raw codestream from a JP2 container:
grk_transcode -i input.jp2 -o output.j2k
Extract codestream from JP2 and insert TLM markers:
grk_transcode -i input.jp2 -o output.j2k -X
grk_transcode() rewrites a JPEG 2000 file with modified metadata boxes or
markers and optional codestream transformations, without full decompression.
The codestream is parsed at the packet level (T2 only — entropy decoding is
skipped) and reassembled with the requested modifications.
Supported formats: JP2 (.jp2), JPH (.jph), and raw codestreams
(.j2k, .j2c, .jpc).
#include "grok.h"
grk_cparameters cparams = {};
grk_compress_set_default_params(&cparams);
cparams.cod_format = GRK_FMT_JP2;
grk_stream_params src = {};
strcpy(src.file, "input.jp2");
grk_stream_params dst = {};
strcpy(dst.file, "output.jp2");
/* Decompress header to obtain image info and metadata */
grk_decompress_parameters dparams = {};
grk_object* dec = grk_decompress_init(&src, &dparams);
grk_header_info hdr = {};
grk_decompress_read_header(dec, &hdr);
grk_image* image = grk_decompress_get_image(dec);
/* Modify metadata on image->meta as needed, then transcode */
uint64_t bytes = grk_transcode(&src, &dst, &cparams, image);
grk_object_unref(dec);These parameters on grk_cparameters control codestream-level transformations
during transcode. All are optional; by default the codestream is copied verbatim
(aside from TLM/PLT insertion if requested).
| Parameter | Type | Default | Description |
|---|---|---|---|
write_tlm |
bool |
false |
Insert TLM (Tile-part Length) markers |
write_plt |
bool |
false |
Insert PLT (Packet Length) markers |
TLM and PLT markers enable efficient random-access decoding of large tiled images. PLT requires a T2-only decompression pass internally to record per-packet lengths.
| Parameter | Type | Default | Description |
|---|---|---|---|
write_sop |
bool |
false |
Inject SOP markers before each packet |
write_eph |
bool |
false |
Inject EPH markers after each packet header |
SOP (Start of Packet) and EPH (End of Packet Header) are resynchronisation markers defined in the JPEG 2000 standard (Part 1, Annex D). They aid error resilience and debugging. When injected during transcode:
- SOP (0xFF91): 6 bytes inserted before each packet, containing a 16-bit sequence number.
- EPH (0xFF92): 2 bytes inserted between the packet header and packet data.
- The COD marker's Scod byte is patched to signal their presence.
- PLT lengths (if enabled) reflect the added marker bytes.
| Parameter | Type | Default | Description |
|---|---|---|---|
max_layers_transcode |
uint16_t |
0 |
Maximum quality layers to keep (0 = all) |
Discards packets with layer index >= max_layers_transcode. The COD marker's
layer count is updated accordingly. This reduces file size by removing higher
quality refinement data.
| Parameter | Type | Default | Description |
|---|---|---|---|
max_res_transcode |
uint8_t |
0 |
Maximum resolutions to keep (0 = all) |
Discards packets with resolution level >= max_res_transcode. The COD marker's
decomposition level count and SIZ marker dimensions are patched to reflect the
reduced resolution. For example, keeping 3 resolutions from a 6-resolution image
reduces each dimension by a factor of 8 (2^3).
| Parameter | Type | Default | Description |
|---|---|---|---|
transcode_prog_order |
GRK_PROG_ORDER |
GRK_PROG_UNKNOWN |
Reorder packets (or keep original) |
Reorders packets according to a new progression order. Supported values:
| Value | Progression |
|---|---|
GRK_LRCP |
Layer-Resolution-Component-Position |
GRK_RLCP |
Resolution-Layer-Component-Position |
GRK_RPCL |
Resolution-Position-Component-Layer |
GRK_PCRL |
Position-Component-Resolution-Layer |
GRK_CPRL |
Component-Position-Resolution-Layer |
The COD marker's progression order field is updated. Use GRK_PROG_UNKNOWN
(the default) to preserve the original order.
grk_cparameters cparams = {};
grk_compress_set_default_params(&cparams);
cparams.cod_format = GRK_FMT_JP2;
/* Add TLM + PLT for random access */
cparams.write_tlm = true;
cparams.write_plt = true;
/* Inject SOP and EPH markers */
cparams.write_sop = true;
cparams.write_eph = true;
/* Keep only 3 quality layers */
cparams.max_layers_transcode = 3;
/* Keep only 4 resolutions (3 decomposition levels) */
cparams.max_res_transcode = 4;
/* Change progression to RLCP */
cparams.transcode_prog_order = GRK_RLCP;
uint64_t bytes = grk_transcode(&src, &dst, &cparams, image);Before calling grk_transcode(), modify image->meta to change JP2 box
metadata:
-
XMP: Set
image->meta->xmp_buf/xmp_len -
GeoTIFF UUID: Set
image->meta->geotiff_buf/geotiff_len -
IPTC: Set
image->meta->iptc_buf/iptc_len -
XML: Set
image->meta->xml_buf/xml_len -
ICC Profile: Set
image->meta->color.icc_profile_buf/icc_profile_len
Set a buffer to nullptr / length to 0 to remove that metadata from the
output. New metadata is written; the old codestream is preserved.
- JP2 and JPH containers both use the
jp2ccodestream box and are handled identically. Raw codestreams (.j2k,.j2c,.jpc) are also supported — TLM/PLT/SOP/EPH markers are codestream-level and apply to all formats. - When any packet-level feature is active (PLT, SOP, EPH, layer/resolution filtering, progression reorder), an internal T2-only decompression pass extracts per-packet information. Entropy decoding (T1) and inverse wavelet transforms are skipped for performance.
- Layer truncation and resolution stripping reduce data sizes; the remaining packets are consolidated into the first tile part of each tile.
- All features can be combined freely.