opj_jp2_check_color(): replace assertion regarding mtyp by runtime check (#672, ...
[openjpeg.git] / src / lib / openjp2 / j2k.c
index 980a8467c1fce0127508d2b771a286c637701216..8bd77f430c2fef6b36d54041baad39bedf751948 100644 (file)
@@ -48,6 +48,8 @@
 /** @name Local static functions */
 /*@{*/
 
+#define OPJ_UNUSED(x) (void)x
+
 /**
  * Sets up the procedures to do on reading header. Developpers wanting to extend the library can add their own reading procedures.
  */
@@ -1791,6 +1793,9 @@ static OPJ_BOOL opj_j2k_calculate_tp(opj_j2k_t *p_j2k,
     assert(p_j2k != 00);
     assert(p_manager != 00);
 
+    OPJ_UNUSED(p_j2k);
+    OPJ_UNUSED(p_manager);
+
     l_nb_tiles = cp->tw * cp->th;
     * p_nb_tiles = 0;
     tcp = cp->tcps;
@@ -2226,9 +2231,12 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
                           i, l_img_comp->dx, l_img_comp->dy);
             return OPJ_FALSE;
         }
-        if (l_img_comp->prec > 38) { /* TODO openjpeg won't handle more than ? */
+        /* Avoids later undefined shift in computation of */
+        /* p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps[i].m_dc_level_shift = 1
+                    << (l_image->comps[i].prec - 1); */
+        if (l_img_comp->prec > 32) {
             opj_event_msg(p_manager, EVT_ERROR,
-                          "Invalid values for comp = %d : prec=%u (should be between 1 and 38 according to the JPEG2000 norm)\n",
+                          "Invalid values for comp = %d : prec=%u (should be between 1 and 38 according to the JPEG2000 norm. OpenJpeg only supports up to 32)\n",
                           i, l_img_comp->prec);
             return OPJ_FALSE;
         }
@@ -2505,7 +2513,11 @@ static OPJ_BOOL opj_j2k_read_com(opj_j2k_t *p_j2k,
     assert(p_j2k != 00);
     assert(p_manager != 00);
     assert(p_header_data != 00);
-    (void)p_header_size;
+
+    OPJ_UNUSED(p_j2k);
+    OPJ_UNUSED(p_header_data);
+    OPJ_UNUSED(p_header_size);
+    OPJ_UNUSED(p_manager);
 
     return OPJ_TRUE;
 }
@@ -3284,6 +3296,8 @@ static void opj_j2k_write_poc_in_memory(opj_j2k_t *p_j2k,
     assert(p_j2k != 00);
     assert(p_manager != 00);
 
+    OPJ_UNUSED(p_manager);
+
     l_tcp = &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number];
     l_tccp = &l_tcp->tccps[0];
     l_image = p_j2k->m_private_image;
@@ -3523,6 +3537,8 @@ static OPJ_BOOL opj_j2k_read_crg(opj_j2k_t *p_j2k,
     assert(p_j2k != 00);
     assert(p_manager != 00);
 
+    OPJ_UNUSED(p_header_data);
+
     l_nb_comp = p_j2k->m_private_image->numcomps;
 
     if (p_header_size != l_nb_comp * 4) {
@@ -3564,6 +3580,8 @@ static OPJ_BOOL opj_j2k_read_tlm(opj_j2k_t *p_j2k,
     assert(p_j2k != 00);
     assert(p_manager != 00);
 
+    OPJ_UNUSED(p_j2k);
+
     if (p_header_size < 2) {
         opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n");
         return OPJ_FALSE;
@@ -3621,6 +3639,9 @@ static OPJ_BOOL opj_j2k_read_plm(opj_j2k_t *p_j2k,
     assert(p_j2k != 00);
     assert(p_manager != 00);
 
+    OPJ_UNUSED(p_j2k);
+    OPJ_UNUSED(p_header_data);
+
     if (p_header_size < 1) {
         opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n");
         return OPJ_FALSE;
@@ -3693,6 +3714,8 @@ static OPJ_BOOL opj_j2k_read_plt(opj_j2k_t *p_j2k,
     assert(p_j2k != 00);
     assert(p_manager != 00);
 
+    OPJ_UNUSED(p_j2k);
+
     if (p_header_size < 1) {
         opj_event_msg(p_manager, EVT_ERROR, "Error reading PLT marker\n");
         return OPJ_FALSE;
@@ -4156,6 +4179,9 @@ static OPJ_BOOL opj_j2k_write_sot(opj_j2k_t *p_j2k,
     assert(p_manager != 00);
     assert(p_stream != 00);
 
+    OPJ_UNUSED(p_stream);
+    OPJ_UNUSED(p_manager);
+
     opj_write_bytes(p_data, J2K_MS_SOT,
                     2);                                 /* SOT */
     p_data += 2;
@@ -4260,6 +4286,24 @@ static OPJ_BOOL opj_j2k_read_sot(opj_j2k_t *p_j2k,
     l_tile_x = p_j2k->m_current_tile_number % l_cp->tw;
     l_tile_y = p_j2k->m_current_tile_number / l_cp->tw;
 
+    /* Fixes issue with id_000020,sig_06,src_001958,op_flip4,pos_149 */
+    /* of https://github.com/uclouvain/openjpeg/issues/939 */
+    /* We must avoid reading twice the same tile part number for a given tile */
+    /* so as to avoid various issues, like opj_j2k_merge_ppt being called */
+    /* several times. */
+    /* ISO 15444-1 A.4.2 Start of tile-part (SOT) mandates that tile parts */
+    /* should appear in increasing order. */
+    if (l_tcp->m_current_tile_part_number + 1 != (OPJ_INT32)l_current_part) {
+        opj_event_msg(p_manager, EVT_ERROR,
+                      "Invalid tile part index for tile number %d. "
+                      "Got %d, expected %d\n",
+                      p_j2k->m_current_tile_number,
+                      l_current_part,
+                      l_tcp->m_current_tile_part_number + 1);
+        return OPJ_FALSE;
+    }
+    ++ l_tcp->m_current_tile_part_number;
+
 #ifdef USE_JPWL
     if (l_cp->correct) {
 
@@ -4520,6 +4564,8 @@ static OPJ_BOOL opj_j2k_write_sod(opj_j2k_t *p_j2k,
     assert(p_manager != 00);
     assert(p_stream != 00);
 
+    OPJ_UNUSED(p_stream);
+
     opj_write_bytes(p_data, J2K_MS_SOD,
                     2);                                 /* SOD */
     p_data += 2;
@@ -4916,6 +4962,8 @@ static OPJ_BOOL opj_j2k_update_rates(opj_j2k_t *p_j2k,
     assert(p_manager != 00);
     assert(p_stream != 00);
 
+    OPJ_UNUSED(p_manager);
+
     l_cp = &(p_j2k->m_cp);
     l_image = p_j2k->m_private_image;
     l_tcp = l_cp->tcps;
@@ -5124,6 +5172,8 @@ static OPJ_BOOL opj_j2k_get_end_header(opj_j2k_t *p_j2k,
     assert(p_manager != 00);
     assert(p_stream != 00);
 
+    OPJ_UNUSED(p_manager);
+
     p_j2k->cstr_index->main_head_end = opj_stream_tell(p_stream);
 
     return OPJ_TRUE;
@@ -5264,6 +5314,8 @@ static OPJ_BOOL opj_j2k_write_epc(opj_j2k_t *p_j2k,
     assert(p_manager != 00);
     assert(p_stream != 00);
 
+    OPJ_UNUSED(p_manager);
+
     l_cstr_index = p_j2k->cstr_index;
     if (l_cstr_index) {
         l_cstr_index->codestream_size = (OPJ_UINT64)opj_stream_tell(p_stream);
@@ -6218,6 +6270,13 @@ static OPJ_BOOL opj_j2k_read_cbd(opj_j2k_t *p_j2k,
         ++p_header_data;
         l_comp->sgnd = (l_comp_def >> 7) & 1;
         l_comp->prec = (l_comp_def & 0x7f) + 1;
+
+        if (l_comp->prec > 32) {
+            opj_event_msg(p_manager, EVT_ERROR,
+                          "Invalid values for comp = %d : prec=%u (should be between 1 and 38 according to the JPEG2000 norm. OpenJpeg only supports up to 32)\n",
+                          i, l_comp->prec);
+            return OPJ_FALSE;
+        }
         ++l_comp;
     }
 
@@ -7291,6 +7350,9 @@ static OPJ_BOOL opj_j2k_mct_validation(opj_j2k_t * p_j2k,
     assert(p_stream != 00);
     assert(p_manager != 00);
 
+    OPJ_UNUSED(p_stream);
+    OPJ_UNUSED(p_manager);
+
     if ((p_j2k->m_cp.rsiz & 0x8200) == 0x8200) {
         OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
         opj_tcp_t * l_tcp = p_j2k->m_cp.tcps;
@@ -7510,6 +7572,8 @@ static OPJ_BOOL opj_j2k_encoding_validation(opj_j2k_t * p_j2k,
     assert(p_stream != 00);
     assert(p_manager != 00);
 
+    OPJ_UNUSED(p_stream);
+
     /* STATE checking */
     /* make sure the state is at 0 */
     l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NONE);
@@ -7560,6 +7624,9 @@ static OPJ_BOOL opj_j2k_decoding_validation(opj_j2k_t *p_j2k,
     assert(p_stream != 00);
     assert(p_manager != 00);
 
+    OPJ_UNUSED(p_stream);
+    OPJ_UNUSED(p_manager);
+
     /* STATE checking */
     /* make sure the state is at 0 */
 #ifdef TODO_MSD
@@ -7672,6 +7739,10 @@ static OPJ_BOOL opj_j2k_read_header_procedure(opj_j2k_t *p_j2k,
         /* read 2 bytes as the marker size */
         opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, &l_marker_size,
                        2);
+        if (l_marker_size < 2) {
+            opj_event_msg(p_manager, EVT_ERROR, "Invalid marker size\n");
+            return OPJ_FALSE;
+        }
         l_marker_size -= 2; /* Subtract the size of the marker ID already read */
 
         /* Check if the marker size is compatible with the header data size */
@@ -7813,6 +7884,8 @@ static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd(opj_j2k_t * p_j2k,
     assert(p_stream != 00);
     assert(p_manager != 00);
 
+    OPJ_UNUSED(p_stream);
+
     l_image = p_j2k->m_private_image;
     l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
     l_tcp = p_j2k->m_cp.tcps;
@@ -7831,6 +7904,7 @@ static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd(opj_j2k_t * p_j2k,
         l_tcp->cod = 0;
         l_tcp->ppt = 0;
         l_tcp->ppt_data = 00;
+        l_tcp->m_current_tile_part_number = -1;
         /* Remove memory not owned by this tile in case of early error return. */
         l_tcp->m_mct_decoding_matrix = 00;
         l_tcp->m_nb_max_mct_records = 0;
@@ -10365,6 +10439,8 @@ static OPJ_BOOL opj_j2k_decode_one_tile(opj_j2k_t *p_j2k,
     OPJ_INT32 l_tile_x0, l_tile_y0, l_tile_x1, l_tile_y1;
     OPJ_UINT32 l_nb_comps;
     OPJ_BYTE * l_current_data;
+    OPJ_UINT32 l_nb_tiles;
+    OPJ_UINT32 i;
 
     l_current_data = (OPJ_BYTE*)opj_malloc(1000);
     if (! l_current_data) {
@@ -10409,6 +10485,15 @@ static OPJ_BOOL opj_j2k_decode_one_tile(opj_j2k_t *p_j2k,
             }
         }
 
+    /* Reset current tile part number for all tiles, and not only the one */
+    /* of interest. */
+    /* Not completely sure this is always correct but required for */
+    /* ./build/bin/j2k_random_tile_access ./build/tests/tte1.j2k */
+    l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th;
+    for (i = 0; i < l_nb_tiles; ++i) {
+        p_j2k->m_cp.tcps[i].m_current_tile_part_number = -1;
+    }
+
     for (;;) {
         if (! opj_j2k_read_tile_header(p_j2k,
                                        &l_current_tile_no,
@@ -11442,6 +11527,9 @@ static OPJ_BOOL opj_j2k_end_encoding(opj_j2k_t *p_j2k,
     assert(p_manager != 00);
     assert(p_stream != 00);
 
+    OPJ_UNUSED(p_stream);
+    OPJ_UNUSED(p_manager);
+
     opj_tcd_destroy(p_j2k->m_tcd);
     p_j2k->m_tcd = 00;
 
@@ -11474,6 +11562,9 @@ static OPJ_BOOL opj_j2k_destroy_header_memory(opj_j2k_t * p_j2k,
     assert(p_stream != 00);
     assert(p_manager != 00);
 
+    OPJ_UNUSED(p_stream);
+    OPJ_UNUSED(p_manager);
+
     if (p_j2k->m_specific_param.m_encoder.m_header_tile_data) {
         opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data);
         p_j2k->m_specific_param.m_encoder.m_header_tile_data = 0;
@@ -11496,6 +11587,8 @@ static OPJ_BOOL opj_j2k_init_info(opj_j2k_t *p_j2k,
     assert(p_stream != 00);
     (void)l_cstr_info;
 
+    OPJ_UNUSED(p_stream);
+
     /* TODO mergeV2: check this part which use cstr_info */
     /*l_cstr_info = p_j2k->cstr_info;
 
@@ -11557,6 +11650,8 @@ static OPJ_BOOL opj_j2k_create_tcd(opj_j2k_t *p_j2k,
     assert(p_manager != 00);
     assert(p_stream != 00);
 
+    OPJ_UNUSED(p_stream);
+
     p_j2k->m_tcd = opj_tcd_create(OPJ_FALSE);
 
     if (! p_j2k->m_tcd) {