Merge to XFA: Upgrade openjpeg to revision 2997.
authorJUN FANG <jun_fang@foxitsoftware.com>
Fri, 27 Feb 2015 18:00:00 +0000 (10:00 -0800)
committerJUN FANG <jun_fang@foxitsoftware.com>
Fri, 27 Feb 2015 18:10:15 +0000 (10:10 -0800)
BUG=457493
R=tsepez@chromium.org

Review URL: https://codereview.chromium.org/960183004

13 files changed:
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/bio.c
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/j2k.c
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/jp2.c
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/mct.c
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/openjpeg.h
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_includes.h
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_intmath.h
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/pi.c
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.c
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.h
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t2.c
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.c
core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.h

index 5d49580..3ce6492 100644 (file)
@@ -81,7 +81,7 @@ static OPJ_BOOL opj_bio_bytein(opj_bio_t *bio);
 OPJ_BOOL opj_bio_byteout(opj_bio_t *bio) {
        bio->buf = (bio->buf << 8) & 0xffff;
        bio->ct = bio->buf == 0xff00 ? 7 : 8;
-       if (bio->bp >= bio->end) {
+       if ((OPJ_SIZE_T)bio->bp >= (OPJ_SIZE_T)bio->end) {
                return OPJ_FALSE;
        }
        *bio->bp++ = (OPJ_BYTE)(bio->buf >> 8);
@@ -91,7 +91,7 @@ OPJ_BOOL opj_bio_byteout(opj_bio_t *bio) {
 OPJ_BOOL opj_bio_bytein(opj_bio_t *bio) {
        bio->buf = (bio->buf << 8) & 0xffff;
        bio->ct = bio->buf == 0xff00 ? 7 : 8;
-       if (bio->bp >= bio->end) {
+       if ((OPJ_SIZE_T)bio->bp >= (OPJ_SIZE_T)bio->end) {
                return OPJ_FALSE;
        }
        bio->buf |= *bio->bp++;
@@ -169,12 +169,10 @@ OPJ_UINT32 opj_bio_read(opj_bio_t *bio, OPJ_UINT32 n) {
 }
 
 OPJ_BOOL opj_bio_flush(opj_bio_t *bio) {
-       bio->ct = 0;
        if (! opj_bio_byteout(bio)) {
                return OPJ_FALSE;
        }
        if (bio->ct == 7) {
-               bio->ct = 0;
                if (! opj_bio_byteout(bio)) {
                        return OPJ_FALSE;
                }
@@ -183,12 +181,11 @@ OPJ_BOOL opj_bio_flush(opj_bio_t *bio) {
 }
 
 OPJ_BOOL opj_bio_inalign(opj_bio_t *bio) {
-       bio->ct = 0;
        if ((bio->buf & 0xff) == 0xff) {
                if (! opj_bio_bytein(bio)) {
                        return OPJ_FALSE;
                }
-               bio->ct = 0;
        }
+       bio->ct = 0;
        return OPJ_TRUE;
 }
index 4a1c103..f944ad1 100644 (file)
@@ -1919,7 +1919,7 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
         OPJ_UINT32 l_nb_comp_remain;
         OPJ_UINT32 l_remaining_size;
         OPJ_UINT32 l_nb_tiles;
-        OPJ_UINT32 l_tmp;
+        OPJ_UINT32 l_tmp, l_tx1, l_ty1;
         opj_image_t *l_image = 00;
         opj_cp_t *l_cp = 00;
         opj_image_comp_t * l_img_comp = 00;
@@ -1981,8 +1981,9 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
         }
 
         /* testcase 4035.pdf.SIGSEGV.d8b.3375 */
-        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 image size (%d x %d)\n", l_image->x1 - l_image->x0, l_image->y1 - l_image->y0);
+        /* 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);
                 return OPJ_FALSE;
         }
         /* testcase 2539.pdf.SIGFPE.706.1712 (also 3622.pdf.SIGFPE.706.2916 and 4008.pdf.SIGFPE.706.3345 and maybe more) */
@@ -1997,6 +1998,20 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
                 return OPJ_FALSE;
         }
 
+        /* testcase issue427-illegal-tile-offset.jp2 */
+        l_tx1 = l_cp->tx0 + l_cp->tdx;
+        if (l_tx1 < l_cp->tx0) { /* manage overflow */
+                l_tx1 = 0xFFFFFFFFU;
+        }
+        l_ty1 = l_cp->ty0 + l_cp->tdy;
+        if (l_ty1 < l_cp->ty0) { /* manage overflow */
+                l_ty1 = 0xFFFFFFFFU;
+        }
+        if ((l_cp->tx0 > l_image->x0) || (l_cp->ty0 > l_image->y0) || (l_tx1 <= l_image->x0) || (l_ty1 <= l_image->y0) ) {
+                opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: illegal tile offset\n");
+                return OPJ_FALSE;
+        }
+
 #ifdef USE_JPWL
         if (l_cp->correct) {
                 /* if JPWL is on, we check whether TX errors have damaged
@@ -5221,6 +5236,7 @@ static OPJ_BOOL opj_j2k_read_mct (      opj_j2k_t *p_j2k,
                 }
 
                 l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records;
+                ++l_tcp->m_nb_mct_records;
         }
 
         if (l_mct_data->m_data) {
@@ -5249,7 +5265,6 @@ static OPJ_BOOL opj_j2k_read_mct (      opj_j2k_t *p_j2k,
         memcpy(l_mct_data->m_data,p_header_data,p_header_size);
 
         l_mct_data->m_data_size = p_header_size;
-        ++l_tcp->m_nb_mct_records;
 
         return OPJ_TRUE;
 }
@@ -6571,7 +6586,7 @@ OPJ_BOOL opj_j2k_setup_encoder(     opj_j2k_t *p_j2k,
                     }
                 }
                 else {
-                    if(tcp->mct==1 && image->numcomps == 3) { /* RGB->YCC MCT is enabled */
+                    if(tcp->mct==1 && image->numcomps >= 3) { /* RGB->YCC MCT is enabled */
                         if ((image->comps[0].dx != image->comps[1].dx) ||
                                 (image->comps[0].dx != image->comps[2].dx) ||
                                 (image->comps[0].dy != image->comps[1].dy) ||
@@ -7059,21 +7074,20 @@ OPJ_BOOL opj_j2k_encoding_validation (  opj_j2k_t * p_j2k,
         /* make sure a validation list is present */
         l_is_valid &= (p_j2k->m_validation_list != 00);
 
-             /* ISO 15444-1:2004 states between 1 & 33 (0 -> 32) */
-             /* 33 (32) would always fail the 2 checks below (if a cast to 64bits was done) */
-             /* 32 (31) would always fail the 2 checks below (if a cast to 64bits was done) */
-        /* FIXME Shall we change OPJ_J2K_MAXRLVLS to 31 ? */
-        if ((p_j2k->m_cp.tcps->tccps->numresolutions <= 0) || (p_j2k->m_cp.tcps->tccps->numresolutions > 31)) {
+        /* ISO 15444-1:2004 states between 1 & 33 (0 -> 32) */
+        /* 33 (32) would always fail the check below (if a cast to 64bits was done) */
+        /* FIXME Shall we change OPJ_J2K_MAXRLVLS to 32 ? */
+        if ((p_j2k->m_cp.tcps->tccps->numresolutions <= 0) || (p_j2k->m_cp.tcps->tccps->numresolutions > 32)) {
                 opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n");
                 return OPJ_FALSE;
         }
 
-        if ((p_j2k->m_cp.tdx) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) {
+        if ((p_j2k->m_cp.tdx) < (OPJ_UINT32) (1 << (p_j2k->m_cp.tcps->tccps->numresolutions - 1U))) {
                 opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n");
                 return OPJ_FALSE;
         }
 
-        if ((p_j2k->m_cp.tdy) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) {
+        if ((p_j2k->m_cp.tdy) < (OPJ_UINT32) (1 << (p_j2k->m_cp.tcps->tccps->numresolutions - 1U))) {
                 opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n");
                 return OPJ_FALSE;
         }
@@ -7151,7 +7165,7 @@ OPJ_BOOL opj_j2k_read_header_procedure( opj_j2k_t *p_j2k,
 
                 /* Check if the current marker ID is valid */
                 if (l_current_marker < 0xff00) {
-                        opj_event_msg(p_manager, EVT_ERROR, "We expected read a marker ID (0xff--) instead of %.8x\n", l_current_marker);
+                        opj_event_msg(p_manager, EVT_ERROR, "A marker ID was expected (0xff--) instead of %.8x\n", l_current_marker);
                         return OPJ_FALSE;
                 }
 
@@ -9776,7 +9790,7 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
         assert(p_j2k != 00);
         assert(p_stream != 00);
         assert(p_manager != 00);
-
+       
         p_tcd = p_j2k->m_tcd;
 
         l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
index 1830c11..aafbe19 100644 (file)
@@ -706,7 +706,7 @@ static OPJ_BYTE * opj_jp2_write_cdef(opj_jp2_t *jp2, OPJ_UINT32 * p_nb_bytes_wri
        assert(jp2->color.jp2_cdef->info != 00);
        assert(jp2->color.jp2_cdef->n > 0U);
 
-       l_cdef_size += 6 * jp2->color.jp2_cdef->n;
+       l_cdef_size += 6U * jp2->color.jp2_cdef->n;
 
        l_cdef_data = (OPJ_BYTE *) opj_malloc(l_cdef_size);
        if (l_cdef_data == 00) {
@@ -714,7 +714,7 @@ static OPJ_BYTE * opj_jp2_write_cdef(opj_jp2_t *jp2, OPJ_UINT32 * p_nb_bytes_wri
        }
 
        l_current_cdef_ptr = l_cdef_data;
-
+       
        opj_write_bytes(l_current_cdef_ptr,l_cdef_size,4);                      /* write box size */
        l_current_cdef_ptr += 4;
 
@@ -1184,16 +1184,16 @@ void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color)
 {
        opj_jp2_cdef_info_t *info;
        OPJ_UINT16 i, n, cn, asoc, acn;
-
+       
        info = color->jp2_cdef->info;
        n = color->jp2_cdef->n;
-
+       
        for(i = 0; i < n; ++i)
        {
                /* WATCH: acn = asoc - 1 ! */
                asoc = info[i].asoc;
                cn = info[i].cn;
-
+               
                if( cn >= image->numcomps)
                {
                        fprintf(stderr, "cn=%d, numcomps=%d\n", cn, image->numcomps);
@@ -1204,26 +1204,26 @@ void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color)
                        image->comps[cn].alpha = info[i].typ;
                        continue;
                }
-
+               
                acn = (OPJ_UINT16)(asoc - 1);
                if( acn >= image->numcomps )
                {
                        fprintf(stderr, "acn=%d, numcomps=%d\n", acn, image->numcomps);
                        continue;
                }
-
+               
                /* Swap only if color channel */
                if((cn != acn) && (info[i].typ == 0))
                {
                        opj_image_comp_t saved;
                        OPJ_UINT16 j;
-
+                       
                        memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t));
                        memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t));
                        memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t));
-
+                       
                        /* Swap channels in following channel definitions, don't bother with j <= i that are already processed */
-                       for (j = i + 1; j < n ; ++j)
+                       for (j = (OPJ_UINT16)(i + 1U); j < n ; ++j)
                        {
                                if (info[j].cn == cn) {
                                        info[j].cn = acn;
@@ -1234,14 +1234,14 @@ void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color)
                                /* asoc is related to color index. Do not update. */
                        }
                }
-
+               
                image->comps[cn].alpha = info[i].typ;
        }
-
+       
        if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info);
-
+       
        opj_free(color->jp2_cdef); color->jp2_cdef = NULL;
-
+       
 }/* jp2_apply_cdef() */
 
 OPJ_BOOL opj_jp2_read_cdef(    opj_jp2_t * jp2,
@@ -1487,7 +1487,7 @@ OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2,
                l_writers[l_nb_pass].handler = opj_jp2_write_cdef;
                l_nb_pass++;
        }
-
+       
        /* write box header */
        /* write JP2H type */
        opj_write_bytes(l_jp2h_data+4,JP2_JP2H,4);
@@ -1693,7 +1693,7 @@ OPJ_BOOL opj_jp2_setup_encoder(   opj_jp2_t *jp2,
        OPJ_UINT32 alpha_count;
        OPJ_UINT32 color_channels = 0U;
        OPJ_UINT32 alpha_channel = 0U;
-
+       
 
        if(!jp2 || !parameters || !image)
                return OPJ_FALSE;
@@ -1969,7 +1969,7 @@ OPJ_BOOL opj_jp2_default_validation (     opj_jp2_t * jp2,
        l_is_valid &= (jp2->w > 0);
        /* precision */
        for (i = 0; i < jp2->numcomps; ++i)     {
-               l_is_valid &= (jp2->comps[i].bpcc > 0);
+               l_is_valid &= ((jp2->comps[i].bpcc & 0x7FU) < 38U); /* 0 is valid, ignore sign for check */
        }
 
        /* METH */
@@ -2066,6 +2066,16 @@ OPJ_BOOL opj_jp2_read_header_procedure(  opj_jp2_t *jp2,
                        }
                }
                else {
+            if (!(jp2->jp2_state & JP2_STATE_SIGNATURE)) {
+                opj_event_msg(p_manager, EVT_ERROR, "Malformed JP2 file format: first box must be JPEG 2000 signature box\n");
+                opj_free(l_current_data);
+                return OPJ_FALSE;
+            }
+            if (!(jp2->jp2_state & JP2_STATE_FILE_TYPE)) {
+                opj_event_msg(p_manager, EVT_ERROR, "Malformed JP2 file format: second box must be file type box\n");
+                opj_free(l_current_data);
+                return OPJ_FALSE;
+            }
                        jp2->jp2_state |= JP2_STATE_UNKNOWN;
                        if (opj_stream_skip(stream,l_current_data_size,p_manager) != l_current_data_size) {
                                opj_event_msg(p_manager, EVT_ERROR, "Problem with skipping JPEG2000 box, stream error\n");
@@ -2719,7 +2729,7 @@ OPJ_BOOL opj_jp2_get_tile(        opj_jp2_t *p_jp2,
                else
                        opj_jp2_apply_pclr(p_image, &(p_jp2->color));
        }
-
+       
        /* Apply the color space if needed */
        if(p_jp2->color.jp2_cdef) {
                opj_jp2_apply_cdef(p_image, &(p_jp2->color));
index 60ee096..a0da099 100644 (file)
 #ifdef __SSE__
 #include <xmmintrin.h>
 #endif
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+#ifdef __SSE4_1__
+#include <smmintrin.h>
+#endif
 
 #include "opj_includes.h"
 
@@ -66,14 +72,33 @@ const OPJ_FLOAT64 * opj_mct_get_mct_norms_real ()
 /* <summary> */
 /* Foward reversible MCT. */
 /* </summary> */
+#ifdef __SSE2__
 void opj_mct_encode(
                OPJ_INT32* restrict c0,
                OPJ_INT32* restrict c1,
                OPJ_INT32* restrict c2,
                OPJ_UINT32 n)
 {
-       OPJ_UINT32 i;
-       for(i = 0; i < n; ++i) {
+       OPJ_SIZE_T i;
+       const OPJ_SIZE_T len = n;
+       
+       for(i = 0; i < (len & ~3U); i += 4) {
+               __m128i y, u, v;
+               __m128i r = _mm_load_si128((const __m128i *)&(c0[i]));
+               __m128i g = _mm_load_si128((const __m128i *)&(c1[i]));
+               __m128i b = _mm_load_si128((const __m128i *)&(c2[i]));
+               y = _mm_add_epi32(g, g);
+               y = _mm_add_epi32(y, b);
+               y = _mm_add_epi32(y, r);
+               y = _mm_srai_epi32(y, 2);
+               u = _mm_sub_epi32(b, g);
+               v = _mm_sub_epi32(r, g);
+               _mm_store_si128((__m128i *)&(c0[i]), y);
+               _mm_store_si128((__m128i *)&(c1[i]), u);
+               _mm_store_si128((__m128i *)&(c2[i]), v);
+       }
+       
+       for(; i < len; ++i) {
                OPJ_INT32 r = c0[i];
                OPJ_INT32 g = c1[i];
                OPJ_INT32 b = c2[i];
@@ -85,10 +110,69 @@ void opj_mct_encode(
                c2[i] = v;
        }
 }
+#else
+void opj_mct_encode(
+               OPJ_INT32* restrict c0,
+               OPJ_INT32* restrict c1,
+               OPJ_INT32* restrict c2,
+               OPJ_UINT32 n)
+{
+       OPJ_SIZE_T i;
+       const OPJ_SIZE_T len = n;
+       
+       for(i = 0; i < len; ++i) {
+               OPJ_INT32 r = c0[i];
+               OPJ_INT32 g = c1[i];
+               OPJ_INT32 b = c2[i];
+               OPJ_INT32 y = (r + (g * 2) + b) >> 2;
+               OPJ_INT32 u = b - g;
+               OPJ_INT32 v = r - g;
+               c0[i] = y;
+               c1[i] = u;
+               c2[i] = v;
+       }
+}
+#endif
 
 /* <summary> */
 /* Inverse reversible MCT. */
 /* </summary> */
+#ifdef __SSE2__
+void opj_mct_decode(
+               OPJ_INT32* restrict c0,
+               OPJ_INT32* restrict c1,
+               OPJ_INT32* restrict c2,
+               OPJ_UINT32 n)
+{
+       OPJ_SIZE_T i;
+       const OPJ_SIZE_T len = n;
+       
+       for(i = 0; i < (len & ~3U); i += 4) {
+               __m128i r, g, b;
+               __m128i y = _mm_load_si128((const __m128i *)&(c0[i]));
+               __m128i u = _mm_load_si128((const __m128i *)&(c1[i]));
+               __m128i v = _mm_load_si128((const __m128i *)&(c2[i]));
+               g = y;
+               g = _mm_sub_epi32(g, _mm_srai_epi32(_mm_add_epi32(u, v), 2));
+               r = _mm_add_epi32(v, g);
+               b = _mm_add_epi32(u, g);
+               _mm_store_si128((__m128i *)&(c0[i]), r);
+               _mm_store_si128((__m128i *)&(c1[i]), g);
+               _mm_store_si128((__m128i *)&(c2[i]), b);
+       }
+       for (; i < len; ++i) {
+               OPJ_INT32 y = c0[i];
+               OPJ_INT32 u = c1[i];
+               OPJ_INT32 v = c2[i];
+               OPJ_INT32 g = y - ((u + v) >> 2);
+               OPJ_INT32 r = v + g;
+               OPJ_INT32 b = u + g;
+               c0[i] = r;
+               c1[i] = g;
+               c2[i] = b;
+       }
+}
+#else
 void opj_mct_decode(
                OPJ_INT32* restrict c0,
                OPJ_INT32* restrict c1, 
@@ -108,6 +192,7 @@ void opj_mct_decode(
                c2[i] = b;
        }
 }
+#endif
 
 /* <summary> */
 /* Get norm of basis function of reversible MCT. */
@@ -119,6 +204,148 @@ OPJ_FLOAT64 opj_mct_getnorm(OPJ_UINT32 compno) {
 /* <summary> */
 /* Foward irreversible MCT. */
 /* </summary> */
+#ifdef __SSE4_1__
+void opj_mct_encode_real(
+                                                                                                OPJ_INT32* restrict c0,
+                                                                                                OPJ_INT32* restrict c1,
+                                                                                                OPJ_INT32* restrict c2,
+                                                                                                OPJ_UINT32 n)
+{
+       OPJ_SIZE_T i;
+       const OPJ_SIZE_T len = n;
+       
+       const __m128i ry = _mm_set1_epi32(2449);
+       const __m128i gy = _mm_set1_epi32(4809);
+       const __m128i by = _mm_set1_epi32(934);
+       const __m128i ru = _mm_set1_epi32(1382);
+       const __m128i gu = _mm_set1_epi32(2714);
+       /* const __m128i bu = _mm_set1_epi32(4096); */
+       /* const __m128i rv = _mm_set1_epi32(4096); */
+       const __m128i gv = _mm_set1_epi32(3430);
+       const __m128i bv = _mm_set1_epi32(666);
+       const __m128i mulround = _mm_shuffle_epi32(_mm_cvtsi32_si128(4096), _MM_SHUFFLE(1, 0, 1, 0));
+       
+       for(i = 0; i < (len & ~3U); i += 4) {
+               __m128i lo, hi;
+               __m128i y, u, v;
+               __m128i r = _mm_load_si128((const __m128i *)&(c0[i]));
+               __m128i g = _mm_load_si128((const __m128i *)&(c1[i]));
+               __m128i b = _mm_load_si128((const __m128i *)&(c2[i]));
+               
+               lo = r;
+               hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1));
+               lo = _mm_mul_epi32(lo, ry);
+               hi = _mm_mul_epi32(hi, ry);
+               lo = _mm_add_epi64(lo, mulround);
+               hi = _mm_add_epi64(hi, mulround);
+               lo = _mm_srli_epi64(lo, 13);
+               hi = _mm_slli_epi64(hi, 32-13);
+               y = _mm_blend_epi16(lo, hi, 0xCC);
+               
+               lo = g;
+               hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1));
+               lo = _mm_mul_epi32(lo, gy);
+               hi = _mm_mul_epi32(hi, gy);
+               lo = _mm_add_epi64(lo, mulround);
+               hi = _mm_add_epi64(hi, mulround);
+               lo = _mm_srli_epi64(lo, 13);
+               hi = _mm_slli_epi64(hi, 32-13);
+               y = _mm_add_epi32(y, _mm_blend_epi16(lo, hi, 0xCC));
+               
+               lo = b;
+               hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1));
+               lo = _mm_mul_epi32(lo, by);
+               hi = _mm_mul_epi32(hi, by);
+               lo = _mm_add_epi64(lo, mulround);
+               hi = _mm_add_epi64(hi, mulround);
+               lo = _mm_srli_epi64(lo, 13);
+               hi = _mm_slli_epi64(hi, 32-13);
+               y = _mm_add_epi32(y, _mm_blend_epi16(lo, hi, 0xCC));
+               _mm_store_si128((__m128i *)&(c0[i]), y);
+               
+               /*lo = b;
+               hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1));
+               lo = _mm_mul_epi32(lo, mulround);
+               hi = _mm_mul_epi32(hi, mulround);*/
+               lo = _mm_cvtepi32_epi64(_mm_shuffle_epi32(b, _MM_SHUFFLE(3, 2, 2, 0)));
+               hi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(b, _MM_SHUFFLE(3, 2, 3, 1)));
+               lo = _mm_slli_epi64(lo, 12);
+               hi = _mm_slli_epi64(hi, 12);
+               lo = _mm_add_epi64(lo, mulround);
+               hi = _mm_add_epi64(hi, mulround);
+               lo = _mm_srli_epi64(lo, 13);
+               hi = _mm_slli_epi64(hi, 32-13);
+               u = _mm_blend_epi16(lo, hi, 0xCC);
+               
+               lo = r;
+               hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1));
+               lo = _mm_mul_epi32(lo, ru);
+               hi = _mm_mul_epi32(hi, ru);
+               lo = _mm_add_epi64(lo, mulround);
+               hi = _mm_add_epi64(hi, mulround);
+               lo = _mm_srli_epi64(lo, 13);
+               hi = _mm_slli_epi64(hi, 32-13);
+               u = _mm_sub_epi32(u, _mm_blend_epi16(lo, hi, 0xCC));
+               
+               lo = g;
+               hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1));
+               lo = _mm_mul_epi32(lo, gu);
+               hi = _mm_mul_epi32(hi, gu);
+               lo = _mm_add_epi64(lo, mulround);
+               hi = _mm_add_epi64(hi, mulround);
+               lo = _mm_srli_epi64(lo, 13);
+               hi = _mm_slli_epi64(hi, 32-13);
+               u = _mm_sub_epi32(u, _mm_blend_epi16(lo, hi, 0xCC));
+               _mm_store_si128((__m128i *)&(c1[i]), u);
+               
+               /*lo = r;
+               hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1));
+               lo = _mm_mul_epi32(lo, mulround);
+               hi = _mm_mul_epi32(hi, mulround);*/
+               lo = _mm_cvtepi32_epi64(_mm_shuffle_epi32(r, _MM_SHUFFLE(3, 2, 2, 0)));
+               hi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(r, _MM_SHUFFLE(3, 2, 3, 1)));
+               lo = _mm_slli_epi64(lo, 12);
+               hi = _mm_slli_epi64(hi, 12);
+               lo = _mm_add_epi64(lo, mulround);
+               hi = _mm_add_epi64(hi, mulround);
+               lo = _mm_srli_epi64(lo, 13);
+               hi = _mm_slli_epi64(hi, 32-13);
+               v = _mm_blend_epi16(lo, hi, 0xCC);
+               
+               lo = g;
+               hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1));
+               lo = _mm_mul_epi32(lo, gv);
+               hi = _mm_mul_epi32(hi, gv);
+               lo = _mm_add_epi64(lo, mulround);
+               hi = _mm_add_epi64(hi, mulround);
+               lo = _mm_srli_epi64(lo, 13);
+               hi = _mm_slli_epi64(hi, 32-13);
+               v = _mm_sub_epi32(v, _mm_blend_epi16(lo, hi, 0xCC));
+               
+               lo = b;
+               hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1));
+               lo = _mm_mul_epi32(lo, bv);
+               hi = _mm_mul_epi32(hi, bv);
+               lo = _mm_add_epi64(lo, mulround);
+               hi = _mm_add_epi64(hi, mulround);
+               lo = _mm_srli_epi64(lo, 13);
+               hi = _mm_slli_epi64(hi, 32-13);
+               v = _mm_sub_epi32(v, _mm_blend_epi16(lo, hi, 0xCC));
+               _mm_store_si128((__m128i *)&(c2[i]), v);
+       }
+       for(; i < len; ++i) {
+               OPJ_INT32 r = c0[i];
+               OPJ_INT32 g = c1[i];
+               OPJ_INT32 b = c2[i];
+               OPJ_INT32 y =  opj_int_fix_mul(r, 2449) + opj_int_fix_mul(g, 4809) + opj_int_fix_mul(b, 934);
+               OPJ_INT32 u = -opj_int_fix_mul(r, 1382) - opj_int_fix_mul(g, 2714) + opj_int_fix_mul(b, 4096);
+               OPJ_INT32 v =  opj_int_fix_mul(r, 4096) - opj_int_fix_mul(g, 3430) - opj_int_fix_mul(b, 666);
+               c0[i] = y;
+               c1[i] = u;
+               c2[i] = v;
+       }
+}
+#else
 void opj_mct_encode_real(
                OPJ_INT32* restrict c0,
                OPJ_INT32* restrict c1,
@@ -138,6 +365,7 @@ void opj_mct_encode_real(
                c2[i] = v;
        }
 }
