* A nice message is outputted at errors.
*
* @param p_pocs the progression order changes.
+ * @param tileno the tile number of interest
* @param p_nb_pocs the number of progression order changes.
* @param p_nb_resolutions the number of resolutions.
* @param numcomps the number of components
* @return true if the pocs are valid.
*/
static OPJ_BOOL opj_j2k_check_poc_val(const opj_poc_t *p_pocs,
+ OPJ_UINT32 tileno,
OPJ_UINT32 p_nb_pocs,
OPJ_UINT32 p_nb_resolutions,
OPJ_UINT32 numcomps,
static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz,
opj_event_mgr_t *p_manager);
+static void opj_j2k_set_imf_parameters(opj_cparameters_t *parameters,
+ opj_image_t *image, opj_event_mgr_t *p_manager);
+
+static OPJ_BOOL opj_j2k_is_imf_compliant(opj_cparameters_t *parameters,
+ opj_image_t *image,
+ opj_event_mgr_t *p_manager);
+
/**
* Checks for invalid number of tile-parts in SOT marker (TPsot==TNsot). See issue 254.
*
}
static OPJ_BOOL opj_j2k_check_poc_val(const opj_poc_t *p_pocs,
+ OPJ_UINT32 tileno,
OPJ_UINT32 p_nb_pocs,
OPJ_UINT32 p_nb_resolutions,
OPJ_UINT32 p_num_comps,
OPJ_UINT32 step_r = p_num_comps * step_c;
OPJ_UINT32 step_l = p_nb_resolutions * step_r;
OPJ_BOOL loss = OPJ_FALSE;
- OPJ_UINT32 layno0 = 0;
+
+ assert(p_nb_pocs > 0);
packet_array = (OPJ_UINT32*) opj_calloc(step_l * p_num_layers,
sizeof(OPJ_UINT32));
return OPJ_FALSE;
}
- if (p_nb_pocs == 0) {
- opj_free(packet_array);
- return OPJ_TRUE;
- }
-
- index = step_r * p_pocs->resno0;
- /* take each resolution for each poc */
- for (resno = p_pocs->resno0 ; resno < p_pocs->resno1 ; ++resno) {
- OPJ_UINT32 res_index = index + p_pocs->compno0 * step_c;
-
- /* take each comp of each resolution for each poc */
- for (compno = p_pocs->compno0 ; compno < p_pocs->compno1 ; ++compno) {
- OPJ_UINT32 comp_index = res_index + layno0 * step_l;
-
- /* and finally take each layer of each res of ... */
- for (layno = layno0; layno < p_pocs->layno1 ; ++layno) {
- /*index = step_r * resno + step_c * compno + step_l * layno;*/
- packet_array[comp_index] = 1;
- comp_index += step_l;
- }
-
- res_index += step_c;
- }
-
- index += step_r;
- }
- ++p_pocs;
-
- /* iterate through all the pocs */
- for (i = 1; i < p_nb_pocs ; ++i) {
- OPJ_UINT32 l_last_layno1 = (p_pocs - 1)->layno1 ;
+ /* iterate through all the pocs that match our tile of interest. */
+ for (i = 0; i < p_nb_pocs; ++i) {
+ const opj_poc_t *poc = &p_pocs[i];
+ if (tileno + 1 == poc->tile) {
+ index = step_r * poc->resno0;
- layno0 = (p_pocs->layno1 > l_last_layno1) ? l_last_layno1 : 0;
- index = step_r * p_pocs->resno0;
+ /* take each resolution for each poc */
+ for (resno = poc->resno0 ;
+ resno < opj_uint_min(poc->resno1, p_nb_resolutions); ++resno) {
+ OPJ_UINT32 res_index = index + poc->compno0 * step_c;
- /* take each resolution for each poc */
- for (resno = p_pocs->resno0 ; resno < p_pocs->resno1 ; ++resno) {
- OPJ_UINT32 res_index = index + p_pocs->compno0 * step_c;
+ /* take each comp of each resolution for each poc */
+ for (compno = poc->compno0 ;
+ compno < opj_uint_min(poc->compno1, p_num_comps); ++compno) {
+ /* The layer index always starts at zero for every progression. */
+ const OPJ_UINT32 layno0 = 0;
+ OPJ_UINT32 comp_index = res_index + layno0 * step_l;
- /* take each comp of each resolution for each poc */
- for (compno = p_pocs->compno0 ; compno < p_pocs->compno1 ; ++compno) {
- OPJ_UINT32 comp_index = res_index + layno0 * step_l;
+ /* and finally take each layer of each res of ... */
+ for (layno = layno0; layno < opj_uint_min(poc->layno1, p_num_layers);
+ ++layno) {
+ packet_array[comp_index] = 1;
+ comp_index += step_l;
+ }
- /* and finally take each layer of each res of ... */
- for (layno = layno0; layno < p_pocs->layno1 ; ++layno) {
- /*index = step_r * resno + step_c * compno + step_l * layno;*/
- packet_array[comp_index] = 1;
- comp_index += step_l;
+ res_index += step_c;
}
- res_index += step_c;
+ index += step_r;
}
-
- index += step_r;
}
-
- ++p_pocs;
}
index = 0;
layno, resno, compno);
}
#endif
- /*index = step_r * resno + step_c * compno + step_l * layno;*/
index += step_c;
}
}
return OPJ_FALSE;
}
- if (OPJ_IS_CINEMA(l_cp->rsiz)) {
+ if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) {
p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer =
(OPJ_BYTE *) opj_malloc(5 *
p_j2k->m_specific_param.m_encoder.m_total_tile_parts);
}
/* Precincts */
- parameters->csty |= 0x01;
+ parameters->csty |= J2K_CP_CSTY_PRT;
if (parameters->numresolution == 1) {
parameters->res_spec = 1;
parameters->prcw_init[0] = 128;
return OPJ_TRUE;
}
+static int opj_j2k_get_imf_max_NL(opj_cparameters_t *parameters,
+ opj_image_t *image)
+{
+ /* Decomposition levels */
+ const OPJ_UINT16 rsiz = parameters->rsiz;
+ const OPJ_UINT16 profile = OPJ_GET_IMF_PROFILE(rsiz);
+ const OPJ_UINT32 XTsiz = parameters->tile_size_on ? (OPJ_UINT32)
+ parameters->cp_tdx : image->x1;
+ switch (profile) {
+ case OPJ_PROFILE_IMF_2K:
+ return 5;
+ case OPJ_PROFILE_IMF_4K:
+ return 6;
+ case OPJ_PROFILE_IMF_8K:
+ return 7;
+ case OPJ_PROFILE_IMF_2K_R: {
+ if (XTsiz >= 2048) {
+ return 5;
+ } else if (XTsiz >= 1024) {
+ return 4;
+ }
+ break;
+ }
+ case OPJ_PROFILE_IMF_4K_R: {
+ if (XTsiz >= 4096) {
+ return 6;
+ } else if (XTsiz >= 2048) {
+ return 5;
+ } else if (XTsiz >= 1024) {
+ return 4;
+ }
+ break;
+ }
+ case OPJ_PROFILE_IMF_8K_R: {
+ if (XTsiz >= 8192) {
+ return 7;
+ } else if (XTsiz >= 4096) {
+ return 6;
+ } else if (XTsiz >= 2048) {
+ return 5;
+ } else if (XTsiz >= 1024) {
+ return 4;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return -1;
+}
+
+static void opj_j2k_set_imf_parameters(opj_cparameters_t *parameters,
+ opj_image_t *image, opj_event_mgr_t *p_manager)
+{
+ const OPJ_UINT16 rsiz = parameters->rsiz;
+ const OPJ_UINT16 profile = OPJ_GET_IMF_PROFILE(rsiz);
+
+ OPJ_UNUSED(p_manager);
+
+ /* Override defaults set by opj_set_default_encoder_parameters */
+ if (parameters->cblockw_init == OPJ_COMP_PARAM_DEFAULT_CBLOCKW &&
+ parameters->cblockh_init == OPJ_COMP_PARAM_DEFAULT_CBLOCKH) {
+ parameters->cblockw_init = 32;
+ parameters->cblockh_init = 32;
+ }
+
+ /* One tile part for each component */
+ parameters->tp_flag = 'C';
+ parameters->tp_on = 1;
+
+ if (parameters->prog_order == OPJ_COMP_PARAM_DEFAULT_PROG_ORDER) {
+ parameters->prog_order = OPJ_CPRL;
+ }
+
+ if (profile == OPJ_PROFILE_IMF_2K ||
+ profile == OPJ_PROFILE_IMF_4K ||
+ profile == OPJ_PROFILE_IMF_8K) {
+ /* 9-7 transform */
+ parameters->irreversible = 1;
+ }
+
+ /* Adjust the number of resolutions if set to its defaults */
+ if (parameters->numresolution == OPJ_COMP_PARAM_DEFAULT_NUMRESOLUTION &&
+ image->x0 == 0 &&
+ image->y0 == 0) {
+ const int max_NL = opj_j2k_get_imf_max_NL(parameters, image);
+ if (max_NL >= 0 && parameters->numresolution > max_NL) {
+ parameters->numresolution = max_NL + 1;
+ }
+
+ /* Note: below is generic logic */
+ if (!parameters->tile_size_on) {
+ while (parameters->numresolution > 0) {
+ if (image->x1 < (1U << ((OPJ_UINT32)parameters->numresolution - 1U))) {
+ parameters->numresolution --;
+ continue;
+ }
+ if (image->y1 < (1U << ((OPJ_UINT32)parameters->numresolution - 1U))) {
+ parameters->numresolution --;
+ continue;
+ }
+ break;
+ }
+ }
+ }
+
+ /* Set defaults precincts */
+ if (parameters->csty == 0) {
+ parameters->csty |= J2K_CP_CSTY_PRT;
+ if (parameters->numresolution == 1) {
+ parameters->res_spec = 1;
+ parameters->prcw_init[0] = 128;
+ parameters->prch_init[0] = 128;
+ } else {
+ int i;
+ parameters->res_spec = parameters->numresolution - 1;
+ for (i = 0; i < parameters->res_spec; i++) {
+ parameters->prcw_init[i] = 256;
+ parameters->prch_init[i] = 256;
+ }
+ }
+ }
+}
+
+/* Table A.53 from JPEG2000 standard */
+static const OPJ_UINT16 tabMaxSubLevelFromMainLevel[] = {
+ 15, /* unspecified */
+ 1,
+ 1,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9
+};
+
+static OPJ_BOOL opj_j2k_is_imf_compliant(opj_cparameters_t *parameters,
+ opj_image_t *image,
+ opj_event_mgr_t *p_manager)
+{
+ OPJ_UINT32 i;
+ const OPJ_UINT16 rsiz = parameters->rsiz;
+ const OPJ_UINT16 profile = OPJ_GET_IMF_PROFILE(rsiz);
+ const OPJ_UINT16 mainlevel = OPJ_GET_IMF_MAINLEVEL(rsiz);
+ const OPJ_UINT16 sublevel = OPJ_GET_IMF_SUBLEVEL(rsiz);
+ const int NL = parameters->numresolution - 1;
+ const OPJ_UINT32 XTsiz = parameters->tile_size_on ? (OPJ_UINT32)
+ parameters->cp_tdx : image->x1;
+ OPJ_BOOL ret = OPJ_TRUE;
+
+ /* Validate mainlevel */
+ if (mainlevel > OPJ_IMF_MAINLEVEL_MAX) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profile require mainlevel <= 11.\n"
+ "-> %d is thus not compliant\n"
+ "-> Non-IMF codestream will be generated\n",
+ mainlevel);
+ ret = OPJ_FALSE;
+ }
+
+ /* Validate sublevel */
+ assert(sizeof(tabMaxSubLevelFromMainLevel) ==
+ (OPJ_IMF_MAINLEVEL_MAX + 1) * sizeof(tabMaxSubLevelFromMainLevel[0]));
+ if (sublevel > tabMaxSubLevelFromMainLevel[mainlevel]) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profile require sublevel <= %d for mainlevel = %d.\n"
+ "-> %d is thus not compliant\n"
+ "-> Non-IMF codestream will be generated\n",
+ tabMaxSubLevelFromMainLevel[mainlevel],
+ mainlevel,
+ sublevel);
+ ret = OPJ_FALSE;
+ }
+
+ /* Number of components */
+ if (image->numcomps > 3) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profiles require at most 3 components.\n"
+ "-> Number of components of input image (%d) is not compliant\n"
+ "-> Non-IMF codestream will be generated\n",
+ image->numcomps);
+ ret = OPJ_FALSE;
+ }
+
+ if (image->x0 != 0 || image->y0 != 0) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profiles require image origin to be at 0,0.\n"
+ "-> %d,%d is not compliant\n"
+ "-> Non-IMF codestream will be generated\n",
+ image->x0, image->y0 != 0);
+ ret = OPJ_FALSE;
+ }
+
+ if (parameters->cp_tx0 != 0 || parameters->cp_ty0 != 0) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profiles require tile origin to be at 0,0.\n"
+ "-> %d,%d is not compliant\n"
+ "-> Non-IMF codestream will be generated\n",
+ parameters->cp_tx0, parameters->cp_ty0);
+ ret = OPJ_FALSE;
+ }
+
+ if (parameters->tile_size_on) {
+ if (profile == OPJ_PROFILE_IMF_2K ||
+ profile == OPJ_PROFILE_IMF_4K ||
+ profile == OPJ_PROFILE_IMF_8K) {
+ if ((OPJ_UINT32)parameters->cp_tdx < image->x1 ||
+ (OPJ_UINT32)parameters->cp_tdy < image->y1) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 2K/4K/8K single tile profiles require tile to be greater or equal to image size.\n"
+ "-> %d,%d is lesser than %d,%d\n"
+ "-> Non-IMF codestream will be generated\n",
+ parameters->cp_tdx,
+ parameters->cp_tdy,
+ image->x1,
+ image->y1);
+ ret = OPJ_FALSE;
+ }
+ } else {
+ if ((OPJ_UINT32)parameters->cp_tdx >= image->x1 &&
+ (OPJ_UINT32)parameters->cp_tdy >= image->y1) {
+ /* ok */
+ } else if (parameters->cp_tdx == 1024 &&
+ parameters->cp_tdy == 1024) {
+ /* ok */
+ } else if (parameters->cp_tdx == 2048 &&
+ parameters->cp_tdy == 2048 &&
+ (profile == OPJ_PROFILE_IMF_4K ||
+ profile == OPJ_PROFILE_IMF_8K)) {
+ /* ok */
+ } else if (parameters->cp_tdx == 4096 &&
+ parameters->cp_tdy == 4096 &&
+ profile == OPJ_PROFILE_IMF_8K) {
+ /* ok */
+ } else {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 2K_R/4K_R/8K_R single/multiple tile profiles "
+ "require tile to be greater or equal to image size,\n"
+ "or to be (1024,1024), or (2048,2048) for 4K_R/8K_R "
+ "or (4096,4096) for 8K_R.\n"
+ "-> %d,%d is non conformant\n"
+ "-> Non-IMF codestream will be generated\n",
+ parameters->cp_tdx,
+ parameters->cp_tdy);
+ ret = OPJ_FALSE;
+ }
+ }
+ }
+
+ /* Bitdepth */
+ for (i = 0; i < image->numcomps; i++) {
+ if (!(image->comps[i].bpp >= 8 && image->comps[i].bpp <= 16) ||
+ (image->comps[i].sgnd)) {
+ char signed_str[] = "signed";
+ char unsigned_str[] = "unsigned";
+ char *tmp_str = image->comps[i].sgnd ? signed_str : unsigned_str;
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profiles require precision of each component to b in [8-16] bits unsigned"
+ "-> At least component %d of input image (%d bits, %s) is not compliant\n"
+ "-> Non-IMF codestream will be generated\n",
+ i, image->comps[i].bpp, tmp_str);
+ ret = OPJ_FALSE;
+ }
+ }
+
+ /* Sub-sampling */
+ for (i = 0; i < image->numcomps; i++) {
+ if (i == 0 && image->comps[i].dx != 1) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profiles require XRSiz1 == 1. Here it is set to %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ image->comps[i].dx);
+ ret = OPJ_FALSE;
+ }
+ if (i == 1 && image->comps[i].dx != 1 && image->comps[i].dx != 2) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profiles require XRSiz2 == 1 or 2. Here it is set to %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ image->comps[i].dx);
+ ret = OPJ_FALSE;
+ }
+ if (i > 1 && image->comps[i].dx != image->comps[i - 1].dx) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profiles require XRSiz%d to be the same as XRSiz2. "
+ "Here it is set to %d instead of %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ i + 1, image->comps[i].dx, image->comps[i - 1].dx);
+ ret = OPJ_FALSE;
+ }
+ if (image->comps[i].dy != 1) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profiles require YRsiz == 1. "
+ "Here it is set to %d for component i.\n"
+ "-> Non-IMF codestream will be generated\n",
+ image->comps[i].dy, i);
+ ret = OPJ_FALSE;
+ }
+ }
+
+ /* Image size */
+ switch (profile) {
+ case OPJ_PROFILE_IMF_2K:
+ case OPJ_PROFILE_IMF_2K_R:
+ if (((image->comps[0].w > 2048) | (image->comps[0].h > 1556))) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 2K/2K_R profile require:\n"
+ "width <= 2048 and height <= 1556\n"
+ "-> Input image size %d x %d is not compliant\n"
+ "-> Non-IMF codestream will be generated\n",
+ image->comps[0].w, image->comps[0].h);
+ ret = OPJ_FALSE;
+ }
+ break;
+ case OPJ_PROFILE_IMF_4K:
+ case OPJ_PROFILE_IMF_4K_R:
+ if (((image->comps[0].w > 4096) | (image->comps[0].h > 3112))) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 4K/4K_R profile require:\n"
+ "width <= 4096 and height <= 3112\n"
+ "-> Input image size %d x %d is not compliant\n"
+ "-> Non-IMF codestream will be generated\n",
+ image->comps[0].w, image->comps[0].h);
+ ret = OPJ_FALSE;
+ }
+ break;
+ case OPJ_PROFILE_IMF_8K:
+ case OPJ_PROFILE_IMF_8K_R:
+ if (((image->comps[0].w > 8192) | (image->comps[0].h > 6224))) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 8K/8K_R profile require:\n"
+ "width <= 8192 and height <= 6224\n"
+ "-> Input image size %d x %d is not compliant\n"
+ "-> Non-IMF codestream will be generated\n",
+ image->comps[0].w, image->comps[0].h);
+ ret = OPJ_FALSE;
+ }
+ break;
+ default :
+ assert(0);
+ return OPJ_FALSE;
+ }
+
+ if (parameters->roi_compno != -1) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profile forbid RGN / region of interest marker.\n"
+ "-> Compression parameters specify a ROI\n"
+ "-> Non-IMF codestream will be generated\n");
+ ret = OPJ_FALSE;
+ }
+
+ if (parameters->cblockw_init != 32 || parameters->cblockh_init != 32) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profile require code block size to be 32x32.\n"
+ "-> Compression parameters set it to %dx%d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ parameters->cblockw_init,
+ parameters->cblockh_init);
+ ret = OPJ_FALSE;
+ }
+
+ if (parameters->prog_order != OPJ_CPRL) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profile require progression order to be CPRL.\n"
+ "-> Compression parameters set it to %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ parameters->prog_order);
+ ret = OPJ_FALSE;
+ }
+
+ if (parameters->numpocs != 0) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profile forbid POC markers.\n"
+ "-> Compression parameters set %d POC.\n"
+ "-> Non-IMF codestream will be generated\n",
+ parameters->numpocs);
+ ret = OPJ_FALSE;
+ }
+
+ /* Codeblock style: no mode switch enabled */
+ if (parameters->mode != 0) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profile forbid mode switch in code block style.\n"
+ "-> Compression parameters set code block style to %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ parameters->mode);
+ ret = OPJ_FALSE;
+ }
+
+ if (profile == OPJ_PROFILE_IMF_2K ||
+ profile == OPJ_PROFILE_IMF_4K ||
+ profile == OPJ_PROFILE_IMF_8K) {
+ /* Expect 9-7 transform */
+ if (parameters->irreversible != 1) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 2K/4K/8K profiles require 9-7 Irreversible Transform.\n"
+ "-> Compression parameters set it to reversible.\n"
+ "-> Non-IMF codestream will be generated\n");
+ ret = OPJ_FALSE;
+ }
+ } else {
+ /* Expect 5-3 transform */
+ if (parameters->irreversible != 0) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 2K/4K/8K profiles require 5-3 reversible Transform.\n"
+ "-> Compression parameters set it to irreversible.\n"
+ "-> Non-IMF codestream will be generated\n");
+ ret = OPJ_FALSE;
+ }
+ }
+
+ /* Number of layers */
+ if (parameters->tcp_numlayers != 1) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 2K/4K/8K profiles require 1 single quality layer.\n"
+ "-> Number of layers is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ parameters->tcp_numlayers);
+ ret = OPJ_FALSE;
+ }
+
+ /* Decomposition levels */
+ switch (profile) {
+ case OPJ_PROFILE_IMF_2K:
+ if (!(NL >= 1 && NL <= 5)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 2K profile requires 1 <= NL <= 5:\n"
+ "-> Number of decomposition levels is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ break;
+ case OPJ_PROFILE_IMF_4K:
+ if (!(NL >= 1 && NL <= 6)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 4K profile requires 1 <= NL <= 6:\n"
+ "-> Number of decomposition levels is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ break;
+ case OPJ_PROFILE_IMF_8K:
+ if (!(NL >= 1 && NL <= 7)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 8K profile requires 1 <= NL <= 7:\n"
+ "-> Number of decomposition levels is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ break;
+ case OPJ_PROFILE_IMF_2K_R: {
+ if (XTsiz >= 2048) {
+ if (!(NL >= 1 && NL <= 5)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 2K_R profile requires 1 <= NL <= 5 for XTsiz >= 2048:\n"
+ "-> Number of decomposition levels is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ } else if (XTsiz >= 1024) {
+ if (!(NL >= 1 && NL <= 4)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 2K_R profile requires 1 <= NL <= 4 for XTsiz in [1024,2048[:\n"
+ "-> Number of decomposition levels is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ }
+ break;
+ }
+ case OPJ_PROFILE_IMF_4K_R: {
+ if (XTsiz >= 4096) {
+ if (!(NL >= 1 && NL <= 6)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 4K_R profile requires 1 <= NL <= 6 for XTsiz >= 4096:\n"
+ "-> Number of decomposition levels is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ } else if (XTsiz >= 2048) {
+ if (!(NL >= 1 && NL <= 5)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 4K_R profile requires 1 <= NL <= 5 for XTsiz in [2048,4096[:\n"
+ "-> Number of decomposition levels is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ } else if (XTsiz >= 1024) {
+ if (!(NL >= 1 && NL <= 4)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 4K_R profile requires 1 <= NL <= 4 for XTsiz in [1024,2048[:\n"
+ "-> Number of decomposition levels is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ }
+ break;
+ }
+ case OPJ_PROFILE_IMF_8K_R: {
+ if (XTsiz >= 8192) {
+ if (!(NL >= 1 && NL <= 7)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 4K_R profile requires 1 <= NL <= 7 for XTsiz >= 8192:\n"
+ "-> Number of decomposition levels is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ } else if (XTsiz >= 4096) {
+ if (!(NL >= 1 && NL <= 6)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 4K_R profile requires 1 <= NL <= 6 for XTsiz in [4096,8192[:\n"
+ "-> Number of decomposition levels is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ } else if (XTsiz >= 2048) {
+ if (!(NL >= 1 && NL <= 5)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 4K_R profile requires 1 <= NL <= 5 for XTsiz in [2048,4096[:\n"
+ "-> Number of decomposition levels is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ } else if (XTsiz >= 1024) {
+ if (!(NL >= 1 && NL <= 4)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF 4K_R profile requires 1 <= NL <= 4 for XTsiz in [1024,2048[:\n"
+ "-> Number of decomposition levels is %d.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (parameters->numresolution == 1) {
+ if (parameters->res_spec != 1 ||
+ parameters->prcw_init[0] != 128 ||
+ parameters->prch_init[0] != 128) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profiles require PPx = PPy = 7 for NLLL band, else 8.\n"
+ "-> Supplied values are different from that.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ } else {
+ int i;
+ for (i = 0; i < parameters->res_spec; i++) {
+ if (parameters->prcw_init[i] != 256 ||
+ parameters->prch_init[i] != 256) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "IMF profiles require PPx = PPy = 7 for NLLL band, else 8.\n"
+ "-> Supplied values are different from that.\n"
+ "-> Non-IMF codestream will be generated\n",
+ NL);
+ ret = OPJ_FALSE;
+ }
+ }
+ }
+
+ return ret;
+}
+
+
OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
opj_cparameters_t *parameters,
opj_image_t *image,
} else {
OPJ_FLOAT32 temp_rate;
OPJ_BOOL cap = OPJ_FALSE;
+
+ if (OPJ_IS_IMF(parameters->rsiz) && parameters->max_cs_size > 0 &&
+ parameters->tcp_numlayers == 1 && parameters->tcp_rates[0] == 0) {
+ parameters->tcp_rates[0] = (OPJ_FLOAT32)(image->numcomps * image->comps[0].w *
+ image->comps[0].h * image->comps[0].prec) /
+ (OPJ_FLOAT32)(((OPJ_UINT32)parameters->max_cs_size) * 8 * image->comps[0].dx *
+ image->comps[0].dy);
+ }
+
temp_rate = (OPJ_FLOAT32)(((double)image->numcomps * image->comps[0].w *
image->comps[0].h * image->comps[0].prec) /
(((double)parameters->max_cs_size) * 8 * image->comps[0].dx *
"JPEG 2000 Broadcast profiles not yet supported\n");
parameters->rsiz = OPJ_PROFILE_NONE;
} else if (OPJ_IS_IMF(parameters->rsiz)) {
- opj_event_msg(p_manager, EVT_WARNING,
- "JPEG 2000 IMF profiles not yet supported\n");
- parameters->rsiz = OPJ_PROFILE_NONE;
+ opj_j2k_set_imf_parameters(parameters, image, p_manager);
+ if (!opj_j2k_is_imf_compliant(parameters, image, p_manager)) {
+ parameters->rsiz = OPJ_PROFILE_NONE;
+ }
} else if (OPJ_IS_PART2(parameters->rsiz)) {
if (parameters->rsiz == ((OPJ_PROFILE_PART2) | (OPJ_EXTENSION_NONE))) {
opj_event_msg(p_manager, EVT_WARNING,
"Not enough memory to allocate tile coding parameters\n");
return OPJ_FALSE;
}
- if (parameters->numpocs) {
- /* initialisation of POC */
- opj_j2k_check_poc_val(parameters->POC, parameters->numpocs,
- (OPJ_UINT32)parameters->numresolution, image->numcomps,
- (OPJ_UINT32)parameters->tcp_numlayers, p_manager);
- /* TODO MSD use the return value*/
- }
for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
opj_tcp_t *tcp = &cp->tcps[tileno];
tcp->numlayers = (OPJ_UINT32)parameters->tcp_numlayers;
for (j = 0; j < tcp->numlayers; j++) {
- if (OPJ_IS_CINEMA(cp->rsiz)) {
+ if (OPJ_IS_CINEMA(cp->rsiz) || OPJ_IS_IMF(cp->rsiz)) {
if (cp->m_specific_param.m_enc.m_fixed_quality) {
tcp->distoratio[j] = parameters->tcp_distoratio[j];
}
if (parameters->numpocs) {
/* initialisation of POC */
- tcp->POC = 1;
for (i = 0; i < parameters->numpocs; i++) {
if (tileno + 1 == parameters->POC[i].tile) {
opj_poc_t *tcp_poc = &tcp->pocs[numpocs_tile];
}
}
- tcp->numpocs = numpocs_tile - 1 ;
+ if (numpocs_tile) {
+
+ /* TODO MSD use the return value*/
+ opj_j2k_check_poc_val(parameters->POC, tileno, parameters->numpocs,
+ (OPJ_UINT32)parameters->numresolution, image->numcomps,
+ (OPJ_UINT32)parameters->tcp_numlayers, p_manager);
+
+ tcp->POC = 1;
+ tcp->numpocs = numpocs_tile - 1 ;
+ }
} else {
tcp->numpocs = 0;
}
l_img_comp = p_image->comps;
for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) {
OPJ_INT32 l_h, l_w;
+ if (p_image->x0 > (OPJ_UINT32)INT_MAX ||
+ p_image->y0 > (OPJ_UINT32)INT_MAX ||
+ p_image->x1 > (OPJ_UINT32)INT_MAX ||
+ p_image->y1 > (OPJ_UINT32)INT_MAX) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Image coordinates above INT_MAX are not supported\n");
+ return OPJ_FALSE;
+ }
l_img_comp->x0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->x0,
(OPJ_INT32)l_img_comp->dx);
return OPJ_TRUE;
}
+static OPJ_BOOL opj_j2k_are_all_used_components_decoded(opj_j2k_t *p_j2k,
+ opj_event_mgr_t * p_manager)
+{
+ OPJ_UINT32 compno;
+ OPJ_BOOL decoded_all_used_components = OPJ_TRUE;
+
+ if (p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode) {
+ for (compno = 0;
+ compno < p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode; compno++) {
+ OPJ_UINT32 dec_compno =
+ p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode[compno];
+ if (p_j2k->m_output_image->comps[dec_compno].data == NULL) {
+ opj_event_msg(p_manager, EVT_WARNING, "Failed to decode component %d\n",
+ dec_compno);
+ decoded_all_used_components = OPJ_FALSE;
+ }
+ }
+ } else {
+ for (compno = 0; compno < p_j2k->m_output_image->numcomps; compno++) {
+ if (p_j2k->m_output_image->comps[compno].data == NULL) {
+ opj_event_msg(p_manager, EVT_WARNING, "Failed to decode component %d\n",
+ compno);
+ decoded_all_used_components = OPJ_FALSE;
+ }
+ }
+ }
+
+ if (decoded_all_used_components == OPJ_FALSE) {
+ opj_event_msg(p_manager, EVT_ERROR, "Failed to decode all used components\n");
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+
static OPJ_BOOL opj_j2k_decode_tiles(opj_j2k_t *p_j2k,
opj_stream_private_t *p_stream,
opj_event_mgr_t * p_manager)
}
}
+ if (! opj_j2k_are_all_used_components_decoded(p_j2k, p_manager)) {
+ return OPJ_FALSE;
+ }
+
return OPJ_TRUE;
}
}
+ if (! opj_j2k_are_all_used_components_decoded(p_j2k, p_manager)) {
+ return OPJ_FALSE;
+ }
+
return OPJ_TRUE;
}
return OPJ_FALSE;
}
- if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz)) {
+ if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz) || OPJ_IS_IMF(p_j2k->m_cp.rsiz)) {
if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,
(opj_procedure)opj_j2k_write_updated_tlm, p_manager)) {
return OPJ_FALSE;
return OPJ_FALSE;
}
- if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz)) {
+ if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz) || OPJ_IS_IMF(p_j2k->m_cp.rsiz)) {
if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,
(opj_procedure)opj_j2k_write_tlm, p_manager)) {
return OPJ_FALSE;
}
/* DEVELOPER CORNER, insert your custom procedures */
- if (p_j2k->m_cp.rsiz & OPJ_EXTENSION_MCT) {
+ if ((p_j2k->m_cp.rsiz & (OPJ_PROFILE_PART2 | OPJ_EXTENSION_MCT)) ==
+ (OPJ_PROFILE_PART2 | OPJ_EXTENSION_MCT)) {
if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,
(opj_procedure)opj_j2k_write_mct_data_group, p_manager)) {
return OPJ_FALSE;
opj_write_bytes(l_begin_data + 6, l_nb_bytes_written,
4); /* PSOT */
- if (OPJ_IS_CINEMA(l_cp->rsiz)) {
+ if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) {
opj_j2k_update_tlm(p_j2k, l_nb_bytes_written);
}
opj_write_bytes(l_begin_data + 6, l_part_tile_size,
4); /* PSOT */
- if (OPJ_IS_CINEMA(l_cp->rsiz)) {
+ if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) {
opj_j2k_update_tlm(p_j2k, l_part_tile_size);
}
opj_write_bytes(l_begin_data + 6, l_part_tile_size,
4); /* PSOT */
- if (OPJ_IS_CINEMA(l_cp->rsiz)) {
+ if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) {
opj_j2k_update_tlm(p_j2k, l_part_tile_size);
}