j2k.c: remove hardcoded constants related to m_state, and useless FIXME
[openjpeg.git] / src / lib / openjp2 / j2k.c
index 4c2b9326bd8a07988ea526be3e67e3a76b7b9345..ce7fe019b02a89fb3464fa323ac94c1fff185103 100644 (file)
@@ -2231,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 > 31) {
             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 31)\n",
                           i, l_img_comp->prec);
             return OPJ_FALSE;
         }
@@ -2428,8 +2431,7 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
         ++l_current_tile_param;
     }
 
-    p_j2k->m_specific_param.m_decoder.m_state =
-        J2K_STATE_MH; /* FIXME J2K_DEC_STATE_MH; */
+    p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MH;
     opj_image_comp_header_update(l_image, l_cp);
 
     return OPJ_TRUE;
@@ -2887,7 +2889,7 @@ static OPJ_BOOL opj_j2k_read_coc(opj_j2k_t *p_j2k,
 
     l_cp = &(p_j2k->m_cp);
     l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH)
-            ?  /*FIXME J2K_DEC_STATE_TPH*/
+            ?
             &l_cp->tcps[p_j2k->m_current_tile_number] :
             p_j2k->m_specific_param.m_decoder.m_default_tcp;
     l_image = p_j2k->m_private_image;
@@ -4283,6 +4285,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) {
 
@@ -5528,6 +5548,28 @@ static OPJ_BOOL opj_j2k_read_mct(opj_j2k_t *p_j2k,
                 opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read MCT marker\n");
                 return OPJ_FALSE;
             }
+
+            /* Update m_mcc_records[].m_offset_array and m_decorrelation_array
+             * to point to the new addresses */
+            if (new_mct_records != l_tcp->m_mct_records) {
+                for (i = 0; i < l_tcp->m_nb_mcc_records; ++i) {
+                    opj_simple_mcc_decorrelation_data_t* l_mcc_record =
+                        &(l_tcp->m_mcc_records[i]);
+                    if (l_mcc_record->m_decorrelation_array) {
+                        l_mcc_record->m_decorrelation_array =
+                            new_mct_records +
+                            (l_mcc_record->m_decorrelation_array -
+                             l_tcp->m_mct_records);
+                    }
+                    if (l_mcc_record->m_offset_array) {
+                        l_mcc_record->m_offset_array =
+                            new_mct_records +
+                            (l_mcc_record->m_offset_array -
+                             l_tcp->m_mct_records);
+                    }
+                }
+            }
+
             l_tcp->m_mct_records = new_mct_records;
             l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records;
             memset(l_mct_data, 0, (l_tcp->m_nb_max_mct_records - l_tcp->m_nb_mct_records) *
@@ -5541,6 +5583,7 @@ static OPJ_BOOL opj_j2k_read_mct(opj_j2k_t *p_j2k,
     if (l_mct_data->m_data) {
         opj_free(l_mct_data->m_data);
         l_mct_data->m_data = 00;
+        l_mct_data->m_data_size = 0;
     }
 
     l_mct_data->m_index = l_indix;
@@ -6249,6 +6292,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 > 31) {
+            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 31)\n",
+                          i, l_comp->prec);
+            return OPJ_FALSE;
+        }
         ++l_comp;
     }
 
@@ -7711,6 +7761,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 */
@@ -7872,6 +7926,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;
@@ -8562,10 +8617,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
 
     /* Current marker is the EOC marker ?*/
     if (l_current_marker == J2K_MS_EOC) {
-        if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_EOC) {
-            p_j2k->m_current_tile_number = 0;
-            p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC;
-        }
+        p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC;
     }
 
     /* FIXME DOC ???*/
@@ -8602,14 +8654,16 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
     *p_tile_index = p_j2k->m_current_tile_number;
     *p_go_on = OPJ_TRUE;
     *p_data_size = opj_tcd_get_decoded_tile_size(p_j2k->m_tcd);
+    if (*p_data_size == UINT_MAX) {
+        return OPJ_FALSE;
+    }
     *p_tile_x0 = p_j2k->m_tcd->tcd_image->tiles->x0;
     *p_tile_y0 = p_j2k->m_tcd->tcd_image->tiles->y0;
     *p_tile_x1 = p_j2k->m_tcd->tcd_image->tiles->x1;
     *p_tile_y1 = p_j2k->m_tcd->tcd_image->tiles->y1;
     *p_nb_comps = p_j2k->m_tcd->tcd_image->tiles->numcomps;
 