+#endif
 
 /* <summary> */
 /* Inverse irreversible MCT. */
index b1e1c29..4a8e75c 100644 (file)
@@ -76,10 +76,36 @@ Most compilers implement their own version of this keyword ...
        #define OPJ_DEPRECATED(func) func
 #endif
 
-// PDFium doesn't need to export any of these methods.
-#define OPJ_API
-#define OPJ_LOCAL
-#define OPJ_CALLCONV
+#if defined(OPJ_STATIC) || !defined(_WIN32)
+/* http://gcc.gnu.org/wiki/Visibility */
+#      if __GNUC__ >= 4
+#              if defined(OPJ_STATIC) /* static library uses "hidden" */
+#                      define OPJ_API    __attribute__ ((visibility ("hidden")))
+#              else
+#                      define OPJ_API    __attribute__ ((visibility ("default")))
+#              endif
+#              define OPJ_LOCAL  __attribute__ ((visibility ("hidden")))
+#      else
+#              define OPJ_API
+#              define OPJ_LOCAL
+#      endif
+#      define OPJ_CALLCONV
+#else
+#      define OPJ_CALLCONV __stdcall
+/*
+The following ifdef block is the standard way of creating macros which make exporting 
+from a DLL simpler. All files within this DLL are compiled with the OPJ_EXPORTS
+symbol defined on the command line. this symbol should not be defined on any project
+that uses this DLL. This way any other project whose source files include this file see 
+OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols
+defined with this macro as being exported.
+*/
+#      if defined(OPJ_EXPORTS) || defined(DLL_EXPORT)
+#              define OPJ_API __declspec(dllexport)
+#      else
+#              define OPJ_API __declspec(dllimport)
+#      endif /* OPJ_EXPORTS */
+#endif /* !OPJ_STATIC || !_WIN32 */
 
 typedef int OPJ_BOOL;
 #define OPJ_TRUE 1
