Add opj_codec_set_threads() in public API and propagate resulting thread pool to...
[openjpeg.git] / src / lib / openjp2 / j2k.c
index 301bdfe62b063811ce24c91e06a309e392558808..68b2f82e540408623217c942e953d1f3b1320d09 100644 (file)
@@ -2063,17 +2063,17 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
         /* testcase 4035.pdf.SIGSEGV.d8b.3375 */
         /* testcase issue427-null-image-size.jp2 */
         if ((l_image->x0 >= l_image->x1) || (l_image->y0 >= l_image->y1)) {
-                opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: negative or zero image size (%d x %d)\n", l_image->x1 - l_image->x0, l_image->y1 - l_image->y0);
+                opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: negative or zero image size (%" PRId64 " x %" PRId64 ")\n", (OPJ_INT64)l_image->x1 - l_image->x0, (OPJ_INT64)l_image->y1 - l_image->y0);
                 return OPJ_FALSE;
         }
         /* testcase 2539.pdf.SIGFPE.706.1712 (also 3622.pdf.SIGFPE.706.2916 and 4008.pdf.SIGFPE.706.3345 and maybe more) */
-        if (!(l_cp->tdx * l_cp->tdy)) {
+        if ((l_cp->tdx == 0U) || (l_cp->tdy == 0U)) {
                 opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: invalid tile size (tdx: %d, tdy: %d)\n", l_cp->tdx, l_cp->tdy);
                 return OPJ_FALSE;
         }
 
         /* testcase 1610.pdf.SIGSEGV.59c.681 */
-        if (((OPJ_UINT64)l_image->x1) * ((OPJ_UINT64)l_image->y1) != (l_image->x1 * l_image->y1)) {
+        if ((0xFFFFFFFFU / l_image->x1) < l_image->y1) {
                 opj_event_msg(p_manager, EVT_ERROR, "Prevent buffer overflow (x1: %d, y1: %d)\n", l_image->x1, l_image->y1);
                 return OPJ_FALSE;
         }
@@ -2094,7 +2094,7 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
                         opj_event_msg(p_manager, EVT_ERROR,
                                 "JPWL: bad image size (%d x %d)\n",
                                 l_image->x1, l_image->y1);
-                        if (!JPWL_ASSUME || JPWL_ASSUME) {
+                        if (!JPWL_ASSUME) {
                                 opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n");
                                 return OPJ_FALSE;
                         }
@@ -2154,10 +2154,16 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
                 if( l_img_comp->dx < 1 || l_img_comp->dx > 255 ||
                     l_img_comp->dy < 1 || l_img_comp->dy > 255 ) {
                     opj_event_msg(p_manager, EVT_ERROR,
-                                  "Invalid values for comp = %d : dx=%u dy=%u\n (should be between 1 and 255 according the JPEG2000 norm)",
+                                  "Invalid values for comp = %d : dx=%u dy=%u (should be between 1 and 255 according to the JPEG2000 norm)\n",
                                   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 ? */
+                    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",
+                                  i, l_img_comp->prec);
+                    return OPJ_FALSE;
+                }
 
 #ifdef USE_JPWL
                 if (l_cp->correct) {
@@ -2270,7 +2276,7 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
                 if (!l_cp->tcps) {
                         opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
                                 "JPWL: could not alloc tcps field of cp\n");
-                        if (!JPWL_ASSUME || JPWL_ASSUME) {
+                        if (!JPWL_ASSUME) {
                                 opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n");
                                 return OPJ_FALSE;
                         }
@@ -2436,22 +2442,22 @@ static OPJ_BOOL opj_j2k_write_cod(     opj_j2k_t *p_j2k,
 
         l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
 
-        opj_write_bytes(l_current_data,J2K_MS_COD,2);           /* COD */
+        opj_write_bytes(l_current_data,J2K_MS_COD,2);             /* COD */
         l_current_data += 2;
 
-        opj_write_bytes(l_current_data,l_code_size-2,2);        /* L_COD */
+        opj_write_bytes(l_current_data,l_code_size-2,2);          /* L_COD */
         l_current_data += 2;
 
-        opj_write_bytes(l_current_data,l_tcp->csty,1);          /* Scod */
+        opj_write_bytes(l_current_data,l_tcp->csty,1);            /* Scod */
         ++l_current_data;
 
-        opj_write_bytes(l_current_data,l_tcp->prg,1);           /* SGcod (A) */
+        opj_write_bytes(l_current_data,(OPJ_UINT32)l_tcp->prg,1); /* SGcod (A) */
         ++l_current_data;
 
-        opj_write_bytes(l_current_data,l_tcp->numlayers,2);     /* SGcod (B) */
+        opj_write_bytes(l_current_data,l_tcp->numlayers,2);       /* SGcod (B) */
         l_current_data+=2;
 
-        opj_write_bytes(l_current_data,l_tcp->mct,1);           /* SGcod (C) */
+        opj_write_bytes(l_current_data,l_tcp->mct,1);             /* SGcod (C) */
         ++l_current_data;
 
         l_remaining_size -= 9;
@@ -2578,6 +2584,9 @@ static OPJ_BOOL opj_j2k_read_cod (  opj_j2k_t *p_j2k,
                 p_j2k->cstr_info->prog = l_tcp->prg;
                 p_j2k->cstr_info->numlayers = l_tcp->numlayers;
                 p_j2k->cstr_info->numdecompos = (OPJ_INT32*) opj_malloc(l_image->numcomps * sizeof(OPJ_UINT32));
+                               if(!p_j2k->cstr_info->numdecompos){
+                                       return OPJ_FALSE;
+                               }
                 for     (i = 0; i < l_image->numcomps; ++i) {
                         p_j2k->cstr_info->numdecompos[i] = l_tcp->tccps[i].numresolutions - 1;
                 }
@@ -3165,7 +3174,7 @@ static void opj_j2k_write_poc_in_memory(   opj_j2k_t *p_j2k,
                 opj_write_bytes(l_current_data,l_current_poc->compno1,l_poc_room);              /* CEpoc_i */
                 l_current_data+=l_poc_room;
 
-                opj_write_bytes(l_current_data,l_current_poc->prg,1);                                   /* Ppoc_i */
+                opj_write_bytes(l_current_data, (OPJ_UINT32)l_current_poc->prg,1);    /* Ppoc_i */
                 ++l_current_data;
 
                 /* change the value of the max layer according to the actual number of layers in the file, components and resolutions*/
@@ -3615,7 +3624,7 @@ static OPJ_BOOL opj_j2k_read_ppm (
                return OPJ_FALSE;
        }
        
-       l_cp->ppm_markers[l_Z_ppm].m_data = opj_malloc(p_header_size);
+       l_cp->ppm_markers[l_Z_ppm].m_data = (OPJ_BYTE *) opj_malloc(p_header_size);
        if (l_cp->ppm_markers[l_Z_ppm].m_data == NULL) {
                /* clean up to be done on l_cp destruction */
                opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n");
@@ -3837,7 +3846,7 @@ static OPJ_BOOL opj_j2k_read_ppt (  opj_j2k_t *p_j2k,
                return OPJ_FALSE;
        }
        
-       l_tcp->ppt_markers[l_Z_ppt].m_data = opj_malloc(p_header_size);
+       l_tcp->ppt_markers[l_Z_ppt].m_data = (OPJ_BYTE *) opj_malloc(p_header_size);
        if (l_tcp->ppt_markers[l_Z_ppt].m_data == NULL) {
                /* clean up to be done on l_tcp destruction */
                opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n");
@@ -4404,7 +4413,7 @@ static OPJ_BOOL opj_j2k_read_sod (opj_j2k_t *p_j2k,
             }
             if (! *l_current_data) {
                 /* LH: oddly enough, in this path, l_tile_len!=0.
-                 * TODO: If this was consistant, we could simplify the code to only use realloc(), as realloc(0,...) default to malloc(0,...).
+                 * TODO: If this was consistent, we could simplify the code to only use realloc(), as realloc(0,...) default to malloc(0,...).
                  */
                 *l_current_data = (OPJ_BYTE*) opj_malloc(p_j2k->m_specific_param.m_decoder.m_sot_length);
             }
@@ -4621,7 +4630,7 @@ static OPJ_BOOL opj_j2k_read_rgn (opj_j2k_t *p_j2k,
                         opj_event_msg(p_manager, EVT_ERROR,
                                 "JPWL: bad component number in RGN (%d when there are only %d)\n",
                                 l_comp_room, l_nb_comp);
-                        if (!JPWL_ASSUME || JPWL_ASSUME) {
+                        if (!JPWL_ASSUME) {
                                 opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n");
                                 return OPJ_FALSE;
                         }
@@ -4706,7 +4715,7 @@ static OPJ_BOOL opj_j2k_update_rates(  opj_j2k_t *p_j2k,
                         l_rates = l_tcp->rates;
 
                         /* Modification of the RATE >> */
-                        if (*l_rates) {
+                        if (*l_rates > 0.0f) {
                                 *l_rates =              (( (OPJ_FLOAT32) (l_size_pixel * (OPJ_UINT32)(l_x1 - l_x0) * (OPJ_UINT32)(l_y1 - l_y0)))
                                                                 /
                                                                 ((*l_rates) * (OPJ_FLOAT32)l_bits_empty)
@@ -4718,7 +4727,7 @@ static OPJ_BOOL opj_j2k_update_rates(  opj_j2k_t *p_j2k,
                         ++l_rates;
 
                         for (k = 1; k < l_tcp->numlayers; ++k) {
-                                if (*l_rates) {
+                                if (*l_rates > 0.0f) {
                                         *l_rates =              (( (OPJ_FLOAT32) (l_size_pixel * (OPJ_UINT32)(l_x1 - l_x0) * (OPJ_UINT32)(l_y1 - l_y0)))
                                                                         /
                                                                                 ((*l_rates) * (OPJ_FLOAT32)l_bits_empty)
@@ -4741,11 +4750,11 @@ static OPJ_BOOL opj_j2k_update_rates(  opj_j2k_t *p_j2k,
                 for     (j=0;j<l_cp->tw;++j) {
                         l_rates = l_tcp->rates;
 
-                        if (*l_rates) {
+                        if (*l_rates > 0.0f) {
                                 *l_rates -= l_sot_remove;
 
-                                if (*l_rates < 30) {
-                                        *l_rates = 30;
+                                if (*l_rates < 30.0f) {
+                                        *l_rates = 30.0f;
                                 }
                         }
 
@@ -4755,22 +4764,22 @@ static OPJ_BOOL opj_j2k_update_rates(  opj_j2k_t *p_j2k,
 
                         for (k = 1; k < l_last_res; ++k) {
 
-                                if (*l_rates) {
+                                if (*l_rates > 0.0f) {
                                         *l_rates -= l_sot_remove;
 
-                                        if (*l_rates < *(l_rates - 1) + 10) {
-                                                *l_rates  = (*(l_rates - 1)) + 20;
+                                        if (*l_rates < *(l_rates - 1) + 10.0f) {
+                                                *l_rates  = (*(l_rates - 1)) + 20.0f;
                                         }
                                 }
 
                                 ++l_rates;
                         }
 
-                        if (*l_rates) {
+                        if (*l_rates > 0.0f) {
                                 *l_rates -= (l_sot_remove + 2.f);
 
-                                if (*l_rates < *(l_rates - 1) + 10) {
-                                        *l_rates  = (*(l_rates - 1)) + 20;
+                                if (*l_rates < *(l_rates - 1) + 10.0f) {
+                                        *l_rates  = (*(l_rates - 1)) + 20.0f;
                                 }
                         }
 
@@ -5362,7 +5371,7 @@ static OPJ_BOOL opj_j2k_write_mcc_record(      opj_j2k_t *p_j2k,
                 l_current_data+=l_nb_bytes_for_comp;
         }
 
-        l_tmcc = ((!p_mcc_record->m_is_irreversible)&1)<<16;
+        l_tmcc = ((!p_mcc_record->m_is_irreversible) & 1U) << 16;
 
         if (p_mcc_record->m_decorrelation_array) {
                 l_tmcc |= p_mcc_record->m_decorrelation_array->m_index;
@@ -5614,8 +5623,7 @@ static OPJ_BOOL opj_j2k_write_mco(     opj_j2k_t *p_j2k,
         assert(p_stream != 00);
 
         l_tcp =&(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]);
-        l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
-
+       
         l_mco_size = 5 + l_tcp->m_nb_mcc_records;
         if (l_mco_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
 
@@ -5630,6 +5638,8 @@ static OPJ_BOOL opj_j2k_write_mco(     opj_j2k_t *p_j2k,
                 p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
                 p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mco_size;
         }
+        l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
+
 
         opj_write_bytes(l_current_data,J2K_MS_MCO,2);                   /* MCO */
         l_current_data += 2;
@@ -5637,14 +5647,13 @@ static OPJ_BOOL opj_j2k_write_mco(     opj_j2k_t *p_j2k,
         opj_write_bytes(l_current_data,l_mco_size-2,2);                 /* Lmco */
         l_current_data += 2;
 
-        opj_write_bytes(l_current_data,l_tcp->m_nb_mcc_records,1);      /* Nmco : only one tranform stage*/
+        opj_write_bytes(l_current_data,l_tcp->m_nb_mcc_records,1);      /* Nmco : only one transform stage*/
         ++l_current_data;
 
         l_mcc_record = l_tcp->m_mcc_records;
-        for     (i=0;i<l_tcp->m_nb_mcc_records;++i) {
+        for (i=0;i<l_tcp->m_nb_mcc_records;++i) {
                 opj_write_bytes(l_current_data,l_mcc_record->m_index,1);/* Imco -> use the mcc indicated by 1*/
                 ++l_current_data;
-
                 ++l_mcc_record;
         }
 
@@ -5690,7 +5699,7 @@ static OPJ_BOOL opj_j2k_read_mco (      opj_j2k_t *p_j2k,
                 return OPJ_FALSE;
         }
 
-        opj_read_bytes(p_header_data,&l_nb_stages,1);                           /* Nmco : only one tranform stage*/
+        opj_read_bytes(p_header_data,&l_nb_stages,1);                           /* Nmco : only one transform stage*/
         ++p_header_data;
 
         if (l_nb_stages > 1) {
@@ -5935,6 +5944,32 @@ void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters)
         }
 }
 
+OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads)
+{
+        if( opj_has_thread_support() )
+        {
+            opj_thread_pool_destroy(j2k->m_tp);
+            j2k->m_tp = opj_thread_pool_create((int)num_threads);
+            if( j2k->m_tp == 0 )
+            {
+                j2k->m_tp = opj_thread_pool_create(0);
+                return OPJ_FALSE;
+            }
+            return OPJ_TRUE;
+        }
+        return OPJ_FALSE;
+}
+
+static int opj_j2k_get_default_thread_count()
+{
+    const char* num_threads = getenv("OPJ_NUM_THREADS");
+    if( num_threads == NULL || !opj_has_thread_support() )
+        return 0;
+    if( strcmp(num_threads, "ALL_CPUS") == 0 )
+        return opj_get_num_cpus();
+    return atoi(num_threads);
+}
+
 /* ----------------------------------------------------------------------- */
 /* J2K encoder interface                                                       */
 /* ----------------------------------------------------------------------- */
@@ -5972,6 +6007,17 @@ opj_j2k_t* opj_j2k_create_compress(void)
                 return NULL;
         }
 
+        l_j2k->m_tp = opj_thread_pool_create(opj_j2k_get_default_thread_count());
+        if( !l_j2k->m_tp )
+        {
+            l_j2k->m_tp = opj_thread_pool_create(0);
+        }
+        if( !l_j2k->m_tp )
+        {
+            opj_j2k_destroy(l_j2k);
+            return NULL;
+        }
+
         return l_j2k;
 }
 
@@ -7477,7 +7523,7 @@ static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd (       opj_j2k_t * p_j2
                 return OPJ_FALSE;
         }
 
-        if ( !opj_tcd_init(p_j2k->m_tcd, l_image, &(p_j2k->m_cp)) ) {
+        if ( !opj_tcd_init(p_j2k->m_tcd, l_image, &(p_j2k->m_cp), p_j2k->m_tp) ) {
                 opj_tcd_destroy(p_j2k->m_tcd);
                 p_j2k->m_tcd = 00;
                 opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n");
@@ -7558,6 +7604,9 @@ void opj_j2k_destroy (opj_j2k_t *p_j2k)
         opj_image_destroy(p_j2k->m_output_image);
         p_j2k->m_output_image = NULL;
 
+        opj_thread_pool_destroy(p_j2k->m_tp);
+        p_j2k->m_tp = NULL;
+
         opj_free(p_j2k);
 }
 
@@ -7737,6 +7786,11 @@ static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t *p_st
        /* initialize to no correction needed */
        *p_correction_needed = OPJ_FALSE;
        
+       if (!opj_stream_has_seek(p_stream)) {
+               /* We can't do much in this case, seek is needed */
+               return OPJ_TRUE;
+       }
+       
        l_stream_pos_backup = opj_stream_tell(p_stream);
        if (l_stream_pos_backup == -1) {
                /* let's do nothing */
@@ -8644,6 +8698,17 @@ opj_j2k_t* opj_j2k_create_decompress(void)
                 return 00;
         }
 
+        l_j2k->m_tp = opj_thread_pool_create(opj_j2k_get_default_thread_count());
+        if( !l_j2k->m_tp )
+        {
+            l_j2k->m_tp = opj_thread_pool_create(0);
+        }
+        if( !l_j2k->m_tp )
+        {
+            opj_j2k_destroy(l_j2k);
+            return NULL;
+        }
+
         return l_j2k;
 }
 
@@ -8658,8 +8723,10 @@ static opj_codestream_index_t* opj_j2k_create_cstr_index(void)
         cstr_index->marknum = 0;
         cstr_index->marker = (opj_marker_info_t*)
                         opj_calloc(cstr_index->maxmarknum, sizeof(opj_marker_info_t));
-        if (!cstr_index-> marker)
+        if (!cstr_index-> marker) {
+                opj_free(cstr_index);
                 return NULL;
+        }
 
         cstr_index->tile_index = NULL;
 
@@ -8873,6 +8940,10 @@ static OPJ_BOOL opj_j2k_read_SPCod_SPCoc(  opj_j2k_t *p_j2k,
 
         opj_read_bytes(l_current_ptr,&l_tccp->cblksty ,1);              /* SPcoc (G) */
         ++l_current_ptr;
+        if (l_tccp->cblksty & 0xC0U) { /* 2 msb are reserved, assume we can't read */
+                opj_event_msg(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element, Invalid code-block style found\n");
+                return OPJ_FALSE;
+        }
 
         opj_read_bytes(l_current_ptr,&l_tccp->qmfbid ,1);               /* SPcoc (H) */
         ++l_current_ptr;
@@ -9327,16 +9398,19 @@ void j2k_dump (opj_j2k_t* p_j2k, OPJ_INT32 flag, FILE* out_stream)
 
         /* Dump the codestream info from main header */
         if (flag & OPJ_J2K_MH_INFO){
-                opj_j2k_dump_MH_info(p_j2k, out_stream);
+                if (p_j2k->m_private_image)
+                        opj_j2k_dump_MH_info(p_j2k, out_stream);
         }
         /* Dump all tile/codestream info */
         if (flag & OPJ_J2K_TCH_INFO){
           OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
           OPJ_UINT32 i;
           opj_tcp_t * l_tcp = p_j2k->m_cp.tcps;
-          for (i=0;i<l_nb_tiles;++i) {
-            opj_j2k_dump_tile_info( l_tcp,(OPJ_INT32)p_j2k->m_private_image->numcomps, out_stream);
-            ++l_tcp;
+          if (p_j2k->m_private_image) {
+            for (i=0;i<l_nb_tiles;++i) {
+              opj_j2k_dump_tile_info( l_tcp,(OPJ_INT32)p_j2k->m_private_image->numcomps, out_stream);
+              ++l_tcp;
+            }
           }
         }
 
@@ -9817,14 +9891,14 @@ static OPJ_BOOL opj_j2k_decode_one_tile (       opj_j2k_t *p_j2k,
                                  *  so move to the last SOT read */
                                 if ( !(opj_stream_read_seek(p_stream, p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos+2, p_manager)) ){
                                         opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n");
-                        opj_free(l_current_data);
+                                        opj_free(l_current_data);
                                         return OPJ_FALSE;
                                 }
                         }
                         else{
                                 if ( !(opj_stream_read_seek(p_stream, p_j2k->cstr_index->tile_index[l_tile_no_to_dec].tp_index[0].start_pos+2, p_manager)) ) {
                                         opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n");
-                        opj_free(l_current_data);
+                                        opj_free(l_current_data);
                                         return OPJ_FALSE;
                                 }
                         }
@@ -9856,9 +9930,7 @@ static OPJ_BOOL opj_j2k_decode_one_tile (       opj_j2k_t *p_j2k,
                         if (! l_new_current_data) {
                                 opj_free(l_current_data);
                                 l_current_data = NULL;
-                                /* TODO: LH: why tile numbering policy used in messages differs from
-                                   the one used in opj_j2k_decode_tiles() ? */
-                                opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode tile %d/%d\n", l_current_tile_no, (p_j2k->m_cp.th * p_j2k->m_cp.tw) - 1);
+                                opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode tile %d/%d\n", l_current_tile_no+1, p_j2k->m_cp.th * p_j2k->m_cp.tw);
                                 return OPJ_FALSE;
                         }
                         l_current_data = l_new_current_data;
@@ -9869,25 +9941,26 @@ static OPJ_BOOL opj_j2k_decode_one_tile (       opj_j2k_t *p_j2k,
                         opj_free(l_current_data);
                         return OPJ_FALSE;
                 }
-                opj_event_msg(p_manager, EVT_INFO, "Tile %d/%d has been decoded.\n", l_current_tile_no, (p_j2k->m_cp.th * p_j2k->m_cp.tw) - 1);
+                opj_event_msg(p_manager, EVT_INFO, "Tile %d/%d has been decoded.\n", l_current_tile_no+1, p_j2k->m_cp.th * p_j2k->m_cp.tw);
 
                 if (! opj_j2k_update_image_data(p_j2k->m_tcd,l_current_data, p_j2k->m_output_image)) {
                         opj_free(l_current_data);
                         return OPJ_FALSE;
                 }
-                opj_event_msg(p_manager, EVT_INFO, "Image data has been updated with tile %d.\n\n", l_current_tile_no);
+                opj_event_msg(p_manager, EVT_INFO, "Image data has been updated with tile %d.\n\n", l_current_tile_no+1);
 
                 if(l_current_tile_no == l_tile_no_to_dec)
                 {
-                        /* move into the codestream to the the first SOT (FIXME or not move?)*/
+                        /* move into the codestream to the first SOT (FIXME or not move?)*/
                         if (!(opj_stream_read_seek(p_stream, p_j2k->cstr_index->main_head_end + 2, p_manager) ) ) {
                                 opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n");
+                                opj_free(l_current_data);
                                 return OPJ_FALSE;
                         }
                         break;
                 }
                 else {
-                        opj_event_msg(p_manager, EVT_WARNING, "Tile read, decode and updated is not the desired (%d vs %d).\n", l_current_tile_no, l_tile_no_to_dec);
+                        opj_event_msg(p_manager, EVT_WARNING, "Tile read, decoded and updated is not the desired one (%d vs %d).\n", l_current_tile_no+1, l_tile_no_to_dec+1);
                 }
 
         }
@@ -10088,6 +10161,7 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
         OPJ_UINT32 l_nb_tiles;
         OPJ_UINT32 l_max_tile_size = 0, l_current_tile_size;
         OPJ_BYTE * l_current_data = 00;
+        OPJ_BOOL l_reuse_data = OPJ_FALSE;
         opj_tcd_t* p_tcd = 00;
 
         /* preconditions */
@@ -10098,6 +10172,17 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
         p_tcd = p_j2k->m_tcd;
 
         l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
+        if (l_nb_tiles == 1) {
+                l_reuse_data = OPJ_TRUE;
+#ifdef __SSE__
+                for (j=0;j<p_j2k->m_tcd->image->numcomps;++j) {
+                        opj_image_comp_t * l_img_comp = p_tcd->image->comps + j;
+                        if (((size_t)l_img_comp->data & 0xFU) != 0U) { /* tile data shall be aligned on 16 bytes */
+                                                                                                       l_reuse_data = OPJ_FALSE;
+                        }
+                }
+#endif
+        }
         for (i=0;i<l_nb_tiles;++i) {
                 if (! opj_j2k_pre_write_tile(p_j2k,i,p_stream,p_manager)) {
                         if (l_current_data) {
@@ -10110,7 +10195,7 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
                 /* otherwise, allocate the data */
                 for (j=0;j<p_j2k->m_tcd->image->numcomps;++j) {
                         opj_tcd_tilecomp_t* l_tilec = p_tcd->tcd_image->tiles->comps + j;
-                        if (l_nb_tiles == 1) {
+                        if (l_reuse_data) {
                                                                                                        opj_image_comp_t * l_img_comp = p_tcd->image->comps + j;
                                                                                                        l_tilec->data  =  l_img_comp->data;
                                                                                                        l_tilec->ownsData = OPJ_FALSE;
@@ -10125,7 +10210,7 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
                         }
                 }
                 l_current_tile_size = opj_tcd_get_encoded_tile_size(p_j2k->m_tcd);
-                if (l_nb_tiles > 1) {
+                if (!l_reuse_data) {
                         if (l_current_tile_size > l_max_tile_size) {
                                                                                                        OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(l_current_data, l_current_tile_size);
                                                                                                        if (! l_new_current_data) {
@@ -10147,11 +10232,15 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
                         /* now copy this data into the tile component */
                         if (! opj_tcd_copy_tile_data(p_j2k->m_tcd,l_current_data,l_current_tile_size)) {
                                                                                                                                opj_event_msg(p_manager, EVT_ERROR, "Size mismatch between tile data and sent data." );
+                                                                                                                               opj_free(l_current_data);
                                                                                                                                return OPJ_FALSE;
                         }
                 }
 
                 if (! opj_j2k_post_write_tile (p_j2k,p_stream,p_manager)) {
+                        if (l_current_data) {
+                                opj_free(l_current_data);
+                        }
                         return OPJ_FALSE;
                 }
         }
@@ -10896,7 +10985,7 @@ static OPJ_BOOL opj_j2k_create_tcd(     opj_j2k_t *p_j2k,
                 return OPJ_FALSE;
         }
 
-        if (!opj_tcd_init(p_j2k->m_tcd,p_j2k->m_private_image,&p_j2k->m_cp)) {
+        if (!opj_tcd_init(p_j2k->m_tcd,p_j2k->m_private_image,&p_j2k->m_cp, p_j2k->m_tp)) {
                 opj_tcd_destroy(p_j2k->m_tcd);
                 p_j2k->m_tcd = 00;
                 return OPJ_FALSE;
@@ -10928,7 +11017,7 @@ OPJ_BOOL opj_j2k_write_tile (opj_j2k_t * p_j2k,
                         }
                 }
 
-                /* now copy data into the the tile component */
+                /* now copy data into the tile component */
                 if (! opj_tcd_copy_tile_data(p_j2k->m_tcd,p_data,p_data_size)) {
                         opj_event_msg(p_manager, EVT_ERROR, "Size mismatch between tile data and sent data." );
                         return OPJ_FALSE;