opj_tcd_mct_decode()/opj_mct_decode()/opj_mct_encode_real()/opj_mct_decode_real(...
[openjpeg.git] / src / lib / openjp2 / tcd.c
index c221c6ed4fc35898d9e97c8b5eb537eaaa23d5cc..deecc4dff051f607206e0ee4959a380be450c315 100644 (file)
@@ -273,28 +273,33 @@ void opj_tcd_makelayer(opj_tcd_t *tcd,
 
                         n = cblk->numpassesinlayers;
 
-                        for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) {
-                            OPJ_UINT32 dr;
-                            OPJ_FLOAT64 dd;
-                            opj_tcd_pass_t *pass = &cblk->passes[passno];
-
-                            if (n == 0) {
-                                dr = pass->rate;
-                                dd = pass->distortiondec;
-                            } else {
-                                dr = pass->rate - cblk->passes[n - 1].rate;
-                                dd = pass->distortiondec - cblk->passes[n - 1].distortiondec;
-                            }
+                        if (thresh < 0) {
+                            /* Special value to indicate to use all passes */
+                            n = cblk->totalpasses;
+                        } else {
+                            for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) {
+                                OPJ_UINT32 dr;
+                                OPJ_FLOAT64 dd;
+                                opj_tcd_pass_t *pass = &cblk->passes[passno];
+
+                                if (n == 0) {
+                                    dr = pass->rate;
+                                    dd = pass->distortiondec;
+                                } else {
+                                    dr = pass->rate - cblk->passes[n - 1].rate;
+                                    dd = pass->distortiondec - cblk->passes[n - 1].distortiondec;
+                                }
 
-                            if (!dr) {
-                                if (dd != 0) {
+                                if (!dr) {
+                                    if (dd != 0) {
+                                        n = passno + 1;
+                                    }
+                                    continue;
+                                }
+                                if (thresh - (dd / dr) <
+                                        DBL_EPSILON) { /* do not rely on float equality, check with DBL_EPSILON margin */
                                     n = passno + 1;
                                 }
-                                continue;
-                            }
-                            if (thresh - (dd / dr) <
-                                    DBL_EPSILON) { /* do not rely on float equality, check with DBL_EPSILON margin */
-                                n = passno + 1;
                             }
                         }
 
@@ -617,7 +622,8 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd,
 
             opj_t2_destroy(t2);
         } else {
-            goodthresh = min;
+            /* Special value to indicate to use all passes */
+            goodthresh = -1;
         }
 
         if (cstr_info) { /* Threshold for Marcela Index */
@@ -673,6 +679,9 @@ void opj_tcd_destroy(opj_tcd_t *tcd)
             opj_free(tcd->tcd_image);
             tcd->tcd_image = 00;
         }
+
+        opj_free(tcd->used_component);
+
         opj_free(tcd);
     }
 }
@@ -807,30 +816,32 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
         }
 
         if (isEncoder) {
+            OPJ_SIZE_T l_tile_data_size;
+
             /* compute l_data_size with overflow check */
-            l_data_size = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0);
+            OPJ_SIZE_T w = (OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0);
+            OPJ_SIZE_T h = (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0);
+
             /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */
-            if ((l_data_size > 0U) &&
-                    ((((OPJ_UINT32) - 1) / l_data_size) < (OPJ_UINT32)(l_tilec->y1 -
-                            l_tilec->y0))) {
-                opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
+            if (h > 0 && w > SIZE_MAX / h) {
+                opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n");
                 return OPJ_FALSE;
             }
-            l_data_size = l_data_size * (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0);
+            l_tile_data_size = w * h;
 
-            if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof(OPJ_UINT32)) < l_data_size) {
-                opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
+            if (SIZE_MAX / sizeof(OPJ_UINT32) < l_tile_data_size) {
+                opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n");
                 return OPJ_FALSE;
             }
-            l_data_size = l_data_size * (OPJ_UINT32)sizeof(OPJ_UINT32);
+            l_tile_data_size = l_tile_data_size * sizeof(OPJ_UINT32);
 
-            l_tilec->data_size_needed = l_data_size;
+            l_tilec->data_size_needed = l_tile_data_size;
         }
 
         l_data_size = l_tilec->numresolutions * (OPJ_UINT32)sizeof(
                           opj_tcd_resolution_t);
 
-        opj_aligned_free(l_tilec->data_win);
+        opj_image_data_free(l_tilec->data_win);
         l_tilec->data_win = NULL;
         l_tilec->win_x0 = 0;
         l_tilec->win_y0 = 0;