index d9238b1..e3d4686 100644 (file)
@@ -136,6 +136,10 @@ static INLINE long lrintf(float f){
 }
 #endif
 
+#if defined(_MSC_VER) && (_MSC_VER < 1400)
+       #define vsnprintf _vsnprintf
+#endif
+
 #include "opj_inttypes.h"
 #include "opj_clock.h"
 #include "opj_malloc.h"
index dc89895..4e29946 100644 (file)
@@ -82,6 +82,15 @@ static INLINE OPJ_UINT32 opj_uint_max(OPJ_UINT32  a, OPJ_UINT32  b) {
 }
 
 /**
+ Get the saturated sum of two unsigned integers
+ @return Returns saturated sum of a+b
+ */
+static INLINE OPJ_UINT32 opj_uint_adds(OPJ_UINT32 a, OPJ_UINT32 b) {
+       OPJ_UINT64 sum = (OPJ_UINT64)a + (OPJ_UINT64)b;
+       return -(OPJ_UINT32)(sum >> 32) | (OPJ_UINT32)sum;
+}
+
+/**
 Clamp an integer inside an interval
 @return
 <ul>
@@ -108,7 +117,7 @@ Divide an integer and round upwards
 @return Returns a divided by b
 */
 static INLINE OPJ_INT32 opj_int_ceildiv(OPJ_INT32 a, OPJ_INT32 b) {
-  assert(b);
+       assert(b);
        return (a + b - 1) / b;
 }
 
