Fix compilation with AppleClang 8.1.0.8020042 (#1020)
[openjpeg.git] / src / lib / openjp2 / j2k.c
index e548fefc776568dcb242e37962f0c4a15556b98d..3e2bb749d9640dc02bfd85fe51138a6ee8fc2eae 100644 (file)
@@ -4304,6 +4304,10 @@ static OPJ_BOOL opj_j2k_read_sot(opj_j2k_t *p_j2k,
         opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n");
         return OPJ_FALSE;
     }
+#ifdef DEBUG_VERBOSE
+    fprintf(stderr, "SOT %d %d %d %d\n",
+            p_j2k->m_current_tile_number, l_tot_len, l_current_part, l_num_parts);
+#endif
 
     l_cp = &(p_j2k->m_cp);
 
@@ -4318,23 +4322,31 @@ 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;
+    if (p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec < 0 ||
+            p_j2k->m_current_tile_number == (OPJ_UINT32)
+            p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec) {
+        /* Do only this check if we decode all tile part headers, or if */
+        /* we decode one precise tile. Otherwise the m_current_tile_part_number */
+        /* might not be valid */
+        /* 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;
+
+    l_tcp->m_current_tile_part_number = (OPJ_INT32) l_current_part;
 
 #ifdef USE_JPWL
     if (l_cp->correct) {
@@ -6832,25 +6844,84 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
         parameters->tcp_rates[0] = 0;
     }
 
+    if (parameters->cp_disto_alloc) {
+        /* Emit warnings if tcp_rates are not decreasing */
+        for (i = 1; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) {
+            OPJ_FLOAT32 rate_i_corr = parameters->tcp_rates[i];
+            OPJ_FLOAT32 rate_i_m_1_corr = parameters->tcp_rates[i - 1];
+            if (rate_i_corr <= 1.0) {
+                rate_i_corr = 1.0;
+            }
+            if (rate_i_m_1_corr <= 1.0) {
+                rate_i_m_1_corr = 1.0;
+            }
+            if (rate_i_corr >= rate_i_m_1_corr) {
+                if (rate_i_corr != parameters->tcp_rates[i] &&
+                        rate_i_m_1_corr != parameters->tcp_rates[i - 1]) {
+                    opj_event_msg(p_manager, EVT_WARNING,
+                                  "tcp_rates[%d]=%f (corrected as %f) should be strictly lesser "
+                                  "than tcp_rates[%d]=%f (corrected as %f)\n",
+                                  i, parameters->tcp_rates[i], rate_i_corr,
+                                  i - 1, parameters->tcp_rates[i - 1], rate_i_m_1_corr);
+                } else if (rate_i_corr != parameters->tcp_rates[i]) {
+                    opj_event_msg(p_manager, EVT_WARNING,
+                                  "tcp_rates[%d]=%f (corrected as %f) should be strictly lesser "
+                                  "than tcp_rates[%d]=%f\n",
+                                  i, parameters->tcp_rates[i], rate_i_corr,
+                                  i - 1, parameters->tcp_rates[i - 1]);
+                } else if (rate_i_m_1_corr != parameters->tcp_rates[i - 1]) {
+                    opj_event_msg(p_manager, EVT_WARNING,
+                                  "tcp_rates[%d]=%f should be strictly lesser "
+                                  "than tcp_rates[%d]=%f (corrected as %f)\n",
+                                  i, parameters->tcp_rates[i],
+                                  i - 1, parameters->tcp_rates[i - 1], rate_i_m_1_corr);
+                } else {
+                    opj_event_msg(p_manager, EVT_WARNING,
+                                  "tcp_rates[%d]=%f should be strictly lesser "
+                                  "than tcp_rates[%d]=%f\n",
+                                  i, parameters->tcp_rates[i],
+                                  i - 1, parameters->tcp_rates[i - 1]);
+                }
+            }
+        }
+    } else if (parameters->cp_fixed_quality) {
+        /* Emit warnings if tcp_distoratio are not increasing */
+        for (i = 1; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) {
+            if (parameters->tcp_distoratio[i] < parameters->tcp_distoratio[i - 1] &&
+                    !(i == (OPJ_UINT32)parameters->tcp_numlayers - 1 &&
+                      parameters->tcp_distoratio[i] == 0)) {
+                opj_event_msg(p_manager, EVT_WARNING,
+                              "tcp_distoratio[%d]=%f should be strictly greater "
+                              "than tcp_distoratio[%d]=%f\n",
+                              i, parameters->tcp_distoratio[i], i - 1,
+                              parameters->tcp_distoratio[i - 1]);
+            }
+        }
+    }
+
     /* see if max_codestream_size does limit input rate */
     if (parameters->max_cs_size <= 0) {
         if (parameters->tcp_rates[parameters->tcp_numlayers - 1] > 0) {
             OPJ_FLOAT32 temp_size;
-            temp_size = (OPJ_FLOAT32)(image->numcomps * image->comps[0].w *
-                                      image->comps[0].h * image->comps[0].prec) /
-                        (parameters->tcp_rates[parameters->tcp_numlayers - 1] * 8 *
-                         (OPJ_FLOAT32)image->comps[0].dx * (OPJ_FLOAT32)image->comps[0].dy);
-            parameters->max_cs_size = (int) floor(temp_size);
+            temp_size = (OPJ_FLOAT32)(((double)image->numcomps * image->comps[0].w *
+                                       image->comps[0].h * image->comps[0].prec) /
+                                      ((double)parameters->tcp_rates[parameters->tcp_numlayers - 1] * 8 *
+                                       image->comps[0].dx * image->comps[0].dy));
+            if (temp_size > INT_MAX) {
+                parameters->max_cs_size = INT_MAX;
+            } else {
+                parameters->max_cs_size = (int) floor(temp_size);
+            }
         } else {
             parameters->max_cs_size = 0;
         }
     } else {
         OPJ_FLOAT32 temp_rate;
         OPJ_BOOL cap = OPJ_FALSE;
-        temp_rate = (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 *
+                                   image->comps[0].dy));
         for (i = 0; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) {
             if (parameters->tcp_rates[i] < temp_rate) {
                 parameters->tcp_rates[i] = temp_rate;
@@ -7084,6 +7155,10 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
                     tcp->rates[j] = parameters->tcp_rates[j];
                 }
             }
+            if (!cp->m_specific_param.m_enc.m_fixed_quality &&
+                    tcp->rates[j] <= 1.0) {
+                tcp->rates[j] = 0.0;    /* force lossless */
+            }
         }
 
         tcp->csty = (OPJ_UINT32)parameters->csty;
