Upgrade openjpeg to revision 2997.

BUG=457493
R=tsepez@chromium.org

Review URL: https://codereview.chromium.org/960183004
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/bio.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/bio.c
index 5d49580..3ce6492 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/bio.c
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/bio.c
@@ -81,7 +81,7 @@
 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_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_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_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;
 }
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/j2k.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/j2k.c
index 4a1c103..f944ad1 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/j2k.c
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/j2k.c
@@ -1919,7 +1919,7 @@
         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 @@
         }
 
         /* 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 @@
                 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 @@
                 }
 
                 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 @@
         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 @@
                     }
                 }
                 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 @@
         /* 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 @@
 
                 /* 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 @@
         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;
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/jp2.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/jp2.c
index 1830c11..aafbe19 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/jp2.c
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/jp2.c
@@ -706,7 +706,7 @@
 	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 @@
 	}
 
 	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 @@
 {
 	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 @@
 			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 @@
 				/* 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 @@
 		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_UINT32 alpha_count;
 	OPJ_UINT32 color_channels = 0U;
 	OPJ_UINT32 alpha_channel = 0U;
-
+	
 
 	if(!jp2 || !parameters || !image)
 		return OPJ_FALSE;
@@ -1969,7 +1969,7 @@
 	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 @@
 			}
 		}
 		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 @@
 		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));
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/mct.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/mct.c
index 60ee096..a0da099 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/mct.c
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/mct.c
@@ -40,6 +40,12 @@
 #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 @@
 /* <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 @@
 		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 @@
 		c2[i] = b;
 	}
 }
+#endif
 
 /* <summary> */
 /* Get norm of basis function of reversible MCT. */
@@ -119,6 +204,148 @@
 /* <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 @@
 		c2[i] = v;
 	}
 }
+#endif
 
 /* <summary> */
 /* Inverse irreversible MCT. */
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/openjpeg.h b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/openjpeg.h
index b1e1c29..4a8e75c 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/openjpeg.h
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/openjpeg.h
@@ -76,10 +76,36 @@
 	#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
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_includes.h b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_includes.h
index d9238b1..e3d4686 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_includes.h
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_includes.h
@@ -136,6 +136,10 @@
 }
 #endif
 
+#if defined(_MSC_VER) && (_MSC_VER < 1400)
+	#define vsnprintf _vsnprintf
+#endif
+
 #include "opj_inttypes.h"
 #include "opj_clock.h"
 #include "opj_malloc.h"
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_intmath.h b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_intmath.h
index dc89895..4e29946 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_intmath.h
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_intmath.h
@@ -82,6 +82,15 @@
 }
 
 /**
+ 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 @@
 @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 @@
 @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 @@
 @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)) ;
 }
 
 /* ----------------------------------------------------------------------- */
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/pi.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/pi.c
index 65ff626..393a1e5 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/pi.c
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/pi.c
@@ -693,6 +693,9 @@
 	/* 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 @@
 	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;
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.c
index 11b72a33..8cb230f 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.c
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.c
@@ -265,7 +265,8 @@
 		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 @@
                                 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 @@
 		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_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 @@
 								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 @@
 								tccp->cblksty,
 								tile->numcomps,
 								tile,
-								mct_norms);
+								mct_norms,
+								mct_numcomps);
 
 					} /* cblkno */
 				} /* precno */
@@ -1571,7 +1576,8 @@
                         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 @@
 		}
 
 		/* 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;
 
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.h b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.h
index e1d41ed..3bc0ad9 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.h
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.h
@@ -126,11 +126,13 @@
 @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
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t2.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t2.c
index d0d63d2..6f0ac91 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t2.c
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t2.c
@@ -388,13 +388,13 @@
                  * 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)
                 {
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.c
index 6c04f3d..f623120 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.c
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.c
@@ -120,11 +120,16 @@
 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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 			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 @@
 		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 @@
 			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 @@
 			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 @@
 			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 @@
 				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 @@
 					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 @@
 					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 @@
 					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 @@
 					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 @@
 					/*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 @@
 						}
 						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 @@
 						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 @@
 							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 @@
 }
 
 /**
- * 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) {
+	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;
+}
 
-                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;
-                }
-        }
-
-        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_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 @@
         }
 
         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 @@
                 }
         }
         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;
         }
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.h b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.h
index 3cb38d2..9bef0fe 100644
--- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.h
+++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.h
@@ -87,15 +87,16 @@
 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 @@
 	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 */