@@ -117,6 +126,7 @@ Divide an integer and round upwards
 @return Returns a divided by b
 */
 static INLINE OPJ_UINT32  opj_uint_ceildiv(OPJ_UINT32  a, OPJ_UINT32  b) {
+       assert(b);
        return (a + b - 1) / b;
 }
 
@@ -165,9 +175,19 @@ Multiply two fixed-precision rational numbers.
 @return Returns a * b
 */
 static INLINE OPJ_INT32 opj_int_fix_mul(OPJ_INT32 a, OPJ_INT32 b) {
-    OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ;
-    temp += temp & 4096;
-    return (OPJ_INT32) (temp >> 13) ;
+       OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ;
+       temp += 4096;
+       assert((temp >> 13) <= (OPJ_INT64)0x7FFFFFFF);
+       assert((temp >> 13) >= (-(OPJ_INT64)0x7FFFFFFF - (OPJ_INT64)1));
+       return (OPJ_INT32) (temp >> 13);
+}
+
+static INLINE OPJ_INT32 opj_int_fix_mul_t1(OPJ_INT32 a, OPJ_INT32 b) {
+       OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ;
+       temp += 4096;
+       assert((temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) <= (OPJ_INT64)0x7FFFFFFF);
+       assert((temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) >= (-(OPJ_INT64)0x7FFFFFFF - (OPJ_INT64)1));
+       return (OPJ_INT32) (temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) ;
 }
 
 /* ----------------------------------------------------------------------- */