@@ -886,27 +897,6 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
             l_res->x1 = opj_int_ceildivpow2(l_tilec->x1, (OPJ_INT32)l_level_no);
             l_res->y1 = opj_int_ceildivpow2(l_tilec->y1, (OPJ_INT32)l_level_no);
 
-            if (!isEncoder && resno + 1 == l_tilec->minimum_num_resolutions) {
-                /* compute l_data_size with overflow check */
-                OPJ_UINT32 res_w = (OPJ_UINT32)(l_res->x1 - l_res->x0);
-                OPJ_UINT32 res_h = (OPJ_UINT32)(l_res->y1 - l_res->y0);
-
-                /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */
-                if (res_h > 0 && res_h > (((OPJ_UINT32) - 1) / res_h)) {
-                    opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
-                    return OPJ_FALSE;
-                }
-                l_data_size = res_w * res_h;
-
-                if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof(OPJ_UINT32)) < l_data_size) {
-                    opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
-                    return OPJ_FALSE;
-                }
-                l_data_size *= (OPJ_UINT32)sizeof(OPJ_UINT32);
-
-                l_tilec->data_size_needed = l_data_size;
-            }
-
             /*fprintf(stderr, "\t\t\tres_x0= %d, res_y0 =%d, res_x1=%d, res_y1=%d\n", l_res->x0, l_res->y0, l_res->x1, l_res->y1);*/
             /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */
             l_pdx = l_tccp->prcw[resno];
@@ -926,14 +916,14 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
             /*fprintf(stderr, "\t\t\tres_pw=%d, res_ph=%d\n", l_res->pw, l_res->ph );*/
 
             if ((l_res->pw != 0U) && ((((OPJ_UINT32) - 1) / l_res->pw) < l_res->ph)) {
-                opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
+                opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n");
                 return OPJ_FALSE;
             }
             l_nb_precincts = l_res->pw * l_res->ph;
 
             if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof(opj_tcd_precinct_t)) <
                     l_nb_precincts) {
-                opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
+                opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n");
                 return OPJ_FALSE;
             }
             l_nb_precinct_size = l_nb_precincts * (OPJ_UINT32)sizeof(opj_tcd_precinct_t);
@@ -1077,6 +1067,12 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
 
                     l_nb_code_blocks = l_current_precinct->cw * l_current_precinct->ch;
                     /*fprintf(stderr, "\t\t\t\t precinct_cw = %d x recinct_ch = %d\n",l_current_precinct->cw, l_current_precinct->ch);      */