@@ -8922,30 +8997,12 @@ static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd,
 
     l_img_comp_dest = p_output_image->comps;
 
-    for (i = 0; i < l_image_src->numcomps; i++) {
+    for (i = 0; i < l_image_src->numcomps;
+            i++, ++l_img_comp_dest, ++l_img_comp_src,  ++l_tilec) {
         OPJ_INT32 res_x0, res_x1, res_y0, res_y1;
         OPJ_UINT32 src_data_stride;
         const OPJ_INT32* p_src_data;
 
-        /* Allocate output component buffer if necessary */
-        if (!l_img_comp_dest->data) {
-            OPJ_SIZE_T l_width = l_img_comp_dest->w;
-            OPJ_SIZE_T l_height = l_img_comp_dest->h;
-
-            if ((l_height == 0U) || (l_width > (SIZE_MAX / l_height)) ||
-                    l_width * l_height > SIZE_MAX / sizeof(OPJ_INT32)) {
-                /* would overflow */
-                return OPJ_FALSE;
-            }
-            l_img_comp_dest->data = (OPJ_INT32*) opj_image_data_alloc(l_width * l_height *
-                                    sizeof(OPJ_INT32));
-            if (! l_img_comp_dest->data) {
-                return OPJ_FALSE;
-            }
-            /* Do we really need this memset ? */
-            memset(l_img_comp_dest->data, 0, l_width * l_height * sizeof(OPJ_INT32));
-        }
-
         /* Copy info from decoded comp image to output image */
         l_img_comp_dest->resno_decoded = l_img_comp_src->resno_decoded;
 
@@ -9069,6 +9126,44 @@ static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd,
         l_start_offset_dest = (OPJ_SIZE_T)l_start_x_dest + (OPJ_SIZE_T)l_start_y_dest
                               * (OPJ_SIZE_T)l_img_comp_dest->w;
 
+        /* Allocate output component buffer if necessary */
+        if (l_img_comp_dest->data == NULL &&
+                l_start_offset_src == 0 && l_start_offset_dest == 0 &&
+                src_data_stride == l_img_comp_dest->w &&
+                l_width_dest == l_img_comp_dest->w &&
+                l_height_dest == l_img_comp_dest->h) {
+            /* If the final image matches the tile buffer, then borrow it */
+            /* directly to save a copy */
+            if (p_tcd->whole_tile_decoding) {
+                l_img_comp_dest->data = l_tilec->data;
+                l_tilec->data = NULL;
+            } else {
+                l_img_comp_dest->data = l_tilec->data_win;
+                l_tilec->data_win = NULL;
+            }
+            continue;
+        } else if (l_img_comp_dest->data == NULL) {
+            OPJ_SIZE_T l_width = l_img_comp_dest->w;
+            OPJ_SIZE_T l_height = l_img_comp_dest->h;
+
+            if ((l_height == 0U) || (l_width > (SIZE_MAX / l_height)) ||
+                    l_width * l_height > SIZE_MAX / sizeof(OPJ_INT32)) {
+                /* would overflow */
+                return OPJ_FALSE;
+            }
+            l_img_comp_dest->data = (OPJ_INT32*) opj_image_data_alloc(l_width * l_height *
+                                    sizeof(OPJ_INT32));
+            if (! l_img_comp_dest->data) {
+                return OPJ_FALSE;
+            }
+
+            if (l_img_comp_dest->w != l_width_dest ||
+                    l_img_comp_dest->h != l_height_dest) {
+                memset(l_img_comp_dest->data, 0,
+                       (OPJ_SIZE_T)l_img_comp_dest->w * l_img_comp_dest->h * sizeof(OPJ_INT32));
+            }
+        }
+
         /* Move the output buffer to the first place where we will write*/
         l_dest_ptr = l_img_comp_dest->data + l_start_offset_dest;
 
@@ -9083,9 +9178,7 @@ static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd,
             }
         }
 