index 65ff626..393a1e5 100644 (file)
@@ -693,6 +693,9 @@ void opj_get_all_encoding_parameters(   const opj_image_t *p_image,
        /* position in x and y of tile*/
        OPJ_UINT32 p, q;
 
+       /* non-corrected (in regard to image offset) tile offset */
+       OPJ_UINT32 l_tx0, l_ty0;
+
        /* preconditions in debug*/
        assert(p_cp != 00);
        assert(p_image != 00);
@@ -708,10 +711,12 @@ void opj_get_all_encoding_parameters(   const opj_image_t *p_image,
        q = tileno / p_cp->tw;
 
        /* here calculation of tx0, tx1, ty0, ty1, maxprec, l_dx and l_dy */
-       *p_tx0 = opj_int_max((OPJ_INT32)(p_cp->tx0 + p * p_cp->tdx), (OPJ_INT32)p_image->x0);
-       *p_tx1 = opj_int_min((OPJ_INT32)(p_cp->tx0 + (p + 1) * p_cp->tdx), (OPJ_INT32)p_image->x1);
-       *p_ty0 = opj_int_max((OPJ_INT32)(p_cp->ty0 + q * p_cp->tdy), (OPJ_INT32)p_image->y0);
-       *p_ty1 = opj_int_min((OPJ_INT32)(p_cp->ty0 + (q + 1) * p_cp->tdy), (OPJ_INT32)p_image->y1);
+       l_tx0 = p_cp->tx0 + p * p_cp->tdx; /* can't be greater than p_image->x1 so won't overflow */
+       *p_tx0 = (OPJ_INT32)opj_uint_max(l_tx0, p_image->x0);
+       *p_tx1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_tx0, p_cp->tdx), p_image->x1);
+       l_ty0 = p_cp->ty0 + q * p_cp->tdy; /* can't be greater than p_image->y1 so won't overflow */
+       *p_ty0 = (OPJ_INT32)opj_uint_max(l_ty0, p_image->y0);
+       *p_ty1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_ty0, p_cp->tdy), p_image->y1);
 
        /* max precision and resolution is 0 (can only grow)*/
        *p_max_prec = 0;
index 11b72a3..8cb230f 100644 (file)
@@ -265,7 +265,8 @@ static OPJ_FLOAT64 opj_t1_getwmsedec(
                OPJ_UINT32 qmfbid,
                OPJ_FLOAT64 stepsize,
                OPJ_UINT32 numcomps,
-               const OPJ_FLOAT64 * mct_norms);
+               const OPJ_FLOAT64 * mct_norms,
+               OPJ_UINT32 mct_numcomps);
 
 static void opj_t1_encode_cblk( opj_t1_t *t1,
                                 opj_tcd_cblk_enc_t* cblk,
@@ -277,7 +278,8 @@ static void opj_t1_encode_cblk( opj_t1_t *t1,
                                 OPJ_UINT32 cblksty,
                                 OPJ_UINT32 numcomps,
                                 opj_tcd_tile_t * tile,
-                                const OPJ_FLOAT64 * mct_norms);
+                                const OPJ_FLOAT64 * mct_norms,
+                                OPJ_UINT32 mct_numcomps);
 
 /**
 Decode 1 code-block
@@ -1137,12 +1139,13 @@ static OPJ_FLOAT64 opj_t1_getwmsedec(
                OPJ_UINT32 qmfbid,
                OPJ_FLOAT64 stepsize,
                OPJ_UINT32 numcomps,
-               const OPJ_FLOAT64 * mct_norms)
+               const OPJ_FLOAT64 * mct_norms,
+               OPJ_UINT32 mct_numcomps)
 {
        OPJ_FLOAT64 w1 = 1, w2, wmsedec;
-    OPJ_ARG_NOT_USED(numcomps);
+       OPJ_ARG_NOT_USED(numcomps);
 
-       if (mct_norms) {
+       if (mct_norms && (compno < mct_numcomps)) {
                w1 = mct_norms[compno];
        }
 
@@ -1462,7 +1465,8 @@ OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1,
 OPJ_BOOL opj_t1_encode_cblks(   opj_t1_t *t1,
                                 opj_tcd_tile_t *tile,
                                 opj_tcp_t *tcp,
-                                const OPJ_FLOAT64 * mct_norms
+                                const OPJ_FLOAT64 * mct_norms,
+                                OPJ_UINT32 mct_numcomps
                                 )
 {
        OPJ_UINT32 compno, resno, bandno, precno, cblkno;
@@ -1530,9 +1534,9 @@ OPJ_BOOL opj_t1_encode_cblks(   opj_t1_t *t1,
                                                                for (i = 0; i < cblk_w; ++i) {
                                                                        OPJ_INT32 tmp = tiledp[tileIndex];
                                                                        tiledp[tileIndex] =
-                                                                               opj_int_fix_mul(
+                                                                               opj_int_fix_mul_t1(
                                                                                tmp,
-                                                                               bandconst) >> (11 - T1_NMSEDEC_FRACBITS);
+                                                                               bandconst);
                                                                        tileIndex++;
                                                                }
                                                                tileIndex += tileLineAdvance;
@@ -1550,7 +1554,8 @@ OPJ_BOOL opj_t1_encode_cblks(   opj_t1_t *t1,
                                                                tccp->cblksty,
                                                                tile->numcomps,
                                                                tile,
-                                                               mct_norms);
+                                                               mct_norms,
+                                                               mct_numcomps);
 
                                        } /* cblkno */
                                } /* precno */
@@ -1571,7 +1576,8 @@ void opj_t1_encode_cblk(opj_t1_t *t1,
                         OPJ_UINT32 cblksty,
                         OPJ_UINT32 numcomps,
                         opj_tcd_tile_t * tile,
-                        const OPJ_FLOAT64 * mct_norms)
+                        const OPJ_FLOAT64 * mct_norms,
+                        OPJ_UINT32 mct_numcomps)
 {
        OPJ_FLOAT64 cumwmsedec = 0.0;
 
@@ -1626,7 +1632,7 @@ void opj_t1_encode_cblk(opj_t1_t *t1,
                }
 
                /* fixed_quality */
-               tempwmsedec = opj_t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps,mct_norms) ;
+               tempwmsedec = opj_t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps,mct_norms, mct_numcomps) ;
                cumwmsedec += tempwmsedec;
                tile->distotile += tempwmsedec;
 
index e1d41ed..3bc0ad9 100644 (file)
@@ -126,11 +126,13 @@ Encode the code-blocks of a tile
 @param tile The tile to encode
 @param tcp Tile coding parameters
 @param mct_norms  FIXME DOC
+@param mct_numcomps Number of components used for MCT
 */
 OPJ_BOOL opj_t1_encode_cblks(   opj_t1_t *t1,
                                 opj_tcd_tile_t *tile,
                                 opj_tcp_t *tcp,
-                                const OPJ_FLOAT64 * mct_norms);
+                                const OPJ_FLOAT64 * mct_norms,
+                                OPJ_UINT32 mct_numcomps);
 
 /**
 Decode the code-blocks of a tile
index d0d63d2..6f0ac91 100644 (file)
@@ -388,13 +388,13 @@ OPJ_BOOL opj_t2_decode_packets( opj_t2_t *p_t2,
                  * and no l_img_comp->resno_decoded are computed
                  */
                 OPJ_BOOL* first_pass_failed = NULL;