+                    if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof_block) <
+                            l_nb_code_blocks) {
+                        opj_event_msg(manager, EVT_ERROR,
+                                      "Size of code block data exceeds system limits\n");
+                        return OPJ_FALSE;
+                    }
                     l_nb_code_blocks_size = l_nb_code_blocks * (OPJ_UINT32)sizeof_block;
 
                     if (!l_current_precinct->cblks.blocks && (l_nb_code_blocks > 0U)) {
@@ -1281,7 +1277,7 @@ static OPJ_BOOL opj_tcd_code_block_dec_allocate(opj_tcd_cblk_dec_t *
         OPJ_UINT32 l_numchunksalloc = p_code_block->numchunksalloc;
         OPJ_UINT32 i;
 
-        opj_free(p_code_block->decoded_data);
+        opj_aligned_free(p_code_block->decoded_data);
         p_code_block->decoded_data = 00;
 
         memset(p_code_block, 0, sizeof(opj_tcd_cblk_dec_t));
@@ -1312,6 +1308,7 @@ OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd,
     l_img_comp = p_tcd->image->comps;
 
     for (i = 0; i < p_tcd->image->numcomps; ++i) {
+        OPJ_UINT32 w, h;
         l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/
         l_remaining = l_img_comp->prec & 7;  /* (%8) */
 
@@ -1325,12 +1322,16 @@ OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd,
 
         l_res = l_tile_comp->resolutions + l_tile_comp->minimum_num_resolutions - 1;
         if (take_into_account_partial_decoding && !p_tcd->whole_tile_decoding) {
-            l_temp = (l_res->win_x1 - l_res->win_x0) *
-                     (l_res->win_y1 - l_res->win_y0);
+            w = l_res->win_x1 - l_res->win_x0;
+            h = l_res->win_y1 - l_res->win_y0;
         } else {
-            l_temp = (OPJ_UINT32)((l_res->x1 - l_res->x0) * (l_res->y1 -
-                                  l_res->y0)); /* x1*y1 can't overflow */
+            w = (OPJ_UINT32)(l_res->x1 - l_res->x0);
+            h = (OPJ_UINT32)(l_res->y1 - l_res->y0);
+        }
+        if (h > 0 && UINT_MAX / w < h) {
+            return UINT_MAX;
         }
+        l_temp = w * h;
         if (l_size_comp && UINT_MAX / l_size_comp < l_temp) {
             return UINT_MAX;
         }
@@ -1380,7 +1381,8 @@ OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd,
                 p_cstr_info->tile[p_tile_no].pdy[i] = (int)l_tccp->prch[i];
             }
             p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t*) opj_calloc((
-                    size_t)p_cstr_info->numcomps * (size_t)p_cstr_info->numlayers * l_num_packs,
+                    OPJ_SIZE_T)p_cstr_info->numcomps * (OPJ_SIZE_T)p_cstr_info->numlayers *
+                                                  l_num_packs,
                                                   sizeof(opj_packet_info_t));
             if (!p_cstr_info->tile[p_tile_no].packet) {
                 /* FIXME event manager error callback */
@@ -1446,6 +1448,8 @@ OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd,
                              OPJ_UINT32 win_y0,
                              OPJ_UINT32 win_x1,
                              OPJ_UINT32 win_y1,
+                             OPJ_UINT32 numcomps_to_decode,
+                             const OPJ_UINT32 *comps_indices,
                              OPJ_BYTE *p_src,
                              OPJ_UINT32 p_max_length,
                              OPJ_UINT32 p_tile_no,
@@ -1464,7 +1468,27 @@ OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd,
     p_tcd->win_y1 = win_y1;
     p_tcd->whole_tile_decoding = OPJ_TRUE;
 
+    opj_free(p_tcd->used_component);
+    p_tcd->used_component = NULL;
+
+    if (numcomps_to_decode) {
+        OPJ_BOOL* used_component = (OPJ_BOOL*) opj_calloc(sizeof(OPJ_BOOL),
+                                   p_tcd->image->numcomps);
+        if (used_component == NULL) {
+            return OPJ_FALSE;
+        }
+        for (compno = 0; compno < numcomps_to_decode; compno++) {
+            used_component[ comps_indices[compno] ] = OPJ_TRUE;
+        }
+
+        p_tcd->used_component = used_component;
+    }
+
     for (compno = 0; compno < p_tcd->image->numcomps; compno++) {
+        if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) {
+            continue;
+        }
+
         if (!opj_tcd_is_whole_tilecomp_decoding(p_tcd, compno)) {
             p_tcd->whole_tile_decoding = OPJ_FALSE;
             break;
@@ -1473,8 +1497,39 @@ OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd,
 
     if (p_tcd->whole_tile_decoding) {
         for (compno = 0; compno < p_tcd->image->numcomps; compno++) {
-            if (!opj_alloc_tile_component_data(&(p_tcd->tcd_image->tiles->comps[compno]))) {
-                opj_event_msg(p_manager, EVT_ERROR, "Not enough memory for tile data\n");
+            opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]);
+            opj_tcd_resolution_t *l_res = &
+                                          (tilec->resolutions[tilec->minimum_num_resolutions - 1]);
+            OPJ_SIZE_T l_data_size;
+
+            /* compute l_data_size with overflow check */
+            OPJ_SIZE_T res_w = (OPJ_SIZE_T)(l_res->x1 - l_res->x0);
+            OPJ_SIZE_T res_h = (OPJ_SIZE_T)(l_res->y1 - l_res->y0);
+
+            if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) {
+                continue;
+            }
+
+            /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */
+            if (res_h > 0 && res_w > SIZE_MAX / res_h) {
+                opj_event_msg(p_manager, EVT_ERROR,
+                              "Size of tile data exceeds system limits\n");
+                return OPJ_FALSE;
+            }
+            l_data_size = res_w * res_h;
+
+            if (SIZE_MAX / sizeof(OPJ_UINT32) < l_data_size) {
+                opj_event_msg(p_manager, EVT_ERROR,
+                              "Size of tile data exceeds system limits\n");
+                return OPJ_FALSE;
+            }
+            l_data_size *= sizeof(OPJ_UINT32);
+
+            tilec->data_size_needed = l_data_size;
+
+            if (!opj_alloc_tile_component_data(tilec)) {
+                opj_event_msg(p_manager, EVT_ERROR,
+                              "Size of tile data exceeds system limits\n");
                 return OPJ_FALSE;
             }
         }
@@ -1486,6 +1541,11 @@ OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd,
             OPJ_UINT32 resno;
             opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]);
             opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]);
