X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Flib%2Fopenjp2%2Fj2k.c;h=55ca5813d29c1d5af99ea83ae2d8bd105979986c;hb=5d12806091eab0659431fefcefdb797b09f8e884;hp=9cdc770b24c61c700a6b9902edbfcc4aa9c4749b;hpb=ac375ac9f5b4ae47501b60795e905e3d25dd00f8;p=openjpeg.git diff --git a/src/lib/openjp2/j2k.c b/src/lib/openjp2/j2k.c index 9cdc770b..55ca5813 100644 --- a/src/lib/openjp2/j2k.c +++ b/src/lib/openjp2/j2k.c @@ -16,6 +16,7 @@ * Copyright (c) 2010-2011, Kaori Hagihara * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France * Copyright (c) 2012, CS Systemes d'Information, France + * Copyright (c) 2017, IntoPIX SA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -832,13 +833,15 @@ static OPJ_BOOL opj_j2k_write_tlm(opj_j2k_t *p_j2k, * Writes the SOT marker (Start of tile-part) * * @param p_j2k J2K codec. - * @param p_data FIXME DOC - * @param p_data_written FIXME DOC + * @param p_data Output buffer + * @param p_total_data_size Output buffer size + * @param p_data_written Number of bytes written into stream * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ static OPJ_BOOL opj_j2k_write_sot(opj_j2k_t *p_j2k, OPJ_BYTE * p_data, + OPJ_UINT32 p_total_data_size, OPJ_UINT32 * p_data_written, const opj_stream_private_t *p_stream, opj_event_mgr_t * p_manager); @@ -1305,7 +1308,7 @@ typedef struct j2k_prog_order { char str_prog[5]; } j2k_prog_order_t; -static j2k_prog_order_t j2k_prog_order_list[] = { +static const j2k_prog_order_t j2k_prog_order_list[] = { {OPJ_CPRL, "CPRL"}, {OPJ_LRCP, "LRCP"}, {OPJ_PCRL, "PCRL"}, @@ -1602,9 +1605,9 @@ static void opj_j2k_write_float_to_float64(const void * p_src_data, } } -char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order) +const char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order) { - j2k_prog_order_t *po; + const j2k_prog_order_t *po; for (po = j2k_prog_order_list; po->enum_prog != -1; po++) { if (po->enum_prog == prg_order) { return po->str_prog; @@ -4201,6 +4204,7 @@ static OPJ_BOOL opj_j2k_write_tlm(opj_j2k_t *p_j2k, static OPJ_BOOL opj_j2k_write_sot(opj_j2k_t *p_j2k, OPJ_BYTE * p_data, + OPJ_UINT32 p_total_data_size, OPJ_UINT32 * p_data_written, const opj_stream_private_t *p_stream, opj_event_mgr_t * p_manager @@ -4212,7 +4216,12 @@ static OPJ_BOOL opj_j2k_write_sot(opj_j2k_t *p_j2k, assert(p_stream != 00); OPJ_UNUSED(p_stream); - OPJ_UNUSED(p_manager); + + if (p_total_data_size < 12) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough bytes in output buffer to write SOT marker\n"); + return OPJ_FALSE; + } opj_write_bytes(p_data, J2K_MS_SOT, 2); /* SOT */ @@ -4608,6 +4617,12 @@ static OPJ_BOOL opj_j2k_write_sod(opj_j2k_t *p_j2k, OPJ_UNUSED(p_stream); + if (p_total_data_size < 4) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough bytes in output buffer to write SOD marker\n"); + return OPJ_FALSE; + } + opj_write_bytes(p_data, J2K_MS_SOD, 2); /* SOD */ p_data += 2; @@ -4659,7 +4674,8 @@ static OPJ_BOOL opj_j2k_write_sod(opj_j2k_t *p_j2k, *p_data_written = 0; if (! opj_tcd_encode_tile(p_tile_coder, p_j2k->m_current_tile_number, p_data, - p_data_written, l_remaining_data, l_cstr_info)) { + p_data_written, l_remaining_data, l_cstr_info, + p_manager)) { opj_event_msg(p_manager, EVT_ERROR, "Cannot encode tile\n"); return OPJ_FALSE; } @@ -5147,7 +5163,17 @@ static OPJ_BOOL opj_j2k_update_rates(opj_j2k_t *p_j2k, ++l_img_comp; } - l_tile_size = (OPJ_UINT32)(l_tile_size * 0.1625); /* 1.3/8 = 0.1625 */ + /* TODO: where does this magic value come from ? */ + /* This used to be 1.3 / 8, but with random data and very small code */ + /* block sizes, this is not enough. For example with */ + /* bin/test_tile_encoder 1 256 256 32 32 8 0 reversible_with_precinct.j2k 4 4 3 0 0 1 16 16 */ + /* TODO revise this to take into account the overhead linked to the */ + /* number of packets and number of code blocks in packets */ + l_tile_size = (OPJ_UINT32)(l_tile_size * 1.4 / 8); + + /* Arbitrary amount to make the following work: */ + /* bin/test_tile_encoder 1 256 256 17 16 8 0 reversible_no_precinct.j2k 4 4 3 0 0 1 */ + l_tile_size += 500; l_tile_size += opj_j2k_get_specific_header_sizes(p_j2k); @@ -6572,10 +6598,16 @@ static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, /* Precincts */ parameters->csty |= 0x01; - parameters->res_spec = parameters->numresolution - 1; - for (i = 0; i < parameters->res_spec; i++) { - parameters->prcw_init[i] = 256; - parameters->prch_init[i] = 256; + if (parameters->numresolution == 1) { + parameters->res_spec = 1; + parameters->prcw_init[0] = 128; + parameters->prch_init[0] = 128; + } else { + parameters->res_spec = parameters->numresolution - 1; + for (i = 0; i < parameters->res_spec; i++) { + parameters->prcw_init[i] = 256; + parameters->prch_init[i] = 256; + } } /* The progression order shall be CPRL */ @@ -6769,6 +6801,13 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, } } + /* If no explicit layers are provided, use lossless settings */ + if (parameters->tcp_numlayers == 0) { + parameters->tcp_numlayers = 1; + parameters->cp_disto_alloc = 1; + parameters->tcp_rates[0] = 0; + } + /* see if max_codestream_size does limit input rate */ if (parameters->max_cs_size <= 0) { if (parameters->tcp_rates[parameters->tcp_numlayers - 1] > 0) { @@ -8742,6 +8781,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k, OPJ_UINT32 l_current_marker; OPJ_BYTE l_data [2]; opj_tcp_t * l_tcp; + opj_image_t* l_image_for_bounds; /* preconditions */ assert(p_stream != 00); @@ -8759,7 +8799,18 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k, return OPJ_FALSE; } + /* When using the opj_read_tile_header / opj_decode_tile_data API */ + /* such as in test_tile_decoder, m_output_image is NULL, so fall back */ + /* to the full image dimension. This is a bit surprising that */ + /* opj_set_decode_area() is only used to determinte intersecting tiles, */ + /* but full tile decoding is done */ + l_image_for_bounds = p_j2k->m_output_image ? p_j2k->m_output_image : + p_j2k->m_private_image; if (! opj_tcd_decode_tile(p_j2k->m_tcd, + l_image_for_bounds->x0, + l_image_for_bounds->y0, + l_image_for_bounds->x1, + l_image_for_bounds->y1, l_tcp->m_data, l_tcp->m_data_size, p_tile_index, @@ -8769,7 +8820,6 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k, opj_event_msg(p_manager, EVT_ERROR, "Failed to decode.\n"); return OPJ_FALSE; } - p_j2k->m_tcd->enumcs = p_j2k->enumcs; /* p_data can be set to NULL when the call will take care of using */ /* itself the TCD data. This is typically the case for whole single */ @@ -11467,7 +11517,8 @@ static OPJ_BOOL opj_j2k_write_first_tile_part(opj_j2k_t *p_j2k, l_current_nb_bytes_written = 0; l_begin_data = p_data; - if (! opj_j2k_write_sot(p_j2k, p_data, &l_current_nb_bytes_written, p_stream, + if (! opj_j2k_write_sot(p_j2k, p_data, p_total_data_size, + &l_current_nb_bytes_written, p_stream, p_manager)) { return OPJ_FALSE; } @@ -11559,7 +11610,10 @@ static OPJ_BOOL opj_j2k_write_all_tile_parts(opj_j2k_t *p_j2k, l_part_tile_size = 0; l_begin_data = p_data; - if (! opj_j2k_write_sot(p_j2k, p_data, &l_current_nb_bytes_written, p_stream, + if (! opj_j2k_write_sot(p_j2k, p_data, + p_total_data_size, + &l_current_nb_bytes_written, + p_stream, p_manager)) { return OPJ_FALSE; } @@ -11602,7 +11656,9 @@ static OPJ_BOOL opj_j2k_write_all_tile_parts(opj_j2k_t *p_j2k, l_part_tile_size = 0; l_begin_data = p_data; - if (! opj_j2k_write_sot(p_j2k, p_data, &l_current_nb_bytes_written, p_stream, + if (! opj_j2k_write_sot(p_j2k, p_data, + p_total_data_size, + &l_current_nb_bytes_written, p_stream, p_manager)) { return OPJ_FALSE; }