-    p_j2k->m_specific_param.m_decoder.m_state |=
-        0x0080;/* FIXME J2K_DEC_STATE_DATA;*/
+    p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_DATA;
 
     return OPJ_TRUE;
 }
@@ -8630,8 +8684,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
     assert(p_j2k != 00);
     assert(p_manager != 00);
 
-    if (!(p_j2k->m_specific_param.m_decoder.m_state &
-            0x0080/*FIXME J2K_DEC_STATE_DATA*/)
+    if (!(p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_DATA)
             || (p_tile_index != p_j2k->m_current_tile_number)) {
         return OPJ_FALSE;
     }
@@ -8648,7 +8701,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
                               p_tile_index,
                               p_j2k->cstr_index, p_manager)) {
         opj_j2k_tcp_destroy(l_tcp);
-        p_j2k->m_specific_param.m_decoder.m_state |= 0x8000;/*FIXME J2K_DEC_STATE_ERR;*/
+        p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_ERR;
         opj_event_msg(p_manager, EVT_ERROR, "Failed to decode.\n");
         return OPJ_FALSE;
     }
@@ -8664,16 +8717,14 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
     opj_j2k_tcp_data_destroy(l_tcp);
 
     p_j2k->m_specific_param.m_decoder.m_can_decode = 0;
-    p_j2k->m_specific_param.m_decoder.m_state &= (~
-            (0x0080u)); /* FIXME J2K_DEC_STATE_DATA);*/
+    p_j2k->m_specific_param.m_decoder.m_state &= (~(OPJ_UINT32)J2K_STATE_DATA);
 
     if (opj_stream_get_number_byte_left(p_stream) == 0
             && p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NEOC) {
         return OPJ_TRUE;
     }
 