-
+                                       
                 if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) {
                     /* TODO ADE : add an error */
                     opj_pi_destroy(l_pi, l_nb_pocs);
                     return OPJ_FALSE;
                 }
-
+                                       
                 first_pass_failed = (OPJ_BOOL*)opj_malloc(l_image->numcomps * sizeof(OPJ_BOOL));
                 if (!first_pass_failed)
                 {
index 6c04f3d..f623120 100644 (file)
@@ -120,11 +120,16 @@ static OPJ_BOOL opj_tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_blo
 static void opj_tcd_code_block_dec_deallocate (opj_tcd_precinct_t * p_precinct);
 
 /**
- * Allocates memory for an encoding code block.
+ * Allocates memory for an encoding code block (but not data).
  */
 static OPJ_BOOL opj_tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_block);
 
 /**
+ * Allocates data for an encoding code block
+ */
+static OPJ_BOOL opj_tcd_code_block_enc_allocate_data (opj_tcd_cblk_enc_t * p_code_block);
+
+/**
  * Deallocates the encoding data of the given precinct.
  */
 static void opj_tcd_code_block_enc_deallocate (opj_tcd_precinct_t * p_precinct);
@@ -670,6 +675,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
        OPJ_UINT32 l_pdx, l_pdy;
        OPJ_UINT32 l_gain;
        OPJ_INT32 l_x0b, l_y0b;
+       OPJ_UINT32 l_tx0, l_ty0;
        /* extent of precincts , top left, bottom right**/
        OPJ_INT32 l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end, l_br_prc_y_end;
        /* number of precinct for a resolution */
@@ -682,7 +688,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
        OPJ_UINT32 l_nb_code_blocks_size;
        /* size of data for a tile */
        OPJ_UINT32 l_data_size;
-
+       
        l_cp = p_tcd->cp;
        l_tcp = &(l_cp->tcps[p_tile_no]);
        l_tile = p_tcd->tcd_image->tiles;
@@ -690,23 +696,26 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
        l_tilec = l_tile->comps;
        l_image = p_tcd->image;
        l_image_comp = p_tcd->image->comps;
-
+       
        p = p_tile_no % l_cp->tw;       /* tile coordinates */
        q = p_tile_no / l_cp->tw;
        /*fprintf(stderr, "Tile coordinate = %d,%d\n", p, q);*/
-
+       
        /* 4 borders of the tile rescale on the image if necessary */
-       l_tile->x0 = opj_int_max((OPJ_INT32)(l_cp->tx0 + p * l_cp->tdx), (OPJ_INT32)l_image->x0);
-       l_tile->y0 = opj_int_max((OPJ_INT32)(l_cp->ty0 + q * l_cp->tdy), (OPJ_INT32)l_image->y0);
-       l_tile->x1 = opj_int_min((OPJ_INT32)(l_cp->tx0 + (p + 1) * l_cp->tdx), (OPJ_INT32)l_image->x1);
-       l_tile->y1 = opj_int_min((OPJ_INT32)(l_cp->ty0 + (q + 1) * l_cp->tdy), (OPJ_INT32)l_image->y1);
+       l_tx0 = l_cp->tx0 + p * l_cp->tdx; /* can't be greater than l_image->x1 so won't overflow */
+       l_tile->x0 = (OPJ_INT32)opj_uint_max(l_tx0, l_image->x0);
+       l_tile->x1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_tx0, l_cp->tdx), l_image->x1);
+       l_ty0 = l_cp->ty0 + q * l_cp->tdy; /* can't be greater than l_image->y1 so won't overflow */
+       l_tile->y0 = (OPJ_INT32)opj_uint_max(l_ty0, l_image->y0);
+       l_tile->y1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_ty0, l_cp->tdy), l_image->y1);
+
        /* testcase 1888.pdf.asan.35.988 */
        if (l_tccp->numresolutions == 0) {
                fprintf(stderr, "tiles require at least one resolution\n");
                return OPJ_FALSE;
        }
        /*fprintf(stderr, "Tile border = %d,%d,%d,%d\n", l_tile->x0, l_tile->y0,l_tile->x1,l_tile->y1);*/
-
+       
        /*tile->numcomps = image->numcomps; */
        for (compno = 0; compno < l_tile->numcomps; ++compno) {
                /*fprintf(stderr, "compno = %d/%d\n", compno, l_tile->numcomps);*/
@@ -717,7 +726,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                l_tilec->x1 = opj_int_ceildiv(l_tile->x1, (OPJ_INT32)l_image_comp->dx);
                l_tilec->y1 = opj_int_ceildiv(l_tile->y1, (OPJ_INT32)l_image_comp->dy);
                /*fprintf(stderr, "\tTile compo border = %d,%d,%d,%d\n", l_tilec->x0, l_tilec->y0,l_tilec->x1,l_tilec->y1);*/
-
+               
                /* compute l_data_size with overflow check */
                l_data_size = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0);
                if ((((OPJ_UINT32)-1) / l_data_size) < (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0)) {
@@ -725,7 +734,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                        return OPJ_FALSE;
                }
                l_data_size = l_data_size * (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0);
