Merge pull request #551 from mayeut/coc-qcc
[openjpeg.git] / src / lib / openjp2 / j2k.c
index ec3635b6e8cb550a4b3019f999fff79923a4362a..f0e565eae9bd6d62a422b954b6100177ec4084c4 100644 (file)
@@ -212,6 +212,18 @@ static void opj_j2k_tcp_data_destroy (opj_tcp_t *p_tcp);
  */
 static void opj_j2k_cp_destroy (opj_cp_t *p_cp);
 
+/**
+ * Compare 2 a SPCod/ SPCoc elements, i.e. the coding style of a given component of a tile.
+ *
+ * @param       p_j2k            J2K codec.
+ * @param       p_tile_no        Tile number
+ * @param       p_first_comp_no  The 1st component number to compare.
+ * @param       p_second_comp_no The 1st component number to compare.
+ *
+ * @return OPJ_TRUE if SPCdod are equals.
+ */
+static OPJ_BOOL opj_j2k_compare_SPCod_SPCoc(opj_j2k_t *p_j2k, OPJ_UINT32 p_tile_no, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no);
+
 /**
  * Writes a SPCod or SPCoc element, i.e. the coding style of a given component of a tile.
  *
@@ -271,6 +283,19 @@ static OPJ_UINT32 opj_j2k_get_SQcd_SQcc_size (  opj_j2k_t *p_j2k,
                                                                                     OPJ_UINT32 p_tile_no,
                                                                                     OPJ_UINT32 p_comp_no );
 
+/**
+ * Compares 2 SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC.
+ *
+ * @param       p_j2k                   J2K codec.
+ * @param       p_tile_no               the tile to output.
+ * @param       p_first_comp_no         the first component number to compare.
+ * @param       p_second_comp_no        the second component number to compare.
+ *
+ * @return OPJ_TRUE if equals.
+ */
+static OPJ_BOOL opj_j2k_compare_SQcd_SQcc(opj_j2k_t *p_j2k, OPJ_UINT32 p_tile_no, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no);
+
+
 /**
  * Writes a SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC.
  *
@@ -484,7 +509,17 @@ static OPJ_BOOL opj_j2k_read_cod (  opj_j2k_t *p_j2k,
                                     OPJ_UINT32 p_header_size,
                                     opj_event_mgr_t * p_manager);
 
-#if 0
+/**
+ * Compares 2 COC markers (Coding style component)
+ *
+ * @param       p_j2k            J2K codec.
+ * @param       p_first_comp_no  the index of the first component to compare.
+ * @param       p_second_comp_no the index of the second component to compare.
+ *
+ * @return      OPJ_TRUE if equals
+ */
+static OPJ_BOOL opj_j2k_compare_coc(opj_j2k_t *p_j2k, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no);
+
 /**
  * Writes the COC marker (Coding style component)
  *
@@ -497,9 +532,7 @@ static OPJ_BOOL opj_j2k_write_coc(  opj_j2k_t *p_j2k,
                                                                 OPJ_UINT32 p_comp_no,
                                                                 opj_stream_private_t *p_stream,
                                                                 opj_event_mgr_t * p_manager );
-#endif
 
-#if 0
 /**
  * Writes the COC marker (Coding style component)
  *
@@ -514,7 +547,6 @@ static void opj_j2k_write_coc_in_memory(opj_j2k_t *p_j2k,
                                                                             OPJ_BYTE * p_data,
                                                                             OPJ_UINT32 * p_data_written,
                                                                             opj_event_mgr_t * p_manager );
-#endif
 
 /**
  * Gets the maximum size taken by a coc.
@@ -557,7 +589,18 @@ static OPJ_BOOL opj_j2k_read_qcd (  opj_j2k_t *p_j2k,
                                     OPJ_BYTE * p_header_data,
                                     OPJ_UINT32 p_header_size,
                                     opj_event_mgr_t * p_manager );
-#if 0
+
+/**
+ * Compare QCC markers (quantization component)
+ *
+ * @param       p_j2k                 J2K codec.
+ * @param       p_first_comp_no       the index of the first component to compare.
+ * @param       p_second_comp_no      the index of the second component to compare.
+ *
+ * @return OPJ_TRUE if equals.
+ */
+static OPJ_BOOL opj_j2k_compare_qcc(opj_j2k_t *p_j2k, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no);
+
 /**
  * Writes the QCC marker (quantization component)
  *
@@ -570,9 +613,7 @@ static OPJ_BOOL opj_j2k_write_qcc(      opj_j2k_t *p_j2k,
                                                                         OPJ_UINT32 p_comp_no,
                                                                         opj_stream_private_t *p_stream,
                                                                         opj_event_mgr_t * p_manager );
-#endif
 
-#if 0
 /**
  * Writes the QCC marker (quantization component)
  *
@@ -587,7 +628,6 @@ static void opj_j2k_write_qcc_in_memory(opj_j2k_t *p_j2k,
                                                                             OPJ_BYTE * p_data,
                                                                             OPJ_UINT32 * p_data_written,
                                                                             opj_event_mgr_t * p_manager );
-#endif
 
 /**
  * Gets the maximum size taken by a qcc.
@@ -1097,7 +1137,7 @@ static OPJ_BOOL opj_j2k_read_cbd (      opj_j2k_t *p_j2k,
                                                                 OPJ_UINT32 p_header_size,
                                                                 opj_event_mgr_t * p_manager);
 
-#if 0
+
 /**
  * Writes COC marker for each component.
  *
@@ -1108,9 +1148,7 @@ static OPJ_BOOL opj_j2k_read_cbd (      opj_j2k_t *p_j2k,
 static OPJ_BOOL opj_j2k_write_all_coc( opj_j2k_t *p_j2k,
                                                                         opj_stream_private_t *p_stream,
                                                                         opj_event_mgr_t * p_manager );
-#endif
 
-#if 0
 /**
  * Writes QCC marker for each component.
  *
@@ -1121,7 +1159,6 @@ static OPJ_BOOL opj_j2k_write_all_coc( opj_j2k_t *p_j2k,
 static OPJ_BOOL opj_j2k_write_all_qcc( opj_j2k_t *p_j2k,
                                                                         opj_stream_private_t *p_stream,
                                                                         opj_event_mgr_t * p_manager );
-#endif
 
 /**
  * Writes regions of interests.
@@ -2550,7 +2587,6 @@ static OPJ_BOOL opj_j2k_read_cod (  opj_j2k_t *p_j2k,
         return OPJ_TRUE;
 }
 
-#if 0
 static OPJ_BOOL opj_j2k_write_coc( opj_j2k_t *p_j2k,
                                                 OPJ_UINT32 p_comp_no,
                                                 opj_stream_private_t *p_stream,
@@ -2595,9 +2631,26 @@ static OPJ_BOOL opj_j2k_write_coc( opj_j2k_t *p_j2k,
 
         return OPJ_TRUE;
 }
-#endif
 
-#if 0
+static OPJ_BOOL opj_j2k_compare_coc(opj_j2k_t *p_j2k, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no)
+{
+       opj_cp_t *l_cp = NULL;
+       opj_tcp_t *l_tcp = NULL;
+       
+       /* preconditions */
+       assert(p_j2k != 00);
+       
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number];
+       
+       if (l_tcp->tccps[p_first_comp_no].csty != l_tcp->tccps[p_second_comp_no].csty) {
+               return OPJ_FALSE;
+       }
+       
+       
+       return opj_j2k_compare_SPCod_SPCoc(p_j2k, p_j2k->m_current_tile_number, p_first_comp_no, p_second_comp_no);
+}
+
 static void opj_j2k_write_coc_in_memory(   opj_j2k_t *p_j2k,
                                                 OPJ_UINT32 p_comp_no,
                                                 OPJ_BYTE * p_data,
@@ -2642,7 +2695,6 @@ static void opj_j2k_write_coc_in_memory(   opj_j2k_t *p_j2k,
         opj_j2k_write_SPCod_SPCoc(p_j2k,p_j2k->m_current_tile_number,0,l_current_data,&l_remaining_size,p_manager);
         * p_data_written = l_coc_size;
 }
-#endif
 
 static OPJ_UINT32 opj_j2k_get_max_coc_size(opj_j2k_t *p_j2k)
 {
@@ -2816,7 +2868,6 @@ static OPJ_BOOL opj_j2k_read_qcd (  opj_j2k_t *p_j2k,
         return OPJ_TRUE;
 }
 
-#if 0
 static OPJ_BOOL opj_j2k_write_qcc(     opj_j2k_t *p_j2k,
                                                 OPJ_UINT32 p_comp_no,
                                                 opj_stream_private_t *p_stream,
@@ -2855,9 +2906,12 @@ static OPJ_BOOL opj_j2k_write_qcc(     opj_j2k_t *p_j2k,
 
         return OPJ_TRUE;
 }
-#endif
 
-#if 0
+static OPJ_BOOL opj_j2k_compare_qcc(opj_j2k_t *p_j2k, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no)
+{
+       return opj_j2k_compare_SQcd_SQcc(p_j2k,p_j2k->m_current_tile_number,p_first_comp_no, p_second_comp_no);
+}
+
 static void opj_j2k_write_qcc_in_memory(   opj_j2k_t *p_j2k,
                                                                 OPJ_UINT32 p_comp_no,
                                                                 OPJ_BYTE * p_data,
@@ -2906,7 +2960,6 @@ static void opj_j2k_write_qcc_in_memory(   opj_j2k_t *p_j2k,
 
         *p_data_written = l_qcc_size;
 }
-#endif
 
 static OPJ_UINT32 opj_j2k_get_max_qcc_size (opj_j2k_t *p_j2k)
 {
@@ -3562,7 +3615,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");
@@ -3784,7 +3837,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");
@@ -4351,7 +4404,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);
             }
@@ -4877,52 +4930,54 @@ static OPJ_BOOL opj_j2k_write_mct_data_group(  opj_j2k_t *p_j2k,
         return OPJ_TRUE;
 }
 
-#if 0
-static OPJ_BOOL opj_j2k_write_all_coc(opj_j2k_t *p_j2k,
-                                                                        struct opj_stream_private *p_stream,
-                                                                        struct opj_event_mgr * p_manager )
+static OPJ_BOOL opj_j2k_write_all_coc(
+       opj_j2k_t *p_j2k,
+       struct opj_stream_private *p_stream,
+       struct opj_event_mgr * p_manager )
 {
-        OPJ_UINT32 compno;
-
-        /* preconditions */
-        assert(p_j2k != 00);
-        assert(p_manager != 00);
-        assert(p_stream != 00);
-
-        for (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno)
-        {
-                if (! opj_j2k_write_coc(p_j2k,compno,p_stream, p_manager)) {
-                        return OPJ_FALSE;
-                }
-        }
-
-        return OPJ_TRUE;
+       OPJ_UINT32 compno;
+       
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+       
+       for (compno = 1; compno < p_j2k->m_private_image->numcomps; ++compno)
+       {
+               /* cod is first component of first tile */
+               if (! opj_j2k_compare_coc(p_j2k, 0, compno)) {
+                       if (! opj_j2k_write_coc(p_j2k,compno,p_stream, p_manager)) {
+                               return OPJ_FALSE;
+                       }
+               }
+       }
+       
+       return OPJ_TRUE;
 }
-#endif
 
-#if 0
-static OPJ_BOOL opj_j2k_write_all_qcc(opj_j2k_t *p_j2k,
-                                                                        struct opj_stream_private *p_stream,
-                                                                        struct opj_event_mgr * p_manager )
+static OPJ_BOOL opj_j2k_write_all_qcc(
+       opj_j2k_t *p_j2k,
+       struct opj_stream_private *p_stream,
+       struct opj_event_mgr * p_manager )
 {
-        OPJ_UINT32 compno;
-
-        /* preconditions */
-        assert(p_j2k != 00);
-        assert(p_manager != 00);
-        assert(p_stream != 00);
-
-        for (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno)
-        {
-                if (! opj_j2k_write_qcc(p_j2k,compno,p_stream, p_manager)) {
-                        return OPJ_FALSE;
-                }
-        }
-
-        return OPJ_TRUE;
+       OPJ_UINT32 compno;
+       
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+       
+       for (compno = 1; compno < p_j2k->m_private_image->numcomps; ++compno)
+       {
+               /* qcd is first component of first tile */
+               if (! opj_j2k_compare_qcc(p_j2k, 0, compno)) {
+                       if (! opj_j2k_write_qcc(p_j2k,compno,p_stream, p_manager)) {
+                               return OPJ_FALSE;
+                       }
+               }
+       }
+       return OPJ_TRUE;
 }
-#endif
-
 
 static OPJ_BOOL opj_j2k_write_regions( opj_j2k_t *p_j2k,
                                                         struct opj_stream_private *p_stream,
@@ -5583,7 +5638,7 @@ 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;
@@ -5635,7 +5690,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) {
@@ -7682,6 +7737,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 */
@@ -8603,8 +8663,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;
 
@@ -8638,6 +8700,52 @@ static OPJ_UINT32 opj_j2k_get_SPCod_SPCoc_size (       opj_j2k_t *p_j2k,
         }
 }
 
+static OPJ_BOOL opj_j2k_compare_SPCod_SPCoc(opj_j2k_t *p_j2k, OPJ_UINT32 p_tile_no, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no)
+{
+       OPJ_UINT32 i;
+       opj_cp_t *l_cp = NULL;
+       opj_tcp_t *l_tcp = NULL;
+       opj_tccp_t *l_tccp0 = NULL;
+       opj_tccp_t *l_tccp1 = NULL;
+       
+       /* preconditions */
+       assert(p_j2k != 00);
+       
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = &l_cp->tcps[p_tile_no];
+       l_tccp0 = &l_tcp->tccps[p_first_comp_no];
+       l_tccp1 = &l_tcp->tccps[p_second_comp_no];
+       
+       if (l_tccp0->numresolutions != l_tccp1->numresolutions) {
+               return OPJ_FALSE;
+       }
+       if (l_tccp0->cblkw != l_tccp1->cblkw) {
+               return OPJ_FALSE;
+       }
+       if (l_tccp0->cblkh != l_tccp1->cblkh) {
+               return OPJ_FALSE;
+       }
+       if (l_tccp0->cblksty != l_tccp1->cblksty) {
+               return OPJ_FALSE;
+       }
+       if (l_tccp0->qmfbid != l_tccp1->qmfbid) {
+               return OPJ_FALSE;
+       }
+       if ((l_tccp0->csty & J2K_CCP_CSTY_PRT) != (l_tccp1->csty & J2K_CCP_CSTY_PRT)) {
+               return OPJ_FALSE;
+       }
+       
+       for (i = 0U; i < l_tccp0->numresolutions; ++i) {
+               if (l_tccp0->prcw[i] != l_tccp1->prcw[i]) {
+                       return OPJ_FALSE;
+               }
+               if (l_tccp0->prch[i] != l_tccp1->prch[i]) {
+                       return OPJ_FALSE;
+               }
+       }
+       return OPJ_TRUE;
+}
+
 static OPJ_BOOL opj_j2k_write_SPCod_SPCoc(     opj_j2k_t *p_j2k,
                                                                     OPJ_UINT32 p_tile_no,
                                                                     OPJ_UINT32 p_comp_no,
@@ -8891,6 +8999,54 @@ static OPJ_UINT32 opj_j2k_get_SQcd_SQcc_size ( opj_j2k_t *p_j2k,
         }
 }
 
+static OPJ_BOOL opj_j2k_compare_SQcd_SQcc(opj_j2k_t *p_j2k, OPJ_UINT32 p_tile_no, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no)
+{
+       opj_cp_t *l_cp = NULL;
+       opj_tcp_t *l_tcp = NULL;
+       opj_tccp_t *l_tccp0 = NULL;
+       opj_tccp_t *l_tccp1 = NULL;
+       OPJ_UINT32 l_band_no, l_num_bands;
+       
+       /* preconditions */
+       assert(p_j2k != 00);
+       
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = &l_cp->tcps[p_tile_no];
+       l_tccp0 = &l_tcp->tccps[p_first_comp_no];
+       l_tccp1 = &l_tcp->tccps[p_second_comp_no];
+       
+       if (l_tccp0->qntsty != l_tccp1->qntsty ) {
+               return OPJ_FALSE;
+       }
+       if (l_tccp0->numgbits != l_tccp1->numgbits ) {
+               return OPJ_FALSE;
+       }
+       if (l_tccp0->qntsty == J2K_CCP_QNTSTY_SIQNT) {
+               l_num_bands = 1U;
+       } else {
+               l_num_bands = l_tccp0->numresolutions * 3U - 2U;
+               if (l_num_bands != (l_tccp1->numresolutions * 3U - 2U)) {
+                       return OPJ_FALSE;
+               }
+       }
+       
+       for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) {
+               if (l_tccp0->stepsizes[l_band_no].expn != l_tccp1->stepsizes[l_band_no].expn ) {
+                       return OPJ_FALSE;
+               }
+       }
+       if (l_tccp0->qntsty != J2K_CCP_QNTSTY_NOQNT)
+       {
+               for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) {
+                       if (l_tccp0->stepsizes[l_band_no].mant != l_tccp1->stepsizes[l_band_no].mant ) {
+                               return OPJ_FALSE;
+                       }
+               }
+       }
+       return OPJ_TRUE;
+}
+
+
 static OPJ_BOOL opj_j2k_write_SQcd_SQcc(       opj_j2k_t *p_j2k,
                                                                 OPJ_UINT32 p_tile_no,
                                                                 OPJ_UINT32 p_comp_no,
@@ -9730,7 +9886,7 @@ static OPJ_BOOL opj_j2k_decode_one_tile (       opj_j2k_t *p_j2k,
 
                 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);
@@ -9940,6 +10096,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 */
@@ -9950,6 +10107,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) {
@@ -9962,7 +10130,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;
@@ -9977,7 +10145,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) {
@@ -10349,16 +10517,14 @@ static OPJ_BOOL opj_j2k_setup_header_writing (opj_j2k_t *p_j2k, opj_event_mgr_t
         if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_qcd, p_manager)) {
                 return OPJ_FALSE;
         }
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_all_coc, p_manager)) {
+                return OPJ_FALSE;
+        }
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_all_qcc, p_manager)) {
+                return OPJ_FALSE;
+        }
 
         if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz)) {
-                /* No need for COC or QCC, QCD and COD are used
-                if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_all_coc, p_manager)) {
-                        return OPJ_FALSE;
-                }
-                if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_all_qcc, p_manager)) {
-                        return OPJ_FALSE;
-                }
-                */
                 if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_tlm, p_manager)) {
                         return OPJ_FALSE;
                 }
@@ -10456,7 +10622,6 @@ static OPJ_BOOL opj_j2k_write_first_tile_part (opj_j2k_t *p_j2k,
                         p_total_data_size -= l_current_nb_bytes_written;
                 }
 #endif
-
                 if (l_cp->tcps[p_j2k->m_current_tile_number].numpocs) {
                         l_current_nb_bytes_written = 0;
                         opj_j2k_write_poc_in_memory(p_j2k,p_data,&l_current_nb_bytes_written,p_manager);
@@ -10787,7 +10952,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;