-        ++l_img_comp_dest;
-        ++l_img_comp_src;
-        ++l_tilec;
+
     }
 
     return OPJ_TRUE;
@@ -9148,7 +9241,7 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
     OPJ_UINT32 it_comp;
 
     if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 &&
-            &p_j2k->m_cp.tcps[0].m_data != NULL) {
+            p_j2k->m_cp.tcps[0].m_data != NULL) {
         /* In the case of a single-tiled image whose codestream we have already */
         /* ingested, go on */
     }
@@ -9574,9 +9667,10 @@ static OPJ_BOOL opj_j2k_read_SPCod_SPCoc(opj_j2k_t *p_j2k,
     /* If user wants to remove more resolutions than the codestream contains, return error */
     if (l_cp->m_specific_param.m_dec.m_reduce >= l_tccp->numresolutions) {
         opj_event_msg(p_manager, EVT_ERROR,
-                      "Error decoding component %d.\nThe number of resolutions to remove is higher than the number "
-                      "of resolutions of this component\nModify the cp_reduce parameter.\n\n",
-                      compno);
+                      "Error decoding component %d.\nThe number of resolutions "
+                      "to remove (%d) is greater or equal than the number "
+                      "of resolutions of this component (%d)\nModify the cp_reduce parameter.\n\n",
+                      compno, l_cp->m_specific_param.m_dec.m_reduce, l_tccp->numresolutions);
         p_j2k->m_specific_param.m_decoder.m_state |=
             0x8000;/* FIXME J2K_DEC_STATE_ERR;*/
         return OPJ_FALSE;
@@ -10814,6 +10908,12 @@ OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k,
         return OPJ_FALSE;
     }
 
+    if (p_image->numcomps < p_j2k->m_private_image->numcomps) {
+        opj_event_msg(p_manager, EVT_ERROR,
+                      "Image has less components than codestream.\n");
+        return OPJ_FALSE;
+    }
+
     if (/*(tile_index < 0) &&*/ (tile_index >= p_j2k->m_cp.tw * p_j2k->m_cp.th)) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "Tile index provided by the user is incorrect %d (max = %d) \n", tile_index,
@@ -10844,7 +10944,7 @@ OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k,
     }
 
     l_img_comp = p_image->comps;
-    for (compno = 0; compno < p_image->numcomps; ++compno) {
+    for (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno) {
         OPJ_INT32 l_comp_x1, l_comp_y1;
 
         l_img_comp->factor = p_j2k->m_private_image->comps[compno].factor;
@@ -10866,6 +10966,18 @@ OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k,
         l_img_comp++;
     }
 
+    if (p_image->numcomps > p_j2k->m_private_image->numcomps) {
+        /* Can happen when calling repeatdly opj_get_decoded_tile() on an
+         * image with a color palette, where color palette expansion is done
+         * later in jp2.c */
+        for (compno = p_j2k->m_private_image->numcomps; compno < p_image->numcomps;
+                ++compno) {
+            opj_image_data_free(p_image->comps[compno].data);
+            p_image->comps[compno].data = NULL;
+        }
+        p_image->numcomps = p_j2k->m_private_image->numcomps;
+    }
+
     /* Destroy the previous output image*/
     if (p_j2k->m_output_image) {
         opj_image_destroy(p_j2k->m_output_image);