13. Transcode API - GrokImageCompression/grok GitHub Wiki

13. Transcode

Command-Line Tool: grk_transcode

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

Examples

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

C API: grk_transcode()

Overview

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).

Basic Usage

#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);

Codestream Modifications

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).

TLM / PLT Marker Insertion

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.

SOP / EPH Marker Injection

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.

Layer Truncation

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.

Resolution Stripping

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).

Progression Reorder

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.

Example: Combined Transcode

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);

Metadata Modification

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.

Notes

  • JP2 and JPH containers both use the jp2c codestream 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.
⚠️ **GitHub.com Fallback** ⚠️