Merge pull request #1359 from rouault/TLM
Add support for enabling generation of TLM markers in encoder
This commit is contained in:
commit
c28965f255
|
@ -231,6 +231,8 @@ static void encode_help_display(void)
|
|||
fprintf(stdout, " Write EPH marker after each header packet.\n");
|
||||
fprintf(stdout, "-PLT\n");
|
||||
fprintf(stdout, " Write PLT marker in tile-part header.\n");
|
||||
fprintf(stdout, "-TLM\n");
|
||||
fprintf(stdout, " Write TLM marker in main header.\n");
|
||||
fprintf(stdout, "-M <key value>\n");
|
||||
fprintf(stdout, " Mode switch.\n");
|
||||
fprintf(stdout, " [1=BYPASS(LAZY) 2=RESET 4=RESTART(TERMALL)\n");
|
||||
|
@ -597,6 +599,7 @@ static int parse_cmdline_encoder(int argc, char **argv,
|
|||
size_t indexfilename_size,
|
||||
int* pOutFramerate,
|
||||
OPJ_BOOL* pOutPLT,
|
||||
OPJ_BOOL* pOutTLM,
|
||||
int* pOutNumThreads)
|
||||
{
|
||||
OPJ_UINT32 i, j;
|
||||
|
@ -615,7 +618,8 @@ static int parse_cmdline_encoder(int argc, char **argv,
|
|||
{"mct", REQ_ARG, NULL, 'Y'},
|
||||
{"IMF", REQ_ARG, NULL, 'Z'},
|
||||
{"PLT", NO_ARG, NULL, 'A'},
|
||||
{"threads", REQ_ARG, NULL, 'B'}
|
||||
{"threads", REQ_ARG, NULL, 'B'},
|
||||
{"TLM", NO_ARG, NULL, 'D'},
|
||||
};
|
||||
|
||||
/* parse the command line */
|
||||
|
@ -1712,6 +1716,12 @@ static int parse_cmdline_encoder(int argc, char **argv,
|
|||
}
|
||||
}
|
||||
break;
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
case 'D': { /* TLM markers */
|
||||
*pOutTLM = OPJ_TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
|
@ -1895,6 +1905,7 @@ int main(int argc, char **argv)
|
|||
OPJ_FLOAT64 t = opj_clock();
|
||||
|
||||
OPJ_BOOL PLT = OPJ_FALSE;
|
||||
OPJ_BOOL TLM = OPJ_FALSE;
|
||||
int num_threads = 0;
|
||||
|
||||
/* set encoding parameters to default values */
|
||||
|
@ -1916,7 +1927,8 @@ int main(int argc, char **argv)
|
|||
parameters.tcp_mct = (char)
|
||||
255; /* This will be set later according to the input image or the provided option */
|
||||
if (parse_cmdline_encoder(argc, argv, ¶meters, &img_fol, &raw_cp,
|
||||
indexfilename, sizeof(indexfilename), &framerate, &PLT, &num_threads) == 1) {
|
||||
indexfilename, sizeof(indexfilename), &framerate, &PLT, &TLM,
|
||||
&num_threads) == 1) {
|
||||
ret = 1;
|
||||
goto fin;
|
||||
}
|
||||
|
@ -2160,8 +2172,16 @@ int main(int argc, char **argv)
|
|||
goto fin;
|
||||
}
|
||||
|
||||
if (PLT) {
|
||||
const char* const options[] = { "PLT=YES", NULL };
|
||||
if (PLT || TLM) {
|
||||
const char* options[3] = { NULL, NULL, NULL };
|
||||
int iOpt = 0;
|
||||
if (PLT) {
|
||||
options[iOpt++] = "PLT=YES";
|
||||
}
|
||||
if (TLM) {
|
||||
options[iOpt++] = "TLM=YES";
|
||||
}
|
||||
(void)iOpt;
|
||||
if (!opj_encoder_set_extra_options(l_codec, options)) {
|
||||
fprintf(stderr, "failed to encode image: opj_encoder_set_extra_options\n");
|
||||
opj_destroy_codec(l_codec);
|
||||
|
|
|
@ -910,9 +910,15 @@ static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k,
|
|||
|
||||
static void opj_j2k_update_tlm(opj_j2k_t * p_j2k, OPJ_UINT32 p_tile_part_size)
|
||||
{
|
||||
opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,
|
||||
p_j2k->m_current_tile_number, 1); /* PSOT */
|
||||
++p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current;
|
||||
if (p_j2k->m_specific_param.m_encoder.m_Ttlmi_is_byte) {
|
||||
opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,
|
||||
p_j2k->m_current_tile_number, 1);
|
||||
p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current += 1;
|
||||
} else {
|
||||
opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,
|
||||
p_j2k->m_current_tile_number, 2);
|
||||
p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current += 2;
|
||||
}
|
||||
|
||||
opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,
|
||||
p_tile_part_size, 4); /* PSOT */
|
||||
|
@ -4170,13 +4176,33 @@ static OPJ_BOOL opj_j2k_write_tlm(opj_j2k_t *p_j2k,
|
|||
{
|
||||
OPJ_BYTE * l_current_data = 00;
|
||||
OPJ_UINT32 l_tlm_size;
|
||||
OPJ_UINT32 size_per_tile_part;
|
||||
|
||||
/* preconditions */
|
||||
assert(p_j2k != 00);
|
||||
assert(p_manager != 00);
|
||||
assert(p_stream != 00);
|
||||
|
||||
l_tlm_size = 6 + (5 * p_j2k->m_specific_param.m_encoder.m_total_tile_parts);
|
||||
/* 10921 = (65535 - header_size) / size_per_tile_part where */
|
||||
/* header_size = 4 and size_per_tile_part = 6 */
|
||||
if (p_j2k->m_specific_param.m_encoder.m_total_tile_parts > 10921) {
|
||||
/* We could do more but it would require writing several TLM markers */
|
||||
opj_event_msg(p_manager, EVT_ERROR,
|
||||
"A maximum of 10921 tile-parts are supported currently "
|
||||
"when writing TLM marker\n");
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
if (p_j2k->m_specific_param.m_encoder.m_total_tile_parts <= 255) {
|
||||
size_per_tile_part = 5;
|
||||
p_j2k->m_specific_param.m_encoder.m_Ttlmi_is_byte = OPJ_TRUE;
|
||||
} else {
|
||||
size_per_tile_part = 6;
|
||||
p_j2k->m_specific_param.m_encoder.m_Ttlmi_is_byte = OPJ_FALSE;
|
||||
}
|
||||
|
||||
l_tlm_size = 2 + 4 + (size_per_tile_part *
|
||||
p_j2k->m_specific_param.m_encoder.m_total_tile_parts);
|
||||
|
||||
if (l_tlm_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
|
||||
OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(
|
||||
|
@ -4191,6 +4217,7 @@ static OPJ_BOOL opj_j2k_write_tlm(opj_j2k_t *p_j2k,
|
|||
p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
|
||||
p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_tlm_size;
|
||||
}
|
||||
memset(p_j2k->m_specific_param.m_encoder.m_header_tile_data, 0, l_tlm_size);
|
||||
|
||||
l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
|
||||
|
||||
|
@ -4210,11 +4237,14 @@ static OPJ_BOOL opj_j2k_write_tlm(opj_j2k_t *p_j2k,
|
|||
1); /* Ztlm=0*/
|
||||
++l_current_data;
|
||||
|
||||
opj_write_bytes(l_current_data, 0x50,
|
||||
1); /* Stlm ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */
|
||||
/* Stlm 0x50= ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */
|
||||
/* Stlm 0x60= ST=2(16bits-65535 tiles max),SP=1(Ptlm=32bits) */
|
||||
opj_write_bytes(l_current_data,
|
||||
size_per_tile_part == 5 ? 0x50 : 0x60,
|
||||
1);
|
||||
++l_current_data;
|
||||
|
||||
/* do nothing on the 5 * l_j2k->m_specific_param.m_encoder.m_total_tile_parts remaining data */
|
||||
/* do nothing on the size_per_tile_part * l_j2k->m_specific_param.m_encoder.m_total_tile_parts remaining data */
|
||||
if (opj_stream_write_data(p_stream,
|
||||
p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_tlm_size,
|
||||
p_manager) != l_tlm_size) {
|
||||
|
@ -5354,9 +5384,9 @@ static OPJ_BOOL opj_j2k_update_rates(opj_j2k_t *p_j2k,
|
|||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) {
|
||||
if (p_j2k->m_specific_param.m_encoder.m_TLM) {
|
||||
p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer =
|
||||
(OPJ_BYTE *) opj_malloc(5 *
|
||||
(OPJ_BYTE *) opj_malloc(6 *
|
||||
p_j2k->m_specific_param.m_encoder.m_total_tile_parts);
|
||||
if (! p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) {
|
||||
return OPJ_FALSE;
|
||||
|
@ -7709,6 +7739,10 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
|
|||
}
|
||||
}
|
||||
|
||||
if (OPJ_IS_CINEMA(parameters->rsiz) || OPJ_IS_IMF(parameters->rsiz)) {
|
||||
p_j2k->m_specific_param.m_encoder.m_TLM = OPJ_TRUE;
|
||||
}
|
||||
|
||||
/* Manage profiles and applications and set RSIZ */
|
||||
/* set cinema parameters if required */
|
||||
if (OPJ_IS_CINEMA(parameters->rsiz)) {
|
||||
|
@ -12048,6 +12082,16 @@ OPJ_BOOL opj_j2k_encoder_set_extra_options(
|
|||
"Invalid value for option: %s.\n", *p_option_iter);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
} else if (strncmp(*p_option_iter, "TLM=", 4) == 0) {
|
||||
if (strcmp(*p_option_iter, "TLM=YES") == 0) {
|
||||
p_j2k->m_specific_param.m_encoder.m_TLM = OPJ_TRUE;
|
||||
} else if (strcmp(*p_option_iter, "TLM=NO") == 0) {
|
||||
p_j2k->m_specific_param.m_encoder.m_TLM = OPJ_FALSE;
|
||||
} else {
|
||||
opj_event_msg(p_manager, EVT_ERROR,
|
||||
"Invalid value for option: %s.\n", *p_option_iter);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
} else {
|
||||
opj_event_msg(p_manager, EVT_ERROR,
|
||||
"Invalid option: %s.\n", *p_option_iter);
|
||||
|
@ -12445,7 +12489,7 @@ static OPJ_BOOL opj_j2k_setup_end_compress(opj_j2k_t *p_j2k,
|
|||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz) || OPJ_IS_IMF(p_j2k->m_cp.rsiz)) {
|
||||
if (p_j2k->m_specific_param.m_encoder.m_TLM) {
|
||||
if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,
|
||||
(opj_procedure)opj_j2k_write_updated_tlm, p_manager)) {
|
||||
return OPJ_FALSE;
|
||||
|
@ -12528,7 +12572,7 @@ static OPJ_BOOL opj_j2k_setup_header_writing(opj_j2k_t *p_j2k,
|
|||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz) || OPJ_IS_IMF(p_j2k->m_cp.rsiz)) {
|
||||
if (p_j2k->m_specific_param.m_encoder.m_TLM) {
|
||||
if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,
|
||||
(opj_procedure)opj_j2k_write_tlm, p_manager)) {
|
||||
return OPJ_FALSE;
|
||||
|
@ -12661,7 +12705,7 @@ static OPJ_BOOL opj_j2k_write_first_tile_part(opj_j2k_t *p_j2k,
|
|||
opj_write_bytes(l_begin_data + 6, l_nb_bytes_written,
|
||||
4); /* PSOT */
|
||||
|
||||
if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) {
|
||||
if (p_j2k->m_specific_param.m_encoder.m_TLM) {
|
||||
opj_j2k_update_tlm(p_j2k, l_nb_bytes_written);
|
||||
}
|
||||
|
||||
|
@ -12731,7 +12775,7 @@ static OPJ_BOOL opj_j2k_write_all_tile_parts(opj_j2k_t *p_j2k,
|
|||
opj_write_bytes(l_begin_data + 6, l_part_tile_size,
|
||||
4); /* PSOT */
|
||||
|
||||
if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) {
|
||||
if (p_j2k->m_specific_param.m_encoder.m_TLM) {
|
||||
opj_j2k_update_tlm(p_j2k, l_part_tile_size);
|
||||
}
|
||||
|
||||
|
@ -12777,7 +12821,7 @@ static OPJ_BOOL opj_j2k_write_all_tile_parts(opj_j2k_t *p_j2k,
|
|||
opj_write_bytes(l_begin_data + 6, l_part_tile_size,
|
||||
4); /* PSOT */
|
||||
|
||||
if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) {
|
||||
if (p_j2k->m_specific_param.m_encoder.m_TLM) {
|
||||
opj_j2k_update_tlm(p_j2k, l_part_tile_size);
|
||||
}
|
||||
|
||||
|
@ -12796,13 +12840,16 @@ static OPJ_BOOL opj_j2k_write_updated_tlm(opj_j2k_t *p_j2k,
|
|||
{
|
||||
OPJ_UINT32 l_tlm_size;
|
||||
OPJ_OFF_T l_tlm_position, l_current_position;
|
||||
OPJ_UINT32 size_per_tile_part;
|
||||
|
||||
/* preconditions */
|
||||
assert(p_j2k != 00);
|
||||
assert(p_manager != 00);
|
||||
assert(p_stream != 00);
|
||||
|
||||
l_tlm_size = 5 * p_j2k->m_specific_param.m_encoder.m_total_tile_parts;
|
||||
size_per_tile_part = p_j2k->m_specific_param.m_encoder.m_Ttlmi_is_byte ? 5 : 6;
|
||||
l_tlm_size = size_per_tile_part *
|
||||
p_j2k->m_specific_param.m_encoder.m_total_tile_parts;
|
||||
l_tlm_position = 6 + p_j2k->m_specific_param.m_encoder.m_tlm_start;
|
||||
l_current_position = opj_stream_tell(p_stream);
|
||||
|
||||
|
|
|
@ -503,6 +503,12 @@ typedef struct opj_j2k_enc {
|
|||
/** Tile part number currently coding, taking into account POC. m_current_tile_part_number holds the total number of tile parts while encoding the last tile part.*/
|
||||
OPJ_UINT32 m_current_tile_part_number; /*cur_tp_num */
|
||||
|
||||
/* whether to generate TLM markers */
|
||||
OPJ_BOOL m_TLM;
|
||||
|
||||
/* whether the Ttlmi field in a TLM marker is a byte (otherwise a uint16) */
|
||||
OPJ_BOOL m_Ttlmi_is_byte;
|
||||
|
||||
/**
|
||||
locate the start position of the TLM marker
|
||||
after encoding the tilepart, a jump (in j2k_write_sod) is done to the TLM marker to store the value of its length.
|
||||
|
|
|
@ -1592,7 +1592,10 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_setup_encoder(opj_codec_t *p_codec,
|
|||
* <ul>
|
||||
* <li>PLT=YES/NO. Defaults to NO. If set to YES, PLT marker segments,
|
||||
* indicating the length of each packet in the tile-part header, will be
|
||||
* written. Since 2.3.2</li>
|
||||
* written. Since 2.4.0</li>
|
||||
* <li>TLM=YES/NO. Defaults to NO (except for Cinema and IMF profiles).
|
||||
* If set to YES, TLM marker segments, indicating the length of each
|
||||
* tile-part part will be written. Since 2.4.0</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param p_codec Compressor handle
|
||||
|
@ -1600,7 +1603,7 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_setup_encoder(opj_codec_t *p_codec,
|
|||
* array of strings. Each string is of the form KEY=VALUE.
|
||||
*
|
||||
* @return OPJ_TRUE in case of success.
|
||||
* @since 2.3.2
|
||||
* @since 2.4.0
|
||||
*/
|
||||
OPJ_API OPJ_BOOL OPJ_CALLCONV opj_encoder_set_extra_options(
|
||||
opj_codec_t *p_codec,
|
||||
|
|
|
@ -186,6 +186,10 @@ opj_compress_no_raw_lossless -i @INPUT_NR_PATH@/ElephantDream_4K.tif -o @TEMP_PA
|
|||
opj_compress_no_raw_lossless -i @INPUT_NR_PATH@/byte.tif -o @TEMP_PATH@/byte_PLT.j2k -n 1 -PLT
|
||||
opj_compress_no_raw_lossless -i @INPUT_NR_PATH@/byte.tif -o @TEMP_PATH@/byte_PLT.jp2 -n 1 -PLT
|
||||
|
||||
opj_compress_no_raw_lossless -i @INPUT_NR_PATH@/byte.tif -o @TEMP_PATH@/byte_TLM.j2k -n 1 -TLM
|
||||
# Use tile size 1x1 to generate more than 255 tiles
|
||||
opj_compress_no_raw_lossless -i @INPUT_NR_PATH@/byte.tif -o @TEMP_PATH@/byte_TLM_400tiles.j2k -n 1 -t 1,1 -TLM
|
||||
|
||||
# DECODER TEST SUITE
|
||||
opj_decompress -i @INPUT_NR_PATH@/Bretagne2.j2k -o @TEMP_PATH@/Bretagne2.j2k.pgx
|
||||
opj_decompress -i @INPUT_NR_PATH@/_00042.j2k -o @TEMP_PATH@/_00042.j2k.pgx
|
||||
|
|
Loading…
Reference in New Issue