+
+            if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) {
+                continue;
+            }
+
             /* Compute the intersection of the area of interest, expressed in tile coordinates */
             /* with the tile coordinates */
             tilec->win_x0 = opj_uint_max(
@@ -1500,6 +1560,15 @@ OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd,
             tilec->win_y1 = opj_uint_min(
                                 (OPJ_UINT32)tilec->y1,
                                 opj_uint_ceildiv(p_tcd->win_y1, image_comp->dy));
+            if (tilec->win_x1 < tilec->win_x0 ||
+                    tilec->win_y1 < tilec->win_y0) {
+                /* We should not normally go there. The circumstance is when */
+                /* the tile coordinates do not intersect the area of interest */
+                /* Upper level logic should not even try to decode that tile */
+                opj_event_msg(p_manager, EVT_ERROR,
+                              "Invalid tilec->win_xxx values\n");
+                return OPJ_FALSE;
+            }
 
             for (resno = 0; resno < tilec->numresolutions; ++resno) {
                 opj_tcd_resolution_t *res = tilec->resolutions + resno;
@@ -1564,28 +1633,35 @@ OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd,
             opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]);
             opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]);
             opj_tcd_resolution_t *res = tilec->resolutions + image_comp->resno_decoded;
-            OPJ_UINT32 w = res->win_x1 - res->win_x0;
-            OPJ_UINT32 h = res->win_y1 - res->win_y0;
-            OPJ_UINT32 l_data_size;
+            OPJ_SIZE_T w = res->win_x1 - res->win_x0;
+            OPJ_SIZE_T h = res->win_y1 - res->win_y0;
+            OPJ_SIZE_T l_data_size;
 
-            opj_aligned_free(tilec->data_win);
+            opj_image_data_free(tilec->data_win);
             tilec->data_win = NULL;
 