-
+               
                if ((((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(OPJ_UINT32)) < l_data_size) {
                        /* TODO event */
                        return OPJ_FALSE;
@@ -738,14 +747,14 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                else {
                        l_tilec->minimum_num_resolutions = l_tccp->numresolutions - l_cp->m_specific_param.m_dec.m_reduce;
                }
-
+               
                l_tilec->data_size_needed = l_data_size;
                if (p_tcd->m_is_decoder && !opj_alloc_tile_component_data(l_tilec)) {
                        return OPJ_FALSE;
                }
-
+               
                l_data_size = l_tilec->numresolutions * (OPJ_UINT32)sizeof(opj_tcd_resolution_t);
-
+               
                if (l_tilec->resolutions == 00) {
                        l_tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(l_data_size);
                        if (! l_tilec->resolutions ) {
@@ -770,7 +779,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                        memset(((OPJ_BYTE*) l_tilec->resolutions)+l_tilec->resolutions_size,0,l_data_size - l_tilec->resolutions_size);
                        l_tilec->resolutions_size = l_data_size;
                }
-
+               
                l_level_no = l_tilec->numresolutions - 1;
                l_res = l_tilec->resolutions;
                l_step_size = l_tccp->stepsizes;
@@ -781,13 +790,13 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                        l_gain_ptr  = &opj_dwt_getgain;
                }
                /*fprintf(stderr, "\tlevel_no=%d\n",l_level_no);*/
-
+               
                for (resno = 0; resno < l_tilec->numresolutions; ++resno) {
                        /*fprintf(stderr, "\t\tresno = %d/%d\n", resno, l_tilec->numresolutions);*/
                        OPJ_INT32 tlcbgxstart, tlcbgystart /*, brcbgxend, brcbgyend*/;
                        OPJ_UINT32 cbgwidthexpn, cbgheightexpn;
                        OPJ_UINT32 cblkwidthexpn, cblkheightexpn;
-
+                       
                        /* border for each resolution level (global) */
                        l_res->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no);
                        l_res->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no);
@@ -804,11 +813,11 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                        l_br_prc_x_end = opj_int_ceildivpow2(l_res->x1, (OPJ_INT32)l_pdx) << l_pdx;
                        l_br_prc_y_end = opj_int_ceildivpow2(l_res->y1, (OPJ_INT32)l_pdy) << l_pdy;
                        /*fprintf(stderr, "\t\t\tprc_x_start=%d, prc_y_start=%d, br_prc_x_end=%d, br_prc_y_end=%d \n", l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end ,l_br_prc_y_end );*/
-
+                       
                        l_res->pw = (l_res->x0 == l_res->x1) ? 0 : (OPJ_UINT32)((l_br_prc_x_end - l_tl_prc_x_start) >> l_pdx);
                        l_res->ph = (l_res->y0 == l_res->y1) ? 0 : (OPJ_UINT32)((l_br_prc_y_end - l_tl_prc_y_start) >> l_pdy);
                        /*fprintf(stderr, "\t\t\tres_pw=%d, res_ph=%d\n", l_res->pw, l_res->ph );*/
-
+                       
                        l_nb_precincts = l_res->pw * l_res->ph;
                        l_nb_precinct_size = l_nb_precincts * (OPJ_UINT32)sizeof(opj_tcd_precinct_t);
                        if (resno == 0) {
@@ -829,15 +838,15 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                                cbgheightexpn = l_pdy - 1;
                                l_res->numbands = 3;
                        }
-
+                       
                        cblkwidthexpn = opj_uint_min(l_tccp->cblkw, cbgwidthexpn);
                        cblkheightexpn = opj_uint_min(l_tccp->cblkh, cbgheightexpn);
                        l_band = l_res->bands;
-
+                       
                        for (bandno = 0; bandno < l_res->numbands; ++bandno) {
                                OPJ_INT32 numbps;
                                /*fprintf(stderr, "\t\t\tband_no=%d/%d\n", bandno, l_res->numbands );*/
-
+                               
                                if (resno == 0) {
                                        l_band->bandno = 0 ;
                                        l_band->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no);
@@ -857,13 +866,13 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                                        l_band->x1 = opj_int_ceildivpow2(l_tilec->x1 - (1 << l_level_no) * l_x0b, (OPJ_INT32)(l_level_no + 1));
                                        l_band->y1 = opj_int_ceildivpow2(l_tilec->y1 - (1 << l_level_no) * l_y0b, (OPJ_INT32)(l_level_no + 1));
                                }
-
+                               
                                /** avoid an if with storing function pointer */
                                l_gain = (*l_gain_ptr) (l_band->bandno);
                                numbps = (OPJ_INT32)(l_image_comp->prec + l_gain);
                                l_band->stepsize = (OPJ_FLOAT32)(((1.0 + l_step_size->mant / 2048.0) * pow(2.0, (OPJ_INT32) (numbps - l_step_size->expn)))) * fraction;
                                l_band->numbps = l_step_size->expn + (OPJ_INT32)l_tccp->numgbits - 1;      /* WHY -1 ? */
-
+                               
                                if (! l_band->precincts) {
                                        l_band->precincts = (opj_tcd_precinct_t *) opj_malloc( /*3 * */ l_nb_precinct_size);
                                        if (! l_band->precincts) {
@@ -874,7 +883,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                                        l_band->precincts_data_size = l_nb_precinct_size;
                                }
                                else if (l_band->precincts_data_size < l_nb_precinct_size) {
-
+                                       
                                        opj_tcd_precinct_t * new_precincts = (opj_tcd_precinct_t *) opj_realloc(l_band->precincts,/*3 * */ l_nb_precinct_size);
                                        if (! new_precincts) {
                                                /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle band precints\n");                                                                    */
@@ -889,7 +898,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                                        memset(((OPJ_BYTE *) l_band->precincts) + l_band->precincts_data_size,0,l_nb_precinct_size - l_band->precincts_data_size);
                                        l_band->precincts_data_size = l_nb_precinct_size;
                                }
-
+                               
                                l_current_precinct = l_band->precincts;
                                for (precno = 0; precno < l_nb_precincts; ++precno) {
                                        OPJ_INT32 tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend;
@@ -899,16 +908,16 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                                        OPJ_INT32 cbgyend = cbgystart + (1 << cbgheightexpn);
                                        /*fprintf(stderr, "\t precno=%d; bandno=%d, resno=%d; compno=%d\n", precno, bandno , resno, compno);*/
                                        /*fprintf(stderr, "\t tlcbgxstart(=%d) + (precno(=%d) percent res->pw(=%d)) * (1 << cbgwidthexpn(=%d)) \n",tlcbgxstart,precno,l_res->pw,cbgwidthexpn);*/
-
+                                       
                                        /* precinct size (global) */
                                        /*fprintf(stderr, "\t cbgxstart=%d, l_band->x0 = %d \n",cbgxstart, l_band->x0);*/
-
+                                       
                                        l_current_precinct->x0 = opj_int_max(cbgxstart, l_band->x0);
                                        l_current_precinct->y0 = opj_int_max(cbgystart, l_band->y0);
                                        l_current_precinct->x1 = opj_int_min(cbgxend, l_band->x1);
                                        l_current_precinct->y1 = opj_int_min(cbgyend, l_band->y1);
                                        /*fprintf(stderr, "\t prc_x0=%d; prc_y0=%d, prc_x1=%d; prc_y1=%d\n",l_current_precinct->x0, l_current_precinct->y0 ,l_current_precinct->x1, l_current_precinct->y1);*/
-
+                                       
                                        tlcblkxstart = opj_int_floordivpow2(l_current_precinct->x0, (OPJ_INT32)cblkwidthexpn) << cblkwidthexpn;
                                        /*fprintf(stderr, "\t tlcblkxstart =%d\n",tlcblkxstart );*/
                                        tlcblkystart = opj_int_floordivpow2(l_current_precinct->y0, (OPJ_INT32)cblkheightexpn) << cblkheightexpn;
@@ -919,20 +928,20 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                                        /*fprintf(stderr, "\t brcblkyend =%d\n",brcblkyend );*/
                                        l_current_precinct->cw = (OPJ_UINT32)((brcblkxend - tlcblkxstart) >> cblkwidthexpn);
                                        l_current_precinct->ch = (OPJ_UINT32)((brcblkyend - tlcblkystart) >> cblkheightexpn);
-
+                                       
                                        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);      */
                                        l_nb_code_blocks_size = l_nb_code_blocks * (OPJ_UINT32)sizeof_block;
-
+                                       
                                        if (! l_current_precinct->cblks.blocks) {
                                                l_current_precinct->cblks.blocks = opj_malloc(l_nb_code_blocks_size);
                                                if (! l_current_precinct->cblks.blocks ) {
                                                        return OPJ_FALSE;
                                                }
                                                /*fprintf(stderr, "\t\t\t\tAllocate cblks of a precinct (opj_tcd_cblk_dec_t): %d\n",l_nb_code_blocks_size);*/
-
+                                               
                                                memset(l_current_precinct->cblks.blocks,0,l_nb_code_blocks_size);
-
+                                               
                                                l_current_precinct->block_size = l_nb_code_blocks_size;
                                        }
                                        else if (l_nb_code_blocks_size > l_current_precinct->block_size) {
@@ -947,14 +956,14 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                                                }
                                                l_current_precinct->cblks.blocks = new_blocks;
                                                /*fprintf(stderr, "\t\t\t\tReallocate cblks of a precinct (opj_tcd_cblk_dec_t): from %d to %d\n",l_current_precinct->block_size, l_nb_code_blocks_size);     */
-
+                                               
                                                memset(((OPJ_BYTE *) l_current_precinct->cblks.blocks) + l_current_precinct->block_size
                                                                         ,0
                                                                         ,l_nb_code_blocks_size - l_current_precinct->block_size);
-
+                                               
                                                l_current_precinct->block_size = l_nb_code_blocks_size;
                                        }
-
+                                       
                                        if (! l_current_precinct->incltree) {
                                                l_current_precinct->incltree = opj_tgt_create(l_current_precinct->cw,
                                                                                                                                                                                                                                        l_current_precinct->ch);
@@ -992,10 +1001,10 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                                                OPJ_INT32 cblkystart = tlcblkystart + (OPJ_INT32)(cblkno / l_current_precinct->cw) * (1 << cblkheightexpn);
                                                OPJ_INT32 cblkxend = cblkxstart + (1 << cblkwidthexpn);
                                                OPJ_INT32 cblkyend = cblkystart + (1 << cblkheightexpn);
-
+                                               
                                                if (isEncoder) {
                                                        opj_tcd_cblk_enc_t* l_code_block = l_current_precinct->cblks.enc + cblkno;
-
+                                                       
                                                        if (! opj_tcd_code_block_enc_allocate(l_code_block)) {
                                                                return OPJ_FALSE;
                                                        }
@@ -1004,9 +1013,13 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                                                        l_code_block->y0 = opj_int_max(cblkystart, l_current_precinct->y0);
                                                        l_code_block->x1 = opj_int_min(cblkxend, l_current_precinct->x1);
                                                        l_code_block->y1 = opj_int_min(cblkyend, l_current_precinct->y1);
+                                                       
+                                                       if (! opj_tcd_code_block_enc_allocate_data(l_code_block)) {
+                                                               return OPJ_FALSE;
+                                                       }
                                                } else {
                                                        opj_tcd_cblk_dec_t* l_code_block = l_current_precinct->cblks.dec + cblkno;
-
+                                                       
                                                        if (! opj_tcd_code_block_dec_allocate(l_code_block)) {
                                                                return OPJ_FALSE;
                                                        }
@@ -1043,39 +1056,56 @@ OPJ_BOOL opj_tcd_init_decode_tile (opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no)
 }
 
 /**
- * Allocates memory for an encoding code block.
+ * Allocates memory for an encoding code block (but not data memory).
  */
-OPJ_BOOL opj_tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_block)
+static OPJ_BOOL opj_tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_block)
 {
-        if (! p_code_block->data) {
-
-                p_code_block->data = (OPJ_BYTE*) opj_malloc(OPJ_J2K_DEFAULT_CBLK_DATA_SIZE*2); /*why +1 ?*/
-                if(! p_code_block->data) {
-                        return OPJ_FALSE;
-                }
-
-                p_code_block->data[0] = 0;
-                p_code_block->data+=1;
-
-                /* no memset since data */
-                p_code_block->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t));
-                if (! p_code_block->layers) {
-                        return OPJ_FALSE;
-                }
-
-                p_code_block->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t));
-                if (! p_code_block->passes) {
-                        return OPJ_FALSE;
-                }
-        }
+       if (! p_code_block->layers) {
+               /* no memset since data */
+               p_code_block->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t));
+               if (! p_code_block->layers) {
+                       return OPJ_FALSE;
+               }
+       }
+       if (! p_code_block->passes) {
+               p_code_block->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t));
+               if (! p_code_block->passes) {
+                       return OPJ_FALSE;
+               }
+       }
+       return OPJ_TRUE;
+}
 
