From 84f3bebbff515f2b00ccf0c817930ebb10b91760 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 12 Feb 2020 15:55:16 +0100 Subject: [PATCH] Implement writing of IMF profiles Add -IMF switch to opj_compress as well --- src/bin/jp2/opj_compress.c | 143 +++++- src/lib/openjp2/j2k.c | 625 +++++++++++++++++++++++- src/lib/openjp2/openjpeg.c | 8 +- src/lib/openjp2/openjpeg.h | 30 ++ src/lib/openjp2/opj_common.h | 6 + src/lib/openjp2/pi.c | 3 +- src/lib/openjp2/tcd.c | 2 +- tests/nonregression/CMakeLists.txt | 28 +- tests/nonregression/test_suite.ctest.in | 7 + 9 files changed, 819 insertions(+), 33 deletions(-) diff --git a/src/bin/jp2/opj_compress.c b/src/bin/jp2/opj_compress.c index 148bf951..6ccfec0e 100644 --- a/src/bin/jp2/opj_compress.c +++ b/src/bin/jp2/opj_compress.c @@ -287,6 +287,13 @@ static void encode_help_display(void) fprintf(stdout, "-cinema4K\n"); fprintf(stdout, " Digital Cinema 4K profile compliant codestream.\n"); fprintf(stdout, " Frames per second not required. Default value is 24fps.\n"); + fprintf(stdout, "-IMF profile=P[,mainlevel=X][,sublevel=Y][,framerate=FPS]\n"); + fprintf(stdout, " Interoperable Master Format compliant codestream.\n"); + fprintf(stdout, " P=2K, 4K, 8K, 2K_R, 4K_R or 8K_R.\n"); + fprintf(stdout, " X >= 0 and X <= 11.\n"); + fprintf(stdout, " Y >= 0 and Y <= 9.\n"); + fprintf(stdout, + " framerate > 0 may be specified to enhance checks and set maximum bit rate when Y > 0.\n"); fprintf(stdout, "-jpip\n"); fprintf(stdout, " Write jpip codestream index box in JP2 output file.\n"); fprintf(stdout, " Currently supports only RPCL order.\n"); @@ -568,7 +575,8 @@ static char get_next_file(int imageno, dircnt_t *dirptr, img_fol_t *img_fol, static int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters, img_fol_t *img_fol, raw_cparameters_t *raw_cp, char *indexfilename, - size_t indexfilename_size) + size_t indexfilename_size, + int* pOutFramerate) { OPJ_UINT32 i, j; int totlen, c; @@ -583,7 +591,8 @@ static int parse_cmdline_encoder(int argc, char **argv, {"POC", REQ_ARG, NULL, 'P'}, {"ROI", REQ_ARG, NULL, 'R'}, {"jpip", NO_ARG, NULL, 'J'}, - {"mct", REQ_ARG, NULL, 'Y'} + {"mct", REQ_ARG, NULL, 'Y'}, + {"IMF", REQ_ARG, NULL, 'Z'} }; /* parse the command line */ @@ -1129,6 +1138,98 @@ static int parse_cmdline_encoder(int argc, char **argv, /* ------------------------------------------------------ */ + case 'Z': { /* IMF profile*/ + int mainlevel = 0; + int sublevel = 0; + int profile = 0; + int framerate = 0; + const char* msg = + "Wrong value for -IMF. Should be " + "profile[,mainlevel=X][,sublevel=Y][,framerate=FPS] where profile is one " + "of 2K/4K/8K/2K_R/4K_R/8K_R.\n"; + char* comma; + + comma = strstr(opj_optarg, ",mainlevel="); + if (comma && sscanf(comma + 1, "mainlevel=%d", &mainlevel) != 1) { + fprintf(stderr, "%s", msg); + return 1; + } + + comma = strstr(opj_optarg, ",sublevel="); + if (comma && sscanf(comma + 1, "sublevel=%d", &sublevel) != 1) { + fprintf(stderr, "%s", msg); + return 1; + } + + comma = strstr(opj_optarg, ",framerate="); + if (comma && sscanf(comma + 1, "framerate=%d", &framerate) != 1) { + fprintf(stderr, "%s", msg); + return 1; + } + + comma = strchr(opj_optarg, ','); + if (comma != NULL) { + *comma = 0; + } + + if (strcmp(opj_optarg, "2K") == 0) { + profile = OPJ_PROFILE_IMF_2K; + } else if (strcmp(opj_optarg, "4K") == 0) { + profile = OPJ_PROFILE_IMF_4K; + } else if (strcmp(opj_optarg, "8K") == 0) { + profile = OPJ_PROFILE_IMF_8K; + } else if (strcmp(opj_optarg, "2K_R") == 0) { + profile = OPJ_PROFILE_IMF_2K_R; + } else if (strcmp(opj_optarg, "4K_R") == 0) { + profile = OPJ_PROFILE_IMF_4K_R; + } else if (strcmp(opj_optarg, "8K_R") == 0) { + profile = OPJ_PROFILE_IMF_8K_R; + } else { + fprintf(stderr, "%s", msg); + return 1; + } + + if (!(mainlevel >= 0 && mainlevel <= 15)) { + /* Voluntarily rough validation. More fine grained done in library */ + fprintf(stderr, "Invalid mainlevel value.\n"); + return 1; + } + if (!(sublevel >= 0 && sublevel <= 15)) { + /* Voluntarily rough validation. More fine grained done in library */ + fprintf(stderr, "Invalid sublevel value.\n"); + return 1; + } + parameters->rsiz = (OPJ_UINT16)(profile | (sublevel << 4) | mainlevel); + + fprintf(stdout, "IMF profile activated\n" + "Other options specified could be overridden\n"); + + if (pOutFramerate) { + *pOutFramerate = framerate; + } + if (framerate > 0 && sublevel > 0 && sublevel <= 9) { + const int limitMBitsSec[] = { + 0, + OPJ_IMF_SUBLEVEL_1_MBITSSEC, + OPJ_IMF_SUBLEVEL_2_MBITSSEC, + OPJ_IMF_SUBLEVEL_3_MBITSSEC, + OPJ_IMF_SUBLEVEL_4_MBITSSEC, + OPJ_IMF_SUBLEVEL_5_MBITSSEC, + OPJ_IMF_SUBLEVEL_6_MBITSSEC, + OPJ_IMF_SUBLEVEL_7_MBITSSEC, + OPJ_IMF_SUBLEVEL_8_MBITSSEC, + OPJ_IMF_SUBLEVEL_9_MBITSSEC + }; + parameters->max_cs_size = limitMBitsSec[sublevel] * (1000 * 1000 / 8) / + framerate; + fprintf(stdout, "Setting max codestream size to %d bytes.\n", + parameters->max_cs_size); + } + } + break; + + /* ------------------------------------------------------ */ + case 'Y': { /* Shall we do an MCT ? 0:no_mct;1:rgb->ycc;2:custom mct (-m option required)*/ int mct_mode = 0; sscanf(opj_optarg, "%d", &mct_mode); @@ -1744,6 +1845,7 @@ int main(int argc, char **argv) OPJ_BOOL bSuccess; OPJ_BOOL bUseTiles = OPJ_FALSE; /* OPJ_TRUE */ OPJ_UINT32 l_nb_tiles = 4; + int framerate = 0; OPJ_FLOAT64 t = opj_clock(); /* set encoding parameters to default values */ @@ -1765,7 +1867,7 @@ 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)) == 1) { + indexfilename, sizeof(indexfilename), &framerate) == 1) { ret = 1; goto fin; } @@ -1940,6 +2042,41 @@ int main(int argc, char **argv) } } + if (OPJ_IS_IMF(parameters.rsiz) && framerate > 0) { + const int mainlevel = OPJ_GET_IMF_MAINLEVEL(parameters.rsiz); + if (mainlevel > 0 && mainlevel <= OPJ_IMF_MAINLEVEL_MAX) { + const int limitMSamplesSec[] = { + 0, + OPJ_IMF_MAINLEVEL_1_MSAMPLESEC, + OPJ_IMF_MAINLEVEL_2_MSAMPLESEC, + OPJ_IMF_MAINLEVEL_3_MSAMPLESEC, + OPJ_IMF_MAINLEVEL_4_MSAMPLESEC, + OPJ_IMF_MAINLEVEL_5_MSAMPLESEC, + OPJ_IMF_MAINLEVEL_6_MSAMPLESEC, + OPJ_IMF_MAINLEVEL_7_MSAMPLESEC, + OPJ_IMF_MAINLEVEL_8_MSAMPLESEC, + OPJ_IMF_MAINLEVEL_9_MSAMPLESEC, + OPJ_IMF_MAINLEVEL_10_MSAMPLESEC, + OPJ_IMF_MAINLEVEL_11_MSAMPLESEC + }; + OPJ_UINT32 avgcomponents = image->numcomps; + double msamplespersec; + if (image->numcomps == 3 && + image->comps[1].dx == 2 && + image->comps[1].dy == 2) { + avgcomponents = 2; + } + msamplespersec = (double)image->x1 * image->y1 * avgcomponents * framerate / + 1e6; + if (msamplespersec > limitMSamplesSec[mainlevel]) { + fprintf(stderr, + "Warning: MSamples/sec is %f, whereas limit is %d.\n", + msamplespersec, + limitMSamplesSec[mainlevel]); + } + } + } + /* encode the destination image */ /* ---------------------------- */ diff --git a/src/lib/openjp2/j2k.c b/src/lib/openjp2/j2k.c index 922550eb..8e59f8b5 100644 --- a/src/lib/openjp2/j2k.c +++ b/src/lib/openjp2/j2k.c @@ -1284,6 +1284,13 @@ static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, 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. * @@ -5183,7 +5190,7 @@ static OPJ_BOOL opj_j2k_update_rates(opj_j2k_t *p_j2k, 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); @@ -6611,7 +6618,7 @@ static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, } /* Precincts */ - parameters->csty |= 0x01; + parameters->csty |= J2K_CP_CSTY_PRT; if (parameters->numresolution == 1) { parameters->res_spec = 1; parameters->prcw_init[0] = 128; @@ -6737,6 +6744,589 @@ static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, 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, @@ -6929,6 +7519,15 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, } 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 * @@ -6969,9 +7568,10 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, "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, @@ -7147,7 +7747,7 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, 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]; } @@ -11604,7 +12204,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)) { + 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; @@ -11687,7 +12287,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)) { + 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; @@ -11714,7 +12314,8 @@ static OPJ_BOOL opj_j2k_setup_header_writing(opj_j2k_t *p_j2k, } /* 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; @@ -11819,7 +12420,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)) { + if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) { opj_j2k_update_tlm(p_j2k, l_nb_bytes_written); } @@ -11889,7 +12490,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)) { + if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) { opj_j2k_update_tlm(p_j2k, l_part_tile_size); } @@ -11935,7 +12536,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)) { + if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) { opj_j2k_update_tlm(p_j2k, l_part_tile_size); } diff --git a/src/lib/openjp2/openjpeg.c b/src/lib/openjp2/openjpeg.c index 7b123034..e406cb49 100644 --- a/src/lib/openjp2/openjpeg.c +++ b/src/lib/openjp2/openjpeg.c @@ -718,11 +718,11 @@ void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t parameters->cp_cinema = OPJ_OFF; /* DEPRECATED */ parameters->rsiz = OPJ_PROFILE_NONE; parameters->max_comp_size = 0; - parameters->numresolution = 6; + parameters->numresolution = OPJ_COMP_PARAM_DEFAULT_NUMRESOLUTION; parameters->cp_rsiz = OPJ_STD_RSIZ; /* DEPRECATED */ - parameters->cblockw_init = 64; - parameters->cblockh_init = 64; - parameters->prog_order = OPJ_LRCP; + parameters->cblockw_init = OPJ_COMP_PARAM_DEFAULT_CBLOCKW; + parameters->cblockh_init = OPJ_COMP_PARAM_DEFAULT_CBLOCKH; + parameters->prog_order = OPJ_COMP_PARAM_DEFAULT_PROG_ORDER; parameters->roi_compno = -1; /* no ROI */ parameters->subsampling_dx = 1; parameters->subsampling_dy = 1; diff --git a/src/lib/openjp2/openjpeg.h b/src/lib/openjp2/openjpeg.h index dfc09f1e..50ed02d8 100644 --- a/src/lib/openjp2/openjpeg.h +++ b/src/lib/openjp2/openjpeg.h @@ -225,6 +225,36 @@ typedef size_t OPJ_SIZE_T; #define OPJ_IS_IMF(v) (((v) >= OPJ_PROFILE_IMF_2K)&&((v) <= ((OPJ_PROFILE_IMF_8K_R) | (0x009b)))) #define OPJ_IS_PART2(v) ((v) & OPJ_PROFILE_PART2) +#define OPJ_GET_IMF_PROFILE(v) ((v) & 0xff00) /** Extract IMF profile without mainlevel/sublevel */ +#define OPJ_GET_IMF_MAINLEVEL(v) ((v) & 0xf) /** Extract IMF main level */ +#define OPJ_GET_IMF_SUBLEVEL(v) (((v) >> 4) & 0xf) /** Extract IMF sub level */ + +#define OPJ_IMF_MAINLEVEL_MAX 11 /** Maximum main level */ + +/** Max. Components Sampling Rate (MSamples/sec) per IMF main level */ +#define OPJ_IMF_MAINLEVEL_1_MSAMPLESEC 65 /** MSamples/sec for IMF main level 1 */ +#define OPJ_IMF_MAINLEVEL_2_MSAMPLESEC 130 /** MSamples/sec for IMF main level 2 */ +#define OPJ_IMF_MAINLEVEL_3_MSAMPLESEC 195 /** MSamples/sec for IMF main level 3 */ +#define OPJ_IMF_MAINLEVEL_4_MSAMPLESEC 260 /** MSamples/sec for IMF main level 4 */ +#define OPJ_IMF_MAINLEVEL_5_MSAMPLESEC 520 /** MSamples/sec for IMF main level 5 */ +#define OPJ_IMF_MAINLEVEL_6_MSAMPLESEC 1200 /** MSamples/sec for IMF main level 6 */ +#define OPJ_IMF_MAINLEVEL_7_MSAMPLESEC 2400 /** MSamples/sec for IMF main level 7 */ +#define OPJ_IMF_MAINLEVEL_8_MSAMPLESEC 4800 /** MSamples/sec for IMF main level 8 */ +#define OPJ_IMF_MAINLEVEL_9_MSAMPLESEC 9600 /** MSamples/sec for IMF main level 9 */ +#define OPJ_IMF_MAINLEVEL_10_MSAMPLESEC 19200 /** MSamples/sec for IMF main level 10 */ +#define OPJ_IMF_MAINLEVEL_11_MSAMPLESEC 38400 /** MSamples/sec for IMF main level 11 */ + +/** Max. compressed Bit Rate (Mbits/s) per IMF sub level */ +#define OPJ_IMF_SUBLEVEL_1_MBITSSEC 200 /** Mbits/s for IMF sub level 1 */ +#define OPJ_IMF_SUBLEVEL_2_MBITSSEC 400 /** Mbits/s for IMF sub level 2 */ +#define OPJ_IMF_SUBLEVEL_3_MBITSSEC 800 /** Mbits/s for IMF sub level 3 */ +#define OPJ_IMF_SUBLEVEL_4_MBITSSEC 1600 /** Mbits/s for IMF sub level 4 */ +#define OPJ_IMF_SUBLEVEL_5_MBITSSEC 3200 /** Mbits/s for IMF sub level 5 */ +#define OPJ_IMF_SUBLEVEL_6_MBITSSEC 6400 /** Mbits/s for IMF sub level 6 */ +#define OPJ_IMF_SUBLEVEL_7_MBITSSEC 12800 /** Mbits/s for IMF sub level 7 */ +#define OPJ_IMF_SUBLEVEL_8_MBITSSEC 25600 /** Mbits/s for IMF sub level 8 */ +#define OPJ_IMF_SUBLEVEL_9_MBITSSEC 51200 /** Mbits/s for IMF sub level 9 */ + /** * JPEG 2000 codestream and component size limits in cinema profiles * */ diff --git a/src/lib/openjp2/opj_common.h b/src/lib/openjp2/opj_common.h index a0513391..ee8adf47 100644 --- a/src/lib/openjp2/opj_common.h +++ b/src/lib/openjp2/opj_common.h @@ -38,4 +38,10 @@ */ #define OPJ_COMMON_CBLK_DATA_EXTRA 2 /**< Margin for a fake FFFF marker */ + +#define OPJ_COMP_PARAM_DEFAULT_CBLOCKW 64 +#define OPJ_COMP_PARAM_DEFAULT_CBLOCKH 64 +#define OPJ_COMP_PARAM_DEFAULT_PROG_ORDER OPJ_LRCP +#define OPJ_COMP_PARAM_DEFAULT_NUMRESOLUTION 6 + #endif /* OPJ_COMMMON_H */ diff --git a/src/lib/openjp2/pi.c b/src/lib/openjp2/pi.c index 3ddb4a0c..75431b7a 100644 --- a/src/lib/openjp2/pi.c +++ b/src/lib/openjp2/pi.c @@ -1761,7 +1761,8 @@ void opj_pi_create_encode(opj_pi_iterator_t *pi, pi[pino].poc.prg = tcp->prg; if (!(cp->m_specific_param.m_enc.m_tp_on && ((!OPJ_IS_CINEMA(cp->rsiz) && - (t2_mode == FINAL_PASS)) || OPJ_IS_CINEMA(cp->rsiz)))) { + !OPJ_IS_IMF(cp->rsiz) && + (t2_mode == FINAL_PASS)) || OPJ_IS_CINEMA(cp->rsiz) || OPJ_IS_IMF(cp->rsiz)))) { pi[pino].poc.resno0 = tcp->resS; pi[pino].poc.resno1 = tcp->resE; pi[pino].poc.compno0 = tcp->compS; diff --git a/src/lib/openjp2/tcd.c b/src/lib/openjp2/tcd.c index aa419030..c5640066 100644 --- a/src/lib/openjp2/tcd.c +++ b/src/lib/openjp2/tcd.c @@ -573,7 +573,7 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, opj_tcd_makelayer(tcd, layno, thresh, 0); if (cp->m_specific_param.m_enc.m_fixed_quality) { /* fixed_quality */ - if (OPJ_IS_CINEMA(cp->rsiz)) { + if (OPJ_IS_CINEMA(cp->rsiz) || OPJ_IS_IMF(cp->rsiz)) { if (! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, p_data_written, maxlen, cstr_info, tcd->cur_tp_num, tcd->tp_pos, tcd->cur_pino, THRESH_CALC, p_manager)) { diff --git a/tests/nonregression/CMakeLists.txt b/tests/nonregression/CMakeLists.txt index 82eff3c3..9f956b90 100644 --- a/tests/nonregression/CMakeLists.txt +++ b/tests/nonregression/CMakeLists.txt @@ -232,11 +232,13 @@ foreach(OPJ_TEST_CMD_LINE ${OPJ_TEST_CMD_LINE_LIST}) else () # Check if the first argument is equal to opj_compress - string(REGEX MATCH "^opj_compress$|^opj_decompress$" EXE_NAME_FOUND ${EXE_NAME}) + string(REGEX MATCH "^opj_compress$|^opj_compress_no_raw$|^opj_compress_no_raw_lossless$|^opj_decompress$" EXE_NAME_FOUND ${EXE_NAME}) if(EXE_NAME_FOUND) - string(REGEX MATCH "opj_compress" ENC_TEST_FOUND ${EXE_NAME}) + string(REGEX MATCH "^opj_compress$|^opj_compress_no_raw$|^opj_compress_no_raw_lossless$" ENC_TEST_FOUND ${EXE_NAME}) + string(REGEX MATCH "^opj_compress_no_raw$|^opj_compress_no_raw_lossless$" NO_RAW ${EXE_NAME}) + string(REGEX MATCH "opj_compress_no_raw_lossless" LOSSLESS ${EXE_NAME}) else() @@ -330,16 +332,18 @@ foreach(OPJ_TEST_CMD_LINE ${OPJ_TEST_CMD_LINE_LIST}) PROPERTIES DEPENDS NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-encode) - # Compare the decoding file with baseline generated from the kdu_expand and baseline.j2k - add_test(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-compare_dec-ref-out2base - COMMAND compare_raw_files - -b ${BASELINE_NR}/opj_${OUTPUT_FILENAME_NAME_WE}-ENC-${IT_TEST_ENC}.raw - -t ${OUTPUT_FILENAME}.raw - ) + if(NOT NO_RAW) + # Compare the decoding file with baseline generated from the kdu_expand and baseline.j2k + add_test(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-compare_dec-ref-out2base + COMMAND compare_raw_files + -b ${BASELINE_NR}/opj_${OUTPUT_FILENAME_NAME_WE}-ENC-${IT_TEST_ENC}.raw + -t ${OUTPUT_FILENAME}.raw + ) - set_tests_properties(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-compare_dec-ref-out2base - PROPERTIES DEPENDS - NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-decode-ref) + set_tests_properties(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-compare_dec-ref-out2base + PROPERTIES DEPENDS + NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-decode-ref) + endif() endif() @@ -359,7 +363,7 @@ foreach(OPJ_TEST_CMD_LINE ${OPJ_TEST_CMD_LINE_LIST}) # If lossless compression (simple test is 4 arguments), decompress & compare list(LENGTH CMD_ARG_LIST_2 ARG_COUNT) - if (ARG_COUNT EQUAL 4) + if ((ARG_COUNT EQUAL 4) OR LOSSLESS) # can we compare with the input image ? if (${INPUT_FILENAME_NAME} MATCHES "\\.tif$") add_test(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-lossless-decode diff --git a/tests/nonregression/test_suite.ctest.in b/tests/nonregression/test_suite.ctest.in index bda0681f..9d4961af 100644 --- a/tests/nonregression/test_suite.ctest.in +++ b/tests/nonregression/test_suite.ctest.in @@ -176,6 +176,13 @@ opj_compress -i @INPUT_NR_PATH@/byte.tif -o @TEMP_PATH@/byte_one_poc.j2k -n 2 -r opj_compress -i @INPUT_NR_PATH@/byte.tif -o @TEMP_PATH@/byte_one_poc_funky_bounds.j2k -n 2 -r 20,1 -POC T1=0,0,65535,33,255,CPRL -b 4,4 opj_compress -i @INPUT_NR_PATH@/byte.tif -o @TEMP_PATH@/byte_one_poc_unrelated_tile.j2k -n 1 -POC T1000=0,0,1,1,1,CPRL +opj_compress_no_raw -i @INPUT_NR_PATH@/X_4_2K_24_185_CBR_WB_000.tif -o @TEMP_PATH@/X_4_2K_24_185_CBR_WB_000_IMF_2K.j2k -IMF 2K +opj_compress_no_raw -i @INPUT_NR_PATH@/ElephantDream_4K.tif -o @TEMP_PATH@/X_4_2K_24_185_CBR_WB_000_IMF_4K.j2k -IMF 4K +opj_compress_no_raw -i @INPUT_NR_PATH@/ElephantDream_4K.tif -o @TEMP_PATH@/X_4_2K_24_185_CBR_WB_000_IMF_8K.j2k -IMF 8K +opj_compress_no_raw_lossless -i @INPUT_NR_PATH@/X_4_2K_24_185_CBR_WB_000.tif -o @TEMP_PATH@/X_4_2K_24_185_CBR_WB_000_IMF_2K_R.j2k -IMF 2K_R +opj_compress_no_raw_lossless -i @INPUT_NR_PATH@/ElephantDream_4K.tif -o @TEMP_PATH@/X_4_2K_24_185_CBR_WB_000_IMF_4K_R.j2k -IMF 4K_R +opj_compress_no_raw_lossless -i @INPUT_NR_PATH@/ElephantDream_4K.tif -o @TEMP_PATH@/X_4_2K_24_185_CBR_WB_000_IMF_8K_R.j2k -IMF 8K_R + # 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