+            if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) {
+                continue;
+            }
+
             if (w > 0 && h > 0) {
-                if (w > ((OPJ_UINT32) - 1) / h) {
-                    opj_event_msg(p_manager, EVT_ERROR, "Not enough memory for tile data\n");
+                if (w > SIZE_MAX / h) {
+                    opj_event_msg(p_manager, EVT_ERROR,
+                                  "Size of tile data exceeds system limits\n");
                     return OPJ_FALSE;
                 }
                 l_data_size = w * h;
-                if (l_data_size > ((OPJ_UINT32) - 1) / sizeof(OPJ_INT32)) {
-                    opj_event_msg(p_manager, EVT_ERROR, "Not enough memory for tile data\n");
+                if (l_data_size > SIZE_MAX / sizeof(OPJ_INT32)) {
+                    opj_event_msg(p_manager, EVT_ERROR,
+                                  "Size of tile data exceeds system limits\n");
                     return OPJ_FALSE;
                 }
-                l_data_size *= (OPJ_UINT32)sizeof(OPJ_INT32);
+                l_data_size *= sizeof(OPJ_INT32);
 
-                tilec->data_win = opj_aligned_malloc(l_data_size);
+                tilec->data_win = (OPJ_INT32*) opj_image_data_alloc(l_data_size);
                 if (tilec->data_win == NULL) {
-                    opj_event_msg(p_manager, EVT_ERROR, "Not enough memory for tile data\n");
+                    opj_event_msg(p_manager, EVT_ERROR,
+                                  "Size of tile data exceeds system limits\n");
                     return OPJ_FALSE;
                 }
             }
@@ -1780,14 +1856,16 @@ static void opj_tcd_free_tile(opj_tcd_t *p_tcd)
         l_res = l_tile_comp->resolutions;
         if (l_res) {
 
-            l_nb_resolutions = l_tile_comp->resolutions_size / sizeof(opj_tcd_resolution_t);
+            l_nb_resolutions = l_tile_comp->resolutions_size / (OPJ_UINT32)sizeof(
+                                   opj_tcd_resolution_t);
             for (resno = 0; resno < l_nb_resolutions; ++resno) {
                 l_band = l_res->bands;
                 for (bandno = 0; bandno < 3; ++bandno) {
                     l_precinct = l_band->precincts;
                     if (l_precinct) {
 
-                        l_nb_precincts = l_band->precincts_data_size / sizeof(opj_tcd_precinct_t);
+                        l_nb_precincts = l_band->precincts_data_size / (OPJ_UINT32)sizeof(
+                                             opj_tcd_precinct_t);
                         for (precno = 0; precno < l_nb_precincts; ++precno) {
                             opj_tgt_destroy(l_precinct->incltree);
                             l_precinct->incltree = 00;
@@ -1817,7 +1895,7 @@ static void opj_tcd_free_tile(opj_tcd_t *p_tcd)
             l_tile_comp->data_size_needed = 0;
         }
 
-        opj_aligned_free(l_tile_comp->data_win);
+        opj_image_data_free(l_tile_comp->data_win);
 
         ++l_tile_comp;
     }
@@ -1882,14 +1960,17 @@ static OPJ_BOOL opj_tcd_t1_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager)
         check_pterm = OPJ_TRUE;
     }
 
-    for (compno = 0; compno < l_tile->numcomps; ++compno) {
+    for (compno = 0; compno < l_tile->numcomps;
+            ++compno, ++l_tile_comp, ++l_tccp) {
+        if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) {
+            continue;
+        }
+
         opj_t1_decode_cblks(p_tcd, &ret, l_tile_comp, l_tccp,
                             p_manager, p_manager_mutex, check_pterm);
         if (!ret) {
             break;
         }
-        ++l_tile_comp;
-        ++l_tccp;
     }
 
     opj_thread_pool_wait_completion(p_tcd->thread_pool, 0);
@@ -1908,7 +1989,11 @@ static OPJ_BOOL opj_tcd_dwt_decode(opj_tcd_t *p_tcd)
     opj_tccp_t * l_tccp = p_tcd->tcp->tccps;
     opj_image_comp_t * l_img_comp = p_tcd->image->comps;
 
-    for (compno = 0; compno < l_tile->numcomps; compno++) {
+    for (compno = 0; compno < l_tile->numcomps;
+            compno++, ++l_tile_comp, ++l_img_comp, ++l_tccp) {
+        if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) {
+            continue;
+        }
 
         if (l_tccp->qmfbid == 1) {
             if (! opj_dwt_decode(p_tcd, l_tile_comp,
@@ -1922,9 +2007,6 @@ static OPJ_BOOL opj_tcd_dwt_decode(opj_tcd_t *p_tcd)
             }
         }
 
-        ++l_tile_comp;
-        ++l_img_comp;
-        ++l_tccp;
     }
 
     return OPJ_TRUE;
@@ -1935,50 +2017,80 @@ static OPJ_BOOL opj_tcd_mct_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager)
     opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles;
     opj_tcp_t * l_tcp = p_tcd->tcp;
     opj_tcd_tilecomp_t * l_tile_comp = l_tile->comps;
-    OPJ_UINT32 l_samples, i;
+    OPJ_SIZE_T l_samples;
+    OPJ_UINT32 i;
 
-    if (! l_tcp->mct) {
+    if (l_tcp->mct == 0 || p_tcd->used_component != NULL) {
         return OPJ_TRUE;
     }
 
     if (p_tcd->whole_tile_decoding) {
+        opj_tcd_resolution_t* res_comp0 = l_tile->comps[0].resolutions +
+                                          l_tile_comp->minimum_num_resolutions - 1;
+
         /* A bit inefficient: we process more data than needed if */
         /* resno_decoded < l_tile_comp->minimum_num_resolutions-1, */
         /* but we would need to take into account a stride then */
-        l_samples = (OPJ_UINT32)((
-                                     l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].x1 -
-                                     l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].x0) *
-                                 (l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].y1 -
-                                  l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].y0));
+        l_samples = (OPJ_SIZE_T)(res_comp0->x1 - res_comp0->x0) *
+                    (OPJ_SIZE_T)(res_comp0->y1 - res_comp0->y0);
+        if (l_tile->numcomps >= 3) {
+            if (l_tile_comp->minimum_num_resolutions !=
+                    l_tile->comps[1].minimum_num_resolutions ||
+                    l_tile_comp->minimum_num_resolutions !=
+                    l_tile->comps[2].minimum_num_resolutions) {
+                opj_event_msg(p_manager, EVT_ERROR,
+                              "Tiles don't all have the same dimension. Skip the MCT step.\n");
+                return OPJ_FALSE;
+            }
+        }
+        if (l_tile->numcomps >= 3) {
+            opj_tcd_resolution_t* res_comp1 = l_tile->comps[1].resolutions +
+                                              l_tile_comp->minimum_num_resolutions - 1;
+            opj_tcd_resolution_t* res_comp2 = l_tile->comps[2].resolutions +
+                                              l_tile_comp->minimum_num_resolutions - 1;
+            /* testcase 1336.pdf.asan.47.376 */
+            if (p_tcd->image->comps[0].resno_decoded !=
+                    p_tcd->image->comps[1].resno_decoded ||
+                    p_tcd->image->comps[0].resno_decoded !=
+                    p_tcd->image->comps[2].resno_decoded ||
+                    (OPJ_SIZE_T)(res_comp1->x1 - res_comp1->x0) *
+                    (OPJ_SIZE_T)(res_comp1->y1 - res_comp1->y0) != l_samples ||
+                    (OPJ_SIZE_T)(res_comp2->x1 - res_comp2->x0) *
+                    (OPJ_SIZE_T)(res_comp2->y1 - res_comp2->y0) != l_samples) {
+                opj_event_msg(p_manager, EVT_ERROR,
+                              "Tiles don't all have the same dimension. Skip the MCT step.\n");
+                return OPJ_FALSE;
+            }
+        }
     } else {
-        opj_tcd_resolution_t* l_res;
-        l_res = l_tile_comp->resolutions + p_tcd->image->comps[0].resno_decoded;
-        l_samples = (l_res->win_x1 - l_res->win_x0) *
-                    (l_res->win_y1 - l_res->win_y0);
+        opj_tcd_resolution_t* res_comp0 = l_tile->comps[0].resolutions +
+                                          p_tcd->image->comps[0].resno_decoded;
+
+        l_samples = (OPJ_SIZE_T)(res_comp0->win_x1 - res_comp0->win_x0) *
+                    (OPJ_SIZE_T)(res_comp0->win_y1 - res_comp0->win_y0);
+        if (l_tile->numcomps >= 3) {
+            opj_tcd_resolution_t* res_comp1 = l_tile->comps[1].resolutions +
+                                              p_tcd->image->comps[1].resno_decoded;
+            opj_tcd_resolution_t* res_comp2 = l_tile->comps[2].resolutions +
+                                              p_tcd->image->comps[2].resno_decoded;
+            /* testcase 1336.pdf.asan.47.376 */
+            if (p_tcd->image->comps[0].resno_decoded !=
+                    p_tcd->image->comps[1].resno_decoded ||
+                    p_tcd->image->comps[0].resno_decoded !=
+                    p_tcd->image->comps[2].resno_decoded ||
+                    (OPJ_SIZE_T)(res_comp1->win_x1 - res_comp1->win_x0) *
+                    (OPJ_SIZE_T)(res_comp1->win_y1 - res_comp1->win_y0) != l_samples ||
+                    (OPJ_SIZE_T)(res_comp2->win_x1 - res_comp2->win_x0) *
+                    (OPJ_SIZE_T)(res_comp2->win_y1 - res_comp2->win_y0) != l_samples) {
+                opj_event_msg(p_manager, EVT_ERROR,
+                              "Tiles don't all have the same dimension. Skip the MCT step.\n");
+                return OPJ_FALSE;
+            }
+        }
     }
 
     if (l_tile->numcomps >= 3) {
-        opj_tcd_resolution_t* res_comp0 = l_tile->comps[0].resolutions +
-                                          p_tcd->image->comps[0].resno_decoded;
-        opj_tcd_resolution_t* res_comp1 = l_tile->comps[1].resolutions +
-                                          p_tcd->image->comps[1].resno_decoded;
-        opj_tcd_resolution_t* res_comp2 = l_tile->comps[2].resolutions +
-                                          p_tcd->image->comps[2].resno_decoded;
-        OPJ_INT32 l_res_samples = (OPJ_INT32)(res_comp0->x1 - res_comp0->x0) *
-                                  (res_comp0->y1 - res_comp0->y0);
-        /* testcase 1336.pdf.asan.47.376 */
-        if (p_tcd->image->comps[0].resno_decoded !=
-                p_tcd->image->comps[1].resno_decoded ||
-                p_tcd->image->comps[0].resno_decoded !=
-                p_tcd->image->comps[2].resno_decoded ||
-                (res_comp1->x1 - res_comp1->x0) * (res_comp1->y1 -
-                        res_comp1->y0) != l_res_samples ||
-                (res_comp2->x1 - res_comp2->x0) * (res_comp2->y1 -
-                        res_comp2->y0) != l_res_samples) {
-            opj_event_msg(p_manager, EVT_ERROR,
-                          "Tiles don't all have the same dimension. Skip the MCT step.\n");
-            return OPJ_FALSE;
-        } else if (l_tcp->mct == 2) {
+        if (l_tcp->mct == 2) {
             OPJ_BYTE ** l_data;
 
             if (! l_tcp->m_mct_decoding_matrix) {
@@ -2069,7 +2181,13 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd)
     l_tccp = p_tcd->tcp->tccps;
     l_img_comp = p_tcd->image->comps;
 
-    for (compno = 0; compno < l_tile->numcomps; compno++) {
+    for (compno = 0; compno < l_tile->numcomps;
+            compno++, ++l_img_comp, ++l_tccp, ++l_tile_comp) {
+
+        if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) {
+            continue;
+        }
+
         l_res = l_tile_comp->resolutions + l_img_comp->resno_decoded;
 
         if (!p_tcd->whole_tile_decoding) {
@@ -2102,6 +2220,7 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd)
         if (l_tccp->qmfbid == 1) {
             for (j = 0; j < l_height; ++j) {
                 for (i = 0; i < l_width; ++i) {
+                    /* TODO: do addition on int64 ? */
                     *l_current_ptr = opj_int_clamp(*l_current_ptr + l_tccp->m_dc_level_shift, l_min,
                                                    l_max);
                     ++l_current_ptr;
@@ -2112,13 +2231,14 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd)
             for (j = 0; j < l_height; ++j) {
                 for (i = 0; i < l_width; ++i) {
                     OPJ_FLOAT32 l_value = *((OPJ_FLOAT32 *) l_current_ptr);
-                    OPJ_INT32 l_value_int = (OPJ_INT32)opj_lrintf(l_value);
-                    if (l_value > INT_MAX ||
-                            (l_value_int > 0 && l_tccp->m_dc_level_shift > 0 &&
-                             l_value_int > INT_MAX - l_tccp->m_dc_level_shift)) {
+                    if (l_value > INT_MAX) {
                         *l_current_ptr = l_max;
+                    } else if (l_value < INT_MIN) {
+                        *l_current_ptr = l_min;
                     } else {
-                        *l_current_ptr = opj_int_clamp(
+                        /* Do addition on int64 to avoid overflows */
+                        OPJ_INT64 l_value_int = (OPJ_INT64)opj_lrintf(l_value);
+                        *l_current_ptr = (OPJ_INT32)opj_int64_clamp(
                                              l_value_int + l_tccp->m_dc_level_shift, l_min, l_max);
                     }
                     ++l_current_ptr;
@@ -2126,10 +2246,6 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd)
                 l_current_ptr += l_stride;
             }
         }
-
-        ++l_img_comp;
-        ++l_tccp;
-        ++l_tile_comp;
     }
 
     return OPJ_TRUE;
@@ -2152,7 +2268,8 @@ static void opj_tcd_code_block_dec_deallocate(opj_tcd_precinct_t * p_precinct)
                         l_code_block->numbps, l_code_block->numlenbits, l_code_block->len, l_code_block->numnewpasses, l_code_block->real_num_segs, l_code_block->m_current_max_segs );*/
 
 
-        l_nb_code_blocks = p_precinct->block_size / sizeof(opj_tcd_cblk_dec_t);
+        l_nb_code_blocks = p_precinct->block_size / (OPJ_UINT32)sizeof(
+                               opj_tcd_cblk_dec_t);
         /*fprintf(stderr,"nb_code_blocks =%d\t}\n", l_nb_code_blocks);*/
 
         for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) {
@@ -2167,7 +2284,7 @@ static void opj_tcd_code_block_dec_deallocate(opj_tcd_precinct_t * p_precinct)
                 l_code_block->chunks = 00;
             }
 
-            opj_free(l_code_block->decoded_data);
+            opj_aligned_free(l_code_block->decoded_data);
             l_code_block->decoded_data = NULL;
 
             ++l_code_block;
@@ -2187,7 +2304,8 @@ static void opj_tcd_code_block_enc_deallocate(opj_tcd_precinct_t * p_precinct)
 
     opj_tcd_cblk_enc_t * l_code_block = p_precinct->cblks.enc;
     if (l_code_block) {
-        l_nb_code_blocks = p_precinct->block_size / sizeof(opj_tcd_cblk_enc_t);
+        l_nb_code_blocks = p_precinct->block_size / (OPJ_UINT32)sizeof(
+                               opj_tcd_cblk_enc_t);
 
         for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno)  {
             if (l_code_block->data) {
@@ -2215,9 +2333,10 @@ static void opj_tcd_code_block_enc_deallocate(opj_tcd_precinct_t * p_precinct)
     }
 }
 
-OPJ_UINT32 opj_tcd_get_encoded_tile_size(opj_tcd_t *p_tcd)
+OPJ_SIZE_T opj_tcd_get_encoded_tile_size(opj_tcd_t *p_tcd)
 {
-    OPJ_UINT32 i, l_data_size = 0;
+    OPJ_UINT32 i;
+    OPJ_SIZE_T l_data_size = 0;
     opj_image_comp_t * l_img_comp = 00;
     opj_tcd_tilecomp_t * l_tilec = 00;
     OPJ_UINT32 l_size_comp, l_remaining;
@@ -2236,8 +2355,8 @@ OPJ_UINT32 opj_tcd_get_encoded_tile_size(opj_tcd_t *p_tcd)
             l_size_comp = 4;
         }
 
-        l_data_size += l_size_comp * (OPJ_UINT32)((l_tilec->x1 - l_tilec->x0) *
-                       (l_tilec->y1 - l_tilec->y0));
+        l_data_size += l_size_comp * ((OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0) *
+                                      (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0));
         ++l_img_comp;
         ++l_tilec;
     }
@@ -2252,7 +2371,7 @@ static OPJ_BOOL opj_tcd_dc_level_shift_encode(opj_tcd_t *p_tcd)
     opj_tccp_t * l_tccp = 00;
     opj_image_comp_t * l_img_comp = 00;
     opj_tcd_tile_t * l_tile;
-    OPJ_UINT32 l_nb_elem, i;
+    OPJ_SIZE_T l_nb_elem, i;
     OPJ_INT32 * l_current_ptr;
 
     l_tile = p_tcd->tcd_image->tiles;
@@ -2262,8 +2381,8 @@ static OPJ_BOOL opj_tcd_dc_level_shift_encode(opj_tcd_t *p_tcd)
 
     for (compno = 0; compno < l_tile->numcomps; compno++) {
         l_current_ptr = l_tile_comp->data;
-        l_nb_elem = (OPJ_UINT32)((l_tile_comp->x1 - l_tile_comp->x0) *
-                                 (l_tile_comp->y1 - l_tile_comp->y0));
+        l_nb_elem = (OPJ_SIZE_T)(l_tile_comp->x1 - l_tile_comp->x0) *
+                    (OPJ_SIZE_T)(l_tile_comp->y1 - l_tile_comp->y0);
 
         if (l_tccp->qmfbid == 1) {
             for (i = 0; i < l_nb_elem; ++i) {
@@ -2289,8 +2408,8 @@ static OPJ_BOOL opj_tcd_mct_encode(opj_tcd_t *p_tcd)
 {
     opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles;
     opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps;
-    OPJ_UINT32 samples = (OPJ_UINT32)((l_tile_comp->x1 - l_tile_comp->x0) *
-                                      (l_tile_comp->y1 - l_tile_comp->y0));
+    OPJ_SIZE_T samples = (OPJ_SIZE_T)(l_tile_comp->x1 - l_tile_comp->x0) *
+                         (OPJ_SIZE_T)(l_tile_comp->y1 - l_tile_comp->y0);
     OPJ_UINT32 i;
     OPJ_BYTE ** l_data = 00;
     opj_tcp_t * l_tcp = p_tcd->tcp;
@@ -2472,13 +2591,15 @@ static OPJ_BOOL opj_tcd_rate_allocate_encode(opj_tcd_t *p_tcd,
 
 OPJ_BOOL opj_tcd_copy_tile_data(opj_tcd_t *p_tcd,
                                 OPJ_BYTE * p_src,
-                                OPJ_UINT32 p_src_length)
+                                OPJ_SIZE_T p_src_length)
 {
-    OPJ_UINT32 i, j, l_data_size = 0;
+    OPJ_UINT32 i;
+    OPJ_SIZE_T j;
+    OPJ_SIZE_T l_data_size = 0;
     opj_image_comp_t * l_img_comp = 00;
     opj_tcd_tilecomp_t * l_tilec = 00;
     OPJ_UINT32 l_size_comp, l_remaining;
-    OPJ_UINT32 l_nb_elem;
+    OPJ_SIZE_T l_nb_elem;
 
     l_data_size = opj_tcd_get_encoded_tile_size(p_tcd);
     if (l_data_size != p_src_length) {
@@ -2490,8 +2611,8 @@ OPJ_BOOL opj_tcd_copy_tile_data(opj_tcd_t *p_tcd,
     for (i = 0; i < p_tcd->image->numcomps; ++i) {
         l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/
         l_remaining = l_img_comp->prec & 7;  /* (%8) */
-        l_nb_elem = (OPJ_UINT32)((l_tilec->x1 - l_tilec->x0) * (l_tilec->y1 -
-                                 l_tilec->y0));
+        l_nb_elem = (OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0) *
+                    (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0);
 
         if (l_remaining) {
             ++l_size_comp;