-        return OPJ_TRUE;
+/**
+ * Allocates data memory for an encoding code block.
+ */
+static OPJ_BOOL opj_tcd_code_block_enc_allocate_data (opj_tcd_cblk_enc_t * p_code_block)
+{
+       OPJ_UINT32 l_data_size;
+       
+       l_data_size = (OPJ_UINT32)((p_code_block->x1 - p_code_block->x0) * (p_code_block->y1 - p_code_block->y0) * (OPJ_INT32)sizeof(OPJ_UINT32));
+       
+       if (l_data_size > p_code_block->data_size) {
+               if (p_code_block->data) {
+                       opj_free(p_code_block->data - 1); /* again, why -1 */
+               }
+               p_code_block->data = (OPJ_BYTE*) opj_malloc(l_data_size);
+               if(! p_code_block->data) {
+                       p_code_block->data_size = 0U;
+                       return OPJ_FALSE;
+               }
+               p_code_block->data_size = l_data_size;
+               
+               p_code_block->data[0] = 0;
+               p_code_block->data+=1;   /*why +1 ?*/
+       }
+       return OPJ_TRUE;
 }
 
 /**
  * Allocates memory for a decoding code block.
  */
-OPJ_BOOL opj_tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_block)
+static OPJ_BOOL opj_tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_block)
 {
         if (! p_code_block->data) {
 
@@ -1989,6 +2019,7 @@ OPJ_BOOL opj_tcd_t1_encode ( opj_tcd_t *p_tcd )
 {
         opj_t1_t * l_t1;
         const OPJ_FLOAT64 * l_mct_norms;
+        OPJ_UINT32 l_mct_numcomps = 0U;
         opj_tcp_t * l_tcp = p_tcd->tcp;
 
         l_t1 = opj_t1_create(OPJ_TRUE);
@@ -1997,6 +2028,7 @@ OPJ_BOOL opj_tcd_t1_encode ( opj_tcd_t *p_tcd )
         }
 
         if (l_tcp->mct == 1) {
+                l_mct_numcomps = 3U;
                 /* irreversible encoding */
                 if (l_tcp->tccps->qmfbid == 0) {
                         l_mct_norms = opj_mct_get_mct_norms_real();
@@ -2006,10 +2038,11 @@ OPJ_BOOL opj_tcd_t1_encode ( opj_tcd_t *p_tcd )
                 }
         }
         else {
+                l_mct_numcomps = p_tcd->image->numcomps;
                 l_mct_norms = (const OPJ_FLOAT64 *) (l_tcp->mct_norms);
         }
 
-        if (! opj_t1_encode_cblks(l_t1, p_tcd->tcd_image->tiles , l_tcp, l_mct_norms)) {
+        if (! opj_t1_encode_cblks(l_t1, p_tcd->tcd_image->tiles , l_tcp, l_mct_norms, l_mct_numcomps)) {
         opj_t1_destroy(l_t1);
                 return OPJ_FALSE;
         }
index 3cb38d2..9bef0fe 100644 (file)
@@ -87,15 +87,16 @@ typedef struct opj_tcd_layer {
 FIXME DOC
 */
 typedef struct opj_tcd_cblk_enc {
-       OPJ_BYTE* data;                                 /* Data */
-       opj_tcd_layer_t* layers;                /* layer information */
-       opj_tcd_pass_t* passes;         /* information about the passes */
-       OPJ_INT32 x0, y0, x1, y1;               /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */
+       OPJ_BYTE* data;               /* Data */
+       opj_tcd_layer_t* layers;      /* layer information */
+       opj_tcd_pass_t* passes;       /* information about the passes */
+       OPJ_INT32 x0, y0, x1, y1;     /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */
        OPJ_UINT32 numbps;
        OPJ_UINT32 numlenbits;
-       OPJ_UINT32 numpasses;                   /* number of pass already done for the code-blocks */
-       OPJ_UINT32 numpassesinlayers;   /* number of passes in the layer */
-       OPJ_UINT32 totalpasses;                 /* total number of passes */
+       OPJ_UINT32 data_size;         /* Size of allocated data buffer */
+       OPJ_UINT32 numpasses;         /* number of pass already done for the code-blocks */
+       OPJ_UINT32 numpassesinlayers; /* number of passes in the layer */
+       OPJ_UINT32 totalpasses;       /* total number of passes */
 } opj_tcd_cblk_enc_t;
 
 
@@ -105,7 +106,7 @@ typedef struct opj_tcd_cblk_dec {
        OPJ_INT32 x0, y0, x1, y1;               /* position of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */
        OPJ_UINT32 numbps;
        OPJ_UINT32 numlenbits;
-    OPJ_UINT32 data_max_size;          /* Size of allocated data buffer */
+       OPJ_UINT32 data_max_size;               /* Size of allocated data buffer */
        OPJ_UINT32 data_current_size;   /* Size of used data buffer */
        OPJ_UINT32 numnewpasses;                /* number of pass added to the code-blocks */
        OPJ_UINT32 numsegs;                             /* number of segments */