-    if (p_j2k->m_specific_param.m_decoder.m_state !=
-            0x0100) { /*FIXME J2K_DEC_STATE_EOC)*/
+    if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_EOC) {
         if (opj_stream_read_data(p_stream, l_data, 2, p_manager) != 2) {
             opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n");
             return OPJ_FALSE;
@@ -8683,7 +8734,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
 
         if (l_current_marker == J2K_MS_EOC) {
             p_j2k->m_current_tile_number = 0;
-            p_j2k->m_specific_param.m_decoder.m_state =  0x0100;/*FIXME J2K_DEC_STATE_EOC;*/
+            p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC;
         } else if (l_current_marker != J2K_MS_SOT) {
             if (opj_stream_get_number_byte_left(p_stream) == 0) {
                 p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC;
@@ -8918,7 +8969,10 @@ static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd, OPJ_BYTE * p_data,
             if (l_img_comp_src->sgnd) {
                 for (j = 0; j < l_height_dest; ++j) {
                     for (k = 0; k < l_width_dest; ++k) {
-                        *(l_dest_ptr++) = *(l_src_ptr++);
+                        OPJ_INT16 val;
+                        memcpy(&val, l_src_ptr, sizeof(val));
+                        l_src_ptr ++;
+                        *(l_dest_ptr++) = val;
                     }
 
                     l_dest_ptr += l_line_offset_dest;
@@ -8927,7 +8981,10 @@ static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd, OPJ_BYTE * p_data,
             } else {
                 for (j = 0; j < l_height_dest; ++j) {
                     for (k = 0; k < l_width_dest; ++k) {
-                        *(l_dest_ptr++) = (*(l_src_ptr++)) & 0xffff;
+                        OPJ_INT16 val;
+                        memcpy(&val, l_src_ptr, sizeof(val));
+                        l_src_ptr ++;
+                        *(l_dest_ptr++) = val & 0xffff;
                     }
 
                     l_dest_ptr += l_line_offset_dest;
@@ -8944,12 +9001,9 @@ static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd, OPJ_BYTE * p_data,
             l_src_ptr += l_start_offset_src;
 
             for (j = 0; j < l_height_dest; ++j) {
-                for (k = 0; k < l_width_dest; ++k) {
-                    *(l_dest_ptr++) = (*(l_src_ptr++));
-                }
-
-                l_dest_ptr += l_line_offset_dest;
-                l_src_ptr += l_line_offset_src ;
+                memcpy(l_dest_ptr, l_src_ptr, l_width_dest * sizeof(OPJ_INT32));
+                l_dest_ptr += l_width_dest + l_line_offset_dest;
+                l_src_ptr += l_width_dest + l_line_offset_src ;
             }
 
             l_src_ptr += l_end_offset_src;
@@ -8980,8 +9034,7 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
     opj_image_comp_t* l_img_comp = NULL;
 
     /* Check if we are read the main header */
-    if (p_j2k->m_specific_param.m_decoder.m_state !=
-            J2K_STATE_TPHSOT) { /* FIXME J2K_DEC_STATE_TPHSOT)*/
+    if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "Need to decode the main header before begin to decode the remaining codestream");
         return OPJ_FALSE;
@@ -9003,10 +9056,12 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
     /* Check if the positions provided by the user are correct */
 
     /* Left */
-    assert(p_start_x >= 0);
-    assert(p_start_y >= 0);
-
-    if ((OPJ_UINT32)p_start_x > l_image->x1) {
+    if (p_start_x < 0) {
+        opj_event_msg(p_manager, EVT_ERROR,
+                      "Left position of the decoded area (region_x0=%d) should be >= 0.\n",
+                      p_start_x);
+        return OPJ_FALSE;
+    } else if ((OPJ_UINT32)p_start_x > l_image->x1) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "Left position of the decoded area (region_x0=%d) is outside the image area (Xsiz=%d).\n",
                       p_start_x, l_image->x1);
@@ -9024,7 +9079,12 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
     }
 
     /* Up */
-    if ((OPJ_UINT32)p_start_y > l_image->y1) {
+    if (p_start_x < 0) {
+        opj_event_msg(p_manager, EVT_ERROR,
+                      "Up position of the decoded area (region_y0=%d) should be >= 0.\n",
+                      p_start_y);
+        return OPJ_FALSE;
+    } else if ((OPJ_UINT32)p_start_y > l_image->y1) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "Up position of the decoded area (region_y0=%d) is outside the image area (Ysiz=%d).\n",
                       p_start_y, l_image->y1);
@@ -9042,9 +9102,12 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
     }
 
     /* Right */
-    assert((OPJ_UINT32)p_end_x > 0);
-    assert((OPJ_UINT32)p_end_y > 0);
-    if ((OPJ_UINT32)p_end_x < l_image->x0) {
+    if (p_end_x <= 0) {
+        opj_event_msg(p_manager, EVT_ERROR,
+                      "Right position of the decoded area (region_x1=%d) should be > 0.\n",
+                      p_end_x);
+        return OPJ_FALSE;
+    } else if ((OPJ_UINT32)p_end_x < l_image->x0) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "Right position of the decoded area (region_x1=%d) is outside the image area (XOsiz=%d).\n",
                       p_end_x, l_image->x0);
@@ -9062,7 +9125,12 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
     }
 
     /* Bottom */
-    if ((OPJ_UINT32)p_end_y < l_image->y0) {
+    if (p_end_y <= 0) {
+        opj_event_msg(p_manager, EVT_ERROR,
+                      "Bottom position of the decoded area (region_y1=%d) should be > 0.\n",
+                      p_end_y);
+        return OPJ_FALSE;
+    } else if ((OPJ_UINT32)p_end_y < l_image->y0) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "Bottom position of the decoded area (region_y1=%d) is outside the image area (YOsiz=%d).\n",
                       p_end_y, l_image->y0);
@@ -9509,7 +9577,7 @@ static void opj_j2k_copy_tile_component_parameters(opj_j2k_t *p_j2k)
 
     l_cp = &(p_j2k->m_cp);
     l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH)
-            ? /* FIXME J2K_DEC_STATE_TPH*/
+            ?
             &l_cp->tcps[p_j2k->m_current_tile_number] :
             p_j2k->m_specific_param.m_decoder.m_default_tcp;
 
@@ -9706,7 +9774,7 @@ static OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k,
     l_cp = &(p_j2k->m_cp);
     /* come from tile part header or main header ?*/
     l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH)
-            ? /*FIXME J2K_DEC_STATE_TPH*/
+            ?
             &l_cp->tcps[p_j2k->m_current_tile_number] :
             p_j2k->m_specific_param.m_decoder.m_default_tcp;
 
@@ -10406,6 +10474,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) {
@@ -10450,6 +10520,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,