Merge to M46: upgrade openjpeg to commit# cf352af

BUG=457480,497355
R=tsepez@chromium.org

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

(cherry picked from commit c212b684cb028a5d98e57f711c9eed931b853a44)

Review URL: https://codereview.chromium.org/1416783002 .
diff --git a/core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp b/core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp
index 834623d..80e6290 100644
--- a/core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp
+++ b/core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp
@@ -698,7 +698,7 @@
       new JpxBitMapContext(pJpxModule));
   context->set_context(pJpxModule->CreateDecoder(m_pStreamAcc->GetData(),
                                                  m_pStreamAcc->GetSize(),
-                                                 m_pColorSpace != nullptr));
+                                                 m_pColorSpace == nullptr));
   if (!context->context())
     return;
 
diff --git a/core/src/fxcodec/codec/fx_codec_jpx_opj.cpp b/core/src/fxcodec/codec/fx_codec_jpx_opj.cpp
index 0a5d6ab..6df408d 100644
--- a/core/src/fxcodec/codec/fx_codec_jpx_opj.cpp
+++ b/core/src/fxcodec/codec/fx_codec_jpx_opj.cpp
@@ -655,7 +655,7 @@
 }
 class CJPX_Decoder {
  public:
-  CJPX_Decoder();
+  explicit CJPX_Decoder(bool use_colorspace);
   ~CJPX_Decoder();
   FX_BOOL Init(const unsigned char* src_data, int src_size);
   void GetInfo(FX_DWORD& width,
@@ -671,10 +671,10 @@
   opj_image_t* image;
   opj_codec_t* l_codec;
   opj_stream_t* l_stream;
-  FX_BOOL m_useColorSpace;
+  const bool m_UseColorSpace;
 };
-CJPX_Decoder::CJPX_Decoder()
-    : image(NULL), l_codec(NULL), l_stream(NULL), m_useColorSpace(FALSE) {}
+CJPX_Decoder::CJPX_Decoder(bool use_colorspace)
+    : image(NULL), l_codec(NULL), l_stream(NULL), m_UseColorSpace(use_colorspace) {}
 CJPX_Decoder::~CJPX_Decoder() {
   if (l_codec) {
     opj_destroy_codec(l_codec);
@@ -724,6 +724,8 @@
     image = NULL;
     return FALSE;
   }
+  image->pdfium_use_colorspace = m_UseColorSpace;
+
   if (!parameters.nb_tile_to_decode) {
     if (!opj_set_decode_area(l_codec, image, parameters.DA_x0, parameters.DA_y0,
                              parameters.DA_x1, parameters.DA_y1)) {
@@ -864,8 +866,7 @@
 void* CCodec_JpxModule::CreateDecoder(const uint8_t* src_buf,
                                       FX_DWORD src_size,
                                       FX_BOOL useColorSpace) {
-  CJPX_Decoder* pDecoder = new CJPX_Decoder;
-  pDecoder->m_useColorSpace = useColorSpace;
+  CJPX_Decoder* pDecoder = new CJPX_Decoder(useColorSpace);
   if (!pDecoder->Init(src_buf, src_size)) {
     delete pDecoder;
     return NULL;
diff --git a/third_party/libopenjpeg20/0000-use-colorspace.patch b/third_party/libopenjpeg20/0000-use-colorspace.patch
new file mode 100644
index 0000000..b40692c
--- /dev/null
+++ b/third_party/libopenjpeg20/0000-use-colorspace.patch
@@ -0,0 +1,27 @@
+diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c
+index 8bf60f6..47f83a1 100644
+--- a/third_party/libopenjpeg20/jp2.c
++++ b/third_party/libopenjpeg20/jp2.c
+@@ -1508,7 +1508,7 @@ OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
+ 			/* Part 1, I.5.3.4: Either both or none : */
+ 			if( !jp2->color.jp2_pclr->cmap)
+ 				opj_jp2_free_pclr(&(jp2->color));
+-			else
++			else if (p_image->pdfium_use_colorspace)
+ 				opj_jp2_apply_pclr(p_image, &(jp2->color));
+ 		}
+ 
+diff --git a/third_party/libopenjpeg20/openjpeg.h b/third_party/libopenjpeg20/openjpeg.h
+index c07e9c8..e571672 100644
+--- a/third_party/libopenjpeg20/openjpeg.h
++++ b/third_party/libopenjpeg20/openjpeg.h
+@@ -677,6 +677,9 @@ typedef struct opj_image {
+ 	OPJ_BYTE *icc_profile_buf;
+ 	/** size of ICC profile */
+ 	OPJ_UINT32 icc_profile_len;
++
++	/** Whether to apply PCLR or not */
++	OPJ_BOOL pdfium_use_colorspace;
+ } opj_image_t;
+ 
+ 
diff --git a/third_party/libopenjpeg20/0001-image-data.patch b/third_party/libopenjpeg20/0001-image-data.patch
new file mode 100644
index 0000000..5ae0149
--- /dev/null
+++ b/third_party/libopenjpeg20/0001-image-data.patch
@@ -0,0 +1,26 @@
+diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c
+index e612d06..d515798 100644
+--- a/third_party/libopenjpeg20/j2k.c
++++ b/third_party/libopenjpeg20/j2k.c
+@@ -8148,11 +8148,16 @@ static OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data,
+ 
+                 /* Allocate output component buffer if necessary */
+                 if (!l_img_comp_dest->data) {
+-
+-                        l_img_comp_dest->data = (OPJ_INT32*) opj_calloc((OPJ_SIZE_T)l_img_comp_dest->w * (OPJ_SIZE_T)l_img_comp_dest->h, sizeof(OPJ_INT32));
+-                        if (! l_img_comp_dest->data) {
+-                                return OPJ_FALSE;
+-                        }
++                    OPJ_UINT32 width = l_img_comp_dest->w;
++                    OPJ_UINT32 height = l_img_comp_dest->h;
++                    const OPJ_UINT32 MAX_SIZE = UINT32_MAX / sizeof(OPJ_INT32);
++                    if (height == 0 || width > MAX_SIZE / height) {
++                        return OPJ_FALSE;
++                    }
++                    l_img_comp_dest->data = (OPJ_INT32*)opj_calloc(width * height, sizeof(OPJ_INT32));
++                    if (!l_img_comp_dest->data) {
++                        return OPJ_FALSE;
++                    }
+                 }
+ 
+                 /* Copy info from decoded comp image to output image */
diff --git a/third_party/libopenjpeg20/0002-packet-iterator.patch b/third_party/libopenjpeg20/0002-packet-iterator.patch
new file mode 100644
index 0000000..ac755ed
--- /dev/null
+++ b/third_party/libopenjpeg20/0002-packet-iterator.patch
@@ -0,0 +1,27 @@
+diff --git a/third_party/libopenjpeg20/pi.c b/third_party/libopenjpeg20/pi.c
+index 1697bcb..06f1e41 100644
+--- a/third_party/libopenjpeg20/pi.c
++++ b/third_party/libopenjpeg20/pi.c
+@@ -36,6 +36,7 @@
+  * POSSIBILITY OF SUCH DAMAGE.
+  */
+ 
++#include <limits.h>
+ #include "opj_includes.h"
+ 
+ /** @defgroup PI PI - Implementation of a packet iterator */
+@@ -1236,7 +1237,13 @@ opj_pi_iterator_t *opj_pi_create_decode(opj_image_t *p_image,
+ 	l_current_pi = l_pi;
+ 
+ 	/* memory allocation for include */
+-	l_current_pi->include = (OPJ_INT16*) opj_calloc((l_tcp->numlayers +1) * l_step_l, sizeof(OPJ_INT16));
++	l_current_pi->include = 00;
++	if
++		(l_step_l && l_tcp->numlayers < UINT_MAX / l_step_l - 1)
++	{
++		l_current_pi->include = (OPJ_INT16*)opj_calloc((l_tcp->numlayers + 1) * l_step_l, sizeof(OPJ_INT16));
++	}
++
+ 	if
+ 		(!l_current_pi->include)
+ 	{
diff --git a/third_party/libopenjpeg20/0003-dwt-decode.patch b/third_party/libopenjpeg20/0003-dwt-decode.patch
new file mode 100644
index 0000000..c500f0c
--- /dev/null
+++ b/third_party/libopenjpeg20/0003-dwt-decode.patch
@@ -0,0 +1,191 @@
+diff --git a/third_party/libopenjpeg20/dwt.c b/third_party/libopenjpeg20/dwt.c
+index 4ad99ed..975a97e 100644
+--- a/third_party/libopenjpeg20/dwt.c
++++ b/third_party/libopenjpeg20/dwt.c
+@@ -46,14 +46,12 @@
+ /** @defgroup DWT DWT - Implementation of a discrete wavelet transform */
+ /*@{*/
+ 
+-#define OPJ_WS(i) v->mem[(i)*2]
+-#define OPJ_WD(i) v->mem[(1+(i)*2)]
+-
+ /** @name Local data structures */
+ /*@{*/
+ 
+ typedef struct dwt_local {
+ 	OPJ_INT32* mem;
++	OPJ_SIZE_T mem_count;
+ 	OPJ_INT32 dn;
+ 	OPJ_INT32 sn;
+ 	OPJ_INT32 cas;
+@@ -107,16 +105,16 @@ static void opj_dwt_interleave_v(opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x);
+ /**
+ Forward 5-3 wavelet transform in 1-D
+ */
+-static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas);
++static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas);
+ /**
+ Inverse 5-3 wavelet transform in 1-D
+ */
+ static void opj_dwt_decode_1(opj_dwt_t *v);
+-static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas);
++static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas);
+ /**
+ Forward 9-7 wavelet transform in 1-D
+ */
+-static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas);
++static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas);
+ /**
+ Explicit calculation of the Quantization Stepsizes 
+ */
+@@ -124,10 +122,10 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_st
+ /**
+ Inverse wavelet transform in 2-D.
+ */
+-static OPJ_BOOL opj_dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i, DWT1DFN fn);
++static OPJ_BOOL opj_dwt_decode_tile(const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i, DWT1DFN fn);
+ 
+-static OPJ_BOOL opj_dwt_encode_procedure(	opj_tcd_tilecomp_t * tilec,
+-										    void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) );
++static OPJ_BOOL opj_dwt_encode_procedure(const opj_tcd_tilecomp_t * tilec,
++										    void(*p_function)(OPJ_INT32 *, OPJ_SIZE_T, OPJ_INT32, OPJ_INT32, OPJ_INT32));
+ 
+ static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i);
+ 
+@@ -156,13 +154,20 @@ static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w, OPJ_INT32 k, OPJ_IN
+ 
+ /*@}*/
+ 
+-#define OPJ_S(i) a[(i)*2]
+-#define OPJ_D(i) a[(1+(i)*2)]
+-#define OPJ_S_(i) ((i)<0?OPJ_S(0):((i)>=sn?OPJ_S(sn-1):OPJ_S(i)))
+-#define OPJ_D_(i) ((i)<0?OPJ_D(0):((i)>=dn?OPJ_D(dn-1):OPJ_D(i)))
+-/* new */
+-#define OPJ_SS_(i) ((i)<0?OPJ_S(0):((i)>=dn?OPJ_S(dn-1):OPJ_S(i)))
+-#define OPJ_DD_(i) ((i)<0?OPJ_D(0):((i)>=sn?OPJ_D(sn-1):OPJ_D(i)))
++#define IDX_S(i) (i)*2
++#define IDX_D(i) 1 + (i)* 2
++#define UNDERFLOW_SN(i) ((i) >= sn&&sn>0)
++#define UNDERFLOW_DN(i) ((i) >= dn&&dn>0)
++#define OVERFLOW_S(i) (IDX_S(i) >= a_count)
++#define OVERFLOW_D(i) (IDX_D(i) >= a_count)
++
++#define OPJ_S(i) a[IDX_S(i)]
++#define OPJ_D(i) a[IDX_D(i)]
++#define OPJ_S_(i) ((i)<0 ? OPJ_S(0) : (UNDERFLOW_SN(i) ? OPJ_S(sn - 1) : OVERFLOW_S(i) ? OPJ_S(i - 1) : OPJ_S(i)))
++#define OPJ_D_(i) ((i)<0 ? OPJ_D(0) : (UNDERFLOW_DN(i) ? OPJ_D(dn - 1) : OVERFLOW_D(i) ? OPJ_D(i - 1) : OPJ_D(i)))
++/* new */
++#define OPJ_SS_(i) ((i)<0 ? OPJ_S(0) : (UNDERFLOW_DN(i) ? OPJ_S(dn - 1) : OVERFLOW_S(i) ? OPJ_S(i - 1) : OPJ_S(i)))
++#define OPJ_DD_(i) ((i)<0 ? OPJ_D(0) : (UNDERFLOW_SN(i) ? OPJ_D(sn - 1) : OVERFLOW_D(i) ? OPJ_D(i - 1) : OPJ_D(i)))
+ 
+ /* <summary>                                                              */
+ /* This table contains the norms of the 5-3 wavelets for different bands. */
+@@ -283,7 +288,7 @@ static void opj_dwt_interleave_v(opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x) {
+ /* <summary>                            */
+ /* Forward 5-3 wavelet transform in 1-D. */
+ /* </summary>                           */
+-static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
++static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
+ 	OPJ_INT32 i;
+ 	
+ 	if (!cas) {
+@@ -304,7 +309,7 @@ static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32
+ /* <summary>                            */
+ /* Inverse 5-3 wavelet transform in 1-D. */
+ /* </summary>                           */ 
+-static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
++static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
+ 	OPJ_INT32 i;
+ 	
+ 	if (!cas) {
+@@ -326,13 +331,13 @@ static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT3
+ /* Inverse 5-3 wavelet transform in 1-D. */
+ /* </summary>                           */ 
+ static void opj_dwt_decode_1(opj_dwt_t *v) {
+-	opj_dwt_decode_1_(v->mem, v->dn, v->sn, v->cas);
++	opj_dwt_decode_1_(v->mem, v->mem_count, v->dn, v->sn, v->cas);
+ }
+ 
+ /* <summary>                             */
+ /* Forward 9-7 wavelet transform in 1-D. */
+ /* </summary>                            */
+-static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
++static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
+ 	OPJ_INT32 i;
+ 	if (!cas) {
+ 		if ((dn > 0) || (sn > 1)) {	/* NEW :  CASE ONE ELEMENT */
+@@ -385,7 +390,7 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_st
+ /* <summary>                            */
+ /* Forward 5-3 wavelet transform in 2-D. */
+ /* </summary>                           */
+-static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) )
++static INLINE OPJ_BOOL opj_dwt_encode_procedure(const opj_tcd_tilecomp_t * tilec, void(*p_function)(OPJ_INT32 *, OPJ_SIZE_T, OPJ_INT32, OPJ_INT32, OPJ_INT32))
+ {
+ 	OPJ_INT32 i, j, k;
+ 	OPJ_INT32 *a = 00;
+@@ -395,7 +400,8 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void
+ 
+ 	OPJ_INT32 rw;			/* width of the resolution level computed   */
+ 	OPJ_INT32 rh;			/* height of the resolution level computed  */
+-	OPJ_UINT32 l_data_size;
++	OPJ_SIZE_T l_data_count;
++	OPJ_SIZE_T l_data_size;
+ 
+ 	opj_tcd_resolution_t * l_cur_res = 0;
+ 	opj_tcd_resolution_t * l_last_res = 0;
+@@ -407,8 +413,9 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void
+ 	l_cur_res = tilec->resolutions + l;
+ 	l_last_res = l_cur_res - 1;
+ 
+-	l_data_size = opj_dwt_max_resolution( tilec->resolutions,tilec->numresolutions) * (OPJ_UINT32)sizeof(OPJ_INT32);
+-	bj = (OPJ_INT32*)opj_malloc((size_t)l_data_size);
++	l_data_count = opj_dwt_max_resolution(tilec->resolutions, tilec->numresolutions) * (OPJ_UINT32)sizeof(OPJ_INT32);
++	l_data_size = l_data_count * (OPJ_UINT32)sizeof(OPJ_INT32);
++	bj = (OPJ_INT32*)opj_malloc(l_data_size);
+ 	if (! bj) {
+ 		return OPJ_FALSE;
+ 	}
+@@ -437,7 +444,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void
+ 				bj[k] = aj[k*w];
+ 			}
+ 
+-			(*p_function) (bj, dn, sn, cas_col);
++			(*p_function) (bj, l_data_count, dn, sn, cas_col);
+ 
+ 			opj_dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col);
+ 		}
+@@ -448,7 +455,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void
+ 		for (j = 0; j < rh; j++) {
+ 			aj = a + j * w;
+ 			for (k = 0; k < rw; k++)  bj[k] = aj[k];
+-			(*p_function) (bj, dn, sn, cas_row);
++			(*p_function) (bj, l_data_count, dn, sn, cas_row);
+ 			opj_dwt_deinterleave_h(bj, aj, dn, sn, cas_row);
+ 		}
+ 
+@@ -557,7 +564,7 @@ static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_U
+ /* <summary>                            */
+ /* Inverse wavelet transform in 2-D.     */
+ /* </summary>                           */
+-static OPJ_BOOL opj_dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D) {
++static OPJ_BOOL opj_dwt_decode_tile(const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D) {
+ 	opj_dwt_t h;
+ 	opj_dwt_t v;
+ 
+@@ -568,13 +575,14 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres
+ 
+ 	OPJ_UINT32 w = (OPJ_UINT32)(tilec->x1 - tilec->x0);
+ 
+-	h.mem = (OPJ_INT32*)
+-	opj_aligned_malloc(opj_dwt_max_resolution(tr, numres) * sizeof(OPJ_INT32));
++	h.mem_count = opj_dwt_max_resolution(tr, numres);
++	h.mem = (OPJ_INT32*)opj_aligned_malloc(h.mem_count * sizeof(OPJ_INT32));
+ 	if (! h.mem){
+ 		/* FIXME event manager error callback */
+ 		return OPJ_FALSE;
+ 	}
+ 
++	v.mem_count = h.mem_count;
+ 	v.mem = h.mem;
+ 
+ 	while( --numres) {
diff --git a/third_party/libopenjpeg20/README.pdfium b/third_party/libopenjpeg20/README.pdfium
new file mode 100644
index 0000000..bdb2f62
--- /dev/null
+++ b/third_party/libopenjpeg20/README.pdfium
@@ -0,0 +1,16 @@
+Name: OpenJPEG
+URL: http://www.openjpeg.org/
+Version: 0fa5a17c98c4b8f9ee2286f4f0a50cf52a5fccb0
+Security Critical: yes
+License: 2-clause BSD
+
+Description:
+JPEG 2000 library.
+
+Local Modifications:
+
+0000-use-colorspace.patch: Makes it possible to not call opj_jp2_apply_pclr().
+0001-image-data.patch: Fix a crashier in opj_j2k_update_image_data().
+0002-packet-iterator.patch: Fix integer overflow in opj_pi_create_decode().
+0003-dwt-decode.patch: Check array bounds for opj_dwt_decode_1() and friends.
+TODO(thestig): List all the other patches.
diff --git a/third_party/libopenjpeg20/bio.c b/third_party/libopenjpeg20/bio.c
index 3ce6492..e4edb37 100644
--- a/third_party/libopenjpeg20/bio.c
+++ b/third_party/libopenjpeg20/bio.c
@@ -78,7 +78,7 @@
 ==========================================================
 */
 
-OPJ_BOOL opj_bio_byteout(opj_bio_t *bio) {
+static OPJ_BOOL opj_bio_byteout(opj_bio_t *bio) {
 	bio->buf = (bio->buf << 8) & 0xffff;
 	bio->ct = bio->buf == 0xff00 ? 7 : 8;
 	if ((OPJ_SIZE_T)bio->bp >= (OPJ_SIZE_T)bio->end) {
@@ -88,7 +88,7 @@
 	return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_bio_bytein(opj_bio_t *bio) {
+static OPJ_BOOL opj_bio_bytein(opj_bio_t *bio) {
 	bio->buf = (bio->buf << 8) & 0xffff;
 	bio->ct = bio->buf == 0xff00 ? 7 : 8;
 	if ((OPJ_SIZE_T)bio->bp >= (OPJ_SIZE_T)bio->end) {
@@ -98,7 +98,7 @@
 	return OPJ_TRUE;
 }
 
-void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b) {
+static void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b) {
 	if (bio->ct == 0) {
 		opj_bio_byteout(bio); /* MSD: why not check the return value of this function ? */
 	}
@@ -106,7 +106,7 @@
 	bio->buf |= b << bio->ct;
 }
 
-OPJ_UINT32 opj_bio_getbit(opj_bio_t *bio) {
+static OPJ_UINT32 opj_bio_getbit(opj_bio_t *bio) {
 	if (bio->ct == 0) {
 		opj_bio_bytein(bio); /* MSD: why not check the return value of this function ? */
 	}
diff --git a/third_party/libopenjpeg20/cio.c b/third_party/libopenjpeg20/cio.c
index c455bf7..b2f6405 100644
--- a/third_party/libopenjpeg20/cio.c
+++ b/third_party/libopenjpeg20/cio.c
@@ -46,7 +46,7 @@
 
 void opj_write_bytes_BE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes)
 {
-	const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + p_nb_bytes;
+	const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value)+sizeof(OPJ_UINT32)-p_nb_bytes;
 
 	assert(p_nb_bytes > 0 && p_nb_bytes <=  sizeof(OPJ_UINT32));
 
@@ -72,7 +72,7 @@
 	assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
 
 	*p_value = 0;
-	memcpy(l_data_ptr+4-p_nb_bytes,p_buffer,p_nb_bytes);
+	memcpy(l_data_ptr+sizeof(OPJ_UINT32)-p_nb_bytes,p_buffer,p_nb_bytes);
 }
 
 void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes)
@@ -302,7 +302,7 @@
 		p_stream->m_current_data = p_stream->m_stored_data;
 	}
 
-	while(1){
+	for (;;) {
 		/* we should read less than a chunk -> read a chunk */
 		if (p_size < p_stream->m_buffer_size) {
 			/* we should do an actual read on the media */
@@ -382,7 +382,7 @@
 		return (OPJ_SIZE_T)-1;
 	}
 
-	while(1) {
+	for (;;) {
 		l_remaining_bytes = p_stream->m_buffer_size - p_stream->m_bytes_in_buffer;
 		
 		/* we have more memory than required */
diff --git a/third_party/libopenjpeg20/cio.h b/third_party/libopenjpeg20/cio.h
index 6dfa5bb..1b684ef 100644
--- a/third_party/libopenjpeg20/cio.h
+++ b/third_party/libopenjpeg20/cio.h
@@ -184,7 +184,7 @@
  * @param p_buffer		pointer the data buffer to read data from.
  * @param p_value		pointer to the value that will store the data.
  * @param p_nb_bytes	the nb bytes to read.
- * @return				the number of bytes read or -1 if an error occured.
+ * @return				the number of bytes read or -1 if an error occurred.
  */
 void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes);
 
@@ -193,7 +193,7 @@
  * @param p_buffer		pointer the data buffer to write data to.
  * @param p_value		the value to write
  * @param p_nb_bytes	the number of bytes to write
- * @return				the number of bytes written or -1 if an error occured
+ * @return				the number of bytes written or -1 if an error occurred
 */
 void opj_write_bytes_LE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes);
 
@@ -202,7 +202,7 @@
  * @param p_buffer		pointer the data buffer to read data from.
  * @param p_value		pointer to the value that will store the data.
  * @param p_nb_bytes	the nb bytes to read.
- * @return				the number of bytes read or -1 if an error occured.
+ * @return				the number of bytes read or -1 if an error occurred.
  */
 void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes);
 
@@ -269,7 +269,7 @@
  * @param		p_buffer	pointer to the data buffer that will receive the data.
  * @param		p_size		number of bytes to read.
  * @param		p_event_mgr	the user event manager to be notified of special events.
- * @return		the number of bytes read, or -1 if an error occured or if the stream is at the end.
+ * @return		the number of bytes read, or -1 if an error occurred or if the stream is at the end.
  */
 OPJ_SIZE_T opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr);
 
@@ -279,7 +279,7 @@
  * @param		p_buffer	pointer to the data buffer holds the data to be writtent.
  * @param		p_size		number of bytes to write.
  * @param		p_event_mgr	the user event manager to be notified of special events.
- * @return		the number of bytes writtent, or -1 if an error occured.
+ * @return		the number of bytes writtent, or -1 if an error occurred.
  */
 OPJ_SIZE_T opj_stream_write_data (opj_stream_private_t * p_stream,const OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr);
 
@@ -296,7 +296,7 @@
  * @param		p_stream	the stream to skip data from.
  * @param		p_size		the number of bytes to skip.
  * @param		p_event_mgr	the user event manager to be notified of special events.
- * @return		the number of bytes skipped, or -1 if an error occured.
+ * @return		the number of bytes skipped, or -1 if an error occurred.
  */
 OPJ_OFF_T opj_stream_skip (opj_stream_private_t * p_stream,OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr);
 
@@ -324,7 +324,7 @@
  * @param		p_stream	the stream to skip data from.
  * @param		p_size		the number of bytes to skip.
  * @param		p_event_mgr	the user event manager to be notified of special events.
- * @return		the number of bytes skipped, or -1 if an error occured.
+ * @return		the number of bytes skipped, or -1 if an error occurred.
  */
 OPJ_OFF_T opj_stream_write_skip (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr);
 
@@ -333,7 +333,7 @@
  * @param		p_stream	the stream to skip data from.
  * @param		p_size		the number of bytes to skip.
  * @param		p_event_mgr	the user event manager to be notified of special events.
- * @return		the number of bytes skipped, or -1 if an error occured.
+ * @return		the number of bytes skipped, or -1 if an error occurred.
  */
 OPJ_OFF_T opj_stream_read_skip (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr);
 
@@ -342,7 +342,7 @@
  * @param		p_stream	the stream to skip data from.
  * @param		p_size		the number of bytes to skip.
  * @param		p_event_mgr	the user event manager to be notified of special events.
- * @return		OPJ_TRUE if success, or OPJ_FALSE if an error occured.
+ * @return		OPJ_TRUE if success, or OPJ_FALSE if an error occurred.
  */
 OPJ_BOOL opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr);
 
@@ -351,7 +351,7 @@
  * @param		p_stream	the stream to skip data from.
  * @param		p_size		the number of bytes to skip.
  * @param		p_event_mgr	the user event manager to be notified of special events.
- * @return		the number of bytes skipped, or -1 if an error occured.
+ * @return		the number of bytes skipped, or -1 if an error occurred.
  */
 OPJ_BOOL opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr);
 
diff --git a/third_party/libopenjpeg20/dwt.c b/third_party/libopenjpeg20/dwt.c
index 9b40c74..3b92bdf 100644
--- a/third_party/libopenjpeg20/dwt.c
+++ b/third_party/libopenjpeg20/dwt.c
@@ -125,7 +125,7 @@
 static OPJ_BOOL opj_dwt_decode_tile(const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i, DWT1DFN fn);
 
 static OPJ_BOOL opj_dwt_encode_procedure(const opj_tcd_tilecomp_t * tilec,
-										    void (*p_function)(OPJ_INT32 *, OPJ_SIZE_T,OPJ_INT32,OPJ_INT32,OPJ_INT32) );
+										    void(*p_function)(OPJ_INT32 *, OPJ_SIZE_T, OPJ_INT32, OPJ_INT32, OPJ_INT32));
 
 static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i);
 
@@ -155,19 +155,19 @@
 /*@}*/
 
 #define IDX_S(i) (i)*2
-#define IDX_D(i) 1+(i)*2
-#define UNDERFLOW_SN(i) ((i)>=sn&&sn>0)
-#define UNDERFLOW_DN(i) ((i)>=dn&&dn>0)
-#define OVERFLOW_S(i) (IDX_S(i)>=a_count)
-#define OVERFLOW_D(i) (IDX_D(i)>=a_count)
+#define IDX_D(i) 1 + (i)* 2
+#define UNDERFLOW_SN(i) ((i) >= sn&&sn>0)
+#define UNDERFLOW_DN(i) ((i) >= dn&&dn>0)
+#define OVERFLOW_S(i) (IDX_S(i) >= a_count)
+#define OVERFLOW_D(i) (IDX_D(i) >= a_count)
 
 #define OPJ_S(i) a[IDX_S(i)]
 #define OPJ_D(i) a[IDX_D(i)]
-#define OPJ_S_(i) ((i)<0?OPJ_S(0):(UNDERFLOW_SN(i)?OPJ_S(sn-1):OVERFLOW_S(i)?OPJ_S(i-1):OPJ_S(i)))
-#define OPJ_D_(i) ((i)<0?OPJ_D(0):(UNDERFLOW_DN(i)?OPJ_D(dn-1):OVERFLOW_D(i)?OPJ_D(i-1):OPJ_D(i)))
+#define OPJ_S_(i) ((i)<0 ? OPJ_S(0) : (UNDERFLOW_SN(i) ? OPJ_S(sn - 1) : OVERFLOW_S(i) ? OPJ_S(i - 1) : OPJ_S(i)))
+#define OPJ_D_(i) ((i)<0 ? OPJ_D(0) : (UNDERFLOW_DN(i) ? OPJ_D(dn - 1) : OVERFLOW_D(i) ? OPJ_D(i - 1) : OPJ_D(i)))
 /* new */
-#define OPJ_SS_(i) ((i)<0?OPJ_S(0):(UNDERFLOW_DN(i)?OPJ_S(dn-1):OVERFLOW_S(i)?OPJ_S(i-1):OPJ_S(i)))
-#define OPJ_DD_(i) ((i)<0?OPJ_D(0):(UNDERFLOW_SN(i)?OPJ_D(sn-1):OVERFLOW_D(i)?OPJ_D(i-1):OPJ_D(i)))
+#define OPJ_SS_(i) ((i)<0 ? OPJ_S(0) : (UNDERFLOW_DN(i) ? OPJ_S(dn - 1) : OVERFLOW_S(i) ? OPJ_S(i - 1) : OPJ_S(i)))
+#define OPJ_DD_(i) ((i)<0 ? OPJ_D(0) : (UNDERFLOW_SN(i) ? OPJ_D(sn - 1) : OVERFLOW_D(i) ? OPJ_D(i - 1) : OPJ_D(i)))
 
 /* <summary>                                                              */
 /* This table contains the norms of the 5-3 wavelets for different bands. */
@@ -198,7 +198,7 @@
 /* <summary>			                 */
 /* Forward lazy transform (horizontal).  */
 /* </summary>                            */ 
-void opj_dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
+static void opj_dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
 	OPJ_INT32 i;
 	OPJ_INT32 * l_dest = b;
 	OPJ_INT32 * l_src = a+cas;
@@ -220,7 +220,7 @@
 /* <summary>                             */  
 /* Forward lazy transform (vertical).    */
 /* </summary>                            */ 
-void opj_dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 x, OPJ_INT32 cas) {
+static void opj_dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 x, OPJ_INT32 cas) {
     OPJ_INT32 i = sn;
 	OPJ_INT32 * l_dest = b;
 	OPJ_INT32 * l_src = a+cas;
@@ -245,7 +245,7 @@
 /* <summary>                             */
 /* Inverse lazy transform (horizontal).  */
 /* </summary>                            */
-void opj_dwt_interleave_h(opj_dwt_t* h, OPJ_INT32 *a) {
+static void opj_dwt_interleave_h(opj_dwt_t* h, OPJ_INT32 *a) {
     OPJ_INT32 *ai = a;
     OPJ_INT32 *bi = h->mem + h->cas;
     OPJ_INT32  i	= h->sn;
@@ -265,7 +265,7 @@
 /* <summary>                             */  
 /* Inverse lazy transform (vertical).    */
 /* </summary>                            */ 
-void opj_dwt_interleave_v(opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x) {
+static void opj_dwt_interleave_v(opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x) {
     OPJ_INT32 *ai = a;
     OPJ_INT32 *bi = v->mem + v->cas;
     OPJ_INT32  i = v->sn;
@@ -288,7 +288,7 @@
 /* <summary>                            */
 /* Forward 5-3 wavelet transform in 1-D. */
 /* </summary>                           */
-void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
+static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
 	OPJ_INT32 i;
 	
 	if (!cas) {
@@ -309,7 +309,7 @@
 /* <summary>                            */
 /* Inverse 5-3 wavelet transform in 1-D. */
 /* </summary>                           */ 
-void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
+static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
 	OPJ_INT32 i;
 	
 	if (!cas) {
@@ -330,14 +330,14 @@
 /* <summary>                            */
 /* Inverse 5-3 wavelet transform in 1-D. */
 /* </summary>                           */ 
-void opj_dwt_decode_1(opj_dwt_t *v) {
+static void opj_dwt_decode_1(opj_dwt_t *v) {
 	opj_dwt_decode_1_(v->mem, v->mem_count, v->dn, v->sn, v->cas);
 }
 
 /* <summary>                             */
 /* Forward 9-7 wavelet transform in 1-D. */
 /* </summary>                            */
-void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
+static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) {
 	OPJ_INT32 i;
 	if (!cas) {
 		if ((dn > 0) || (sn > 1)) {	/* NEW :  CASE ONE ELEMENT */
@@ -372,7 +372,7 @@
 	}
 }
 
-void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_stepsize_t *bandno_stepsize) {
+static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_stepsize_t *bandno_stepsize) {
 	OPJ_INT32 p, n;
 	p = opj_int_floorlog2(stepsize) - 13;
 	n = 11 - opj_int_floorlog2(stepsize);
@@ -390,7 +390,7 @@
 /* <summary>                            */
 /* Forward 5-3 wavelet transform in 2-D. */
 /* </summary>                           */
-INLINE OPJ_BOOL opj_dwt_encode_procedure(const opj_tcd_tilecomp_t * tilec,void (*p_function)(OPJ_INT32 *, OPJ_SIZE_T,OPJ_INT32,OPJ_INT32,OPJ_INT32) )
+static INLINE OPJ_BOOL opj_dwt_encode_procedure(const opj_tcd_tilecomp_t * tilec, void(*p_function)(OPJ_INT32 *, OPJ_SIZE_T, OPJ_INT32, OPJ_INT32, OPJ_INT32))
 {
 	OPJ_INT32 i, j, k;
 	OPJ_INT32 *a = 00;
@@ -413,7 +413,7 @@
 	l_cur_res = tilec->resolutions + l;
 	l_last_res = l_cur_res - 1;
 
-	l_data_count = opj_dwt_max_resolution( tilec->resolutions,tilec->numresolutions);
+	l_data_count = opj_dwt_max_resolution(tilec->resolutions, tilec->numresolutions) * (OPJ_UINT32)sizeof(OPJ_INT32);
 	l_data_size = l_data_count * (OPJ_UINT32)sizeof(OPJ_INT32);
 	bj = (OPJ_INT32*)opj_malloc(l_data_size);
 	if (! bj) {
@@ -548,7 +548,7 @@
 /* <summary>                             */
 /* Determine maximum computed resolution level for inverse wavelet transform */
 /* </summary>                            */
-OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i) {
+static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i) {
 	OPJ_UINT32 mr	= 0;
 	OPJ_UINT32 w;
 	while( --i ) {
@@ -564,7 +564,7 @@
 /* <summary>                            */
 /* Inverse wavelet transform in 2-D.     */
 /* </summary>                           */
-OPJ_BOOL opj_dwt_decode_tile(const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D) {
+static OPJ_BOOL opj_dwt_decode_tile(const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D) {
 	opj_dwt_t h;
 	opj_dwt_t v;
 
@@ -621,7 +621,7 @@
 	return OPJ_TRUE;
 }
 
-void opj_v4dwt_interleave_h(opj_v4dwt_t* restrict w, OPJ_FLOAT32* restrict a, OPJ_INT32 x, OPJ_INT32 size){
+static void opj_v4dwt_interleave_h(opj_v4dwt_t* restrict w, OPJ_FLOAT32* restrict a, OPJ_INT32 x, OPJ_INT32 size){
 	OPJ_FLOAT32* restrict bi = (OPJ_FLOAT32*) (w->wavelet + w->cas);
 	OPJ_INT32 count = w->sn;
 	OPJ_INT32 i, k;
@@ -664,7 +664,7 @@
 	}
 }
 
-void opj_v4dwt_interleave_v(opj_v4dwt_t* restrict v , OPJ_FLOAT32* restrict a , OPJ_INT32 x, OPJ_INT32 nb_elts_read){
+static void opj_v4dwt_interleave_v(opj_v4dwt_t* restrict v , OPJ_FLOAT32* restrict a , OPJ_INT32 x, OPJ_INT32 nb_elts_read){
 	opj_v4_t* restrict bi = v->wavelet + v->cas;
 	OPJ_INT32 i;
 
@@ -682,7 +682,7 @@
 
 #ifdef __SSE__
 
-void opj_v4dwt_decode_step1_sse(opj_v4_t* w, OPJ_INT32 count, const __m128 c){
+static void opj_v4dwt_decode_step1_sse(opj_v4_t* w, OPJ_INT32 count, const __m128 c){
 	__m128* restrict vw = (__m128*) w;
 	OPJ_INT32 i;
 	/* 4x unrolled loop */
@@ -731,7 +731,7 @@
 
 #else
 
-void opj_v4dwt_decode_step1(opj_v4_t* w, OPJ_INT32 count, const OPJ_FLOAT32 c)
+static void opj_v4dwt_decode_step1(opj_v4_t* w, OPJ_INT32 count, const OPJ_FLOAT32 c)
 {
 	OPJ_FLOAT32* restrict fw = (OPJ_FLOAT32*) w;
 	OPJ_INT32 i;
@@ -747,7 +747,7 @@
 	}
 }
 
-void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w, OPJ_INT32 k, OPJ_INT32 m, OPJ_FLOAT32 c)
+static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w, OPJ_INT32 k, OPJ_INT32 m, OPJ_FLOAT32 c)
 {
 	OPJ_FLOAT32* restrict fl = (OPJ_FLOAT32*) l;
 	OPJ_FLOAT32* restrict fw = (OPJ_FLOAT32*) w;
diff --git a/third_party/libopenjpeg20/dwt.h b/third_party/libopenjpeg20/dwt.h
index f8b57bc..21fe942 100644
--- a/third_party/libopenjpeg20/dwt.h
+++ b/third_party/libopenjpeg20/dwt.h
@@ -54,14 +54,14 @@
 /*@{*/
 /* ----------------------------------------------------------------------- */
 /**
-Forward 5-3 wavelet tranform in 2-D. 
+Forward 5-3 wavelet transform in 2-D.
 Apply a reversible DWT transform to a component of an image.
 @param tilec Tile component information (current tile)
 */
 OPJ_BOOL opj_dwt_encode(opj_tcd_tilecomp_t * tilec);
 
 /**
-Inverse 5-3 wavelet tranform in 2-D.
+Inverse 5-3 wavelet transform in 2-D.
 Apply a reversible inverse DWT transform to a component of an image.
 @param tilec Tile component information (current tile)
 @param numres Number of resolution levels to decode
diff --git a/third_party/libopenjpeg20/event.h b/third_party/libopenjpeg20/event.h
index 88e0395..fa8604e 100644
--- a/third_party/libopenjpeg20/event.h
+++ b/third_party/libopenjpeg20/event.h
@@ -95,6 +95,12 @@
  */
 void opj_set_default_event_handler(opj_event_mgr_t * p_manager);
 
+/*
+#ifdef __GNUC__
+#pragma GCC poison printf fprintf
+#endif
+*/
+
 /*@}*/
 
 /*@}*/
diff --git a/third_party/libopenjpeg20/function_list.c b/third_party/libopenjpeg20/function_list.c
index b9a8b4a..a7ea11d 100644
--- a/third_party/libopenjpeg20/function_list.c
+++ b/third_party/libopenjpeg20/function_list.c
@@ -69,8 +69,11 @@
         opj_free(p_list);
 }
 
-OPJ_BOOL opj_procedure_list_add_procedure (opj_procedure_list_t * p_validation_list, opj_procedure p_procedure)
+OPJ_BOOL opj_procedure_list_add_procedure (opj_procedure_list_t * p_validation_list, opj_procedure p_procedure, opj_event_mgr_t* p_manager )
 {
+	
+        assert(p_manager != NULL);
+	
         if (p_validation_list->m_nb_max_procedures == p_validation_list->m_nb_procedures)
         {
                 opj_procedure * new_procedures;
@@ -84,9 +87,7 @@
                         opj_free(p_validation_list->m_procedures);
                         p_validation_list->m_nb_max_procedures = 0;
                         p_validation_list->m_nb_procedures = 0;
-                        /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add a new validation procedure\n"); */
-                        fprintf(stderr, "Not enough memory to add a new validation procedure\n");
-                        
+                        opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add a new validation procedure\n");
                         return OPJ_FALSE;
                 }
                 else
diff --git a/third_party/libopenjpeg20/function_list.h b/third_party/libopenjpeg20/function_list.h
index 749ad9e..ab091b7 100644
--- a/third_party/libopenjpeg20/function_list.h
+++ b/third_party/libopenjpeg20/function_list.h
@@ -95,7 +95,7 @@
  *
  * @return	OPJ_TRUE if the procedure could be added.
  */
-OPJ_BOOL opj_procedure_list_add_procedure (opj_procedure_list_t * p_validation_list, opj_procedure p_procedure);
+OPJ_BOOL opj_procedure_list_add_procedure (opj_procedure_list_t * p_validation_list, opj_procedure p_procedure, opj_event_mgr_t* p_manager);
 
 /**
  * Gets the number of validation procedures.
diff --git a/third_party/libopenjpeg20/image.c b/third_party/libopenjpeg20/image.c
index 8e68668..23462f0 100644
--- a/third_party/libopenjpeg20/image.c
+++ b/third_party/libopenjpeg20/image.c
@@ -47,7 +47,8 @@
 		/* allocate memory for the per-component information */
 		image->comps = (opj_image_comp_t*)opj_calloc(1,image->numcomps * sizeof(opj_image_comp_t));
 		if(!image->comps) {
-			fprintf(stderr,"Unable to allocate memory for image.\n");
+			/* TODO replace with event manager, breaks API */
+			/* fprintf(stderr,"Unable to allocate memory for image.\n"); */
 			opj_image_destroy(image);
 			return NULL;
 		}
@@ -65,7 +66,8 @@
 			comp->sgnd = cmptparms[compno].sgnd;
 			comp->data = (OPJ_INT32*) opj_calloc(comp->w * comp->h, sizeof(OPJ_INT32));
 			if(!comp->data) {
-				fprintf(stderr,"Unable to allocate memory for image.\n");
+				/* TODO replace with event manager, breaks API */
+				/* fprintf(stderr,"Unable to allocate memory for image.\n"); */
 				opj_image_destroy(image);
 				return NULL;
 			}
@@ -107,27 +109,29 @@
 void opj_image_comp_header_update(opj_image_t * p_image_header, const struct opj_cp * p_cp)
 {
 	OPJ_UINT32 i, l_width, l_height;
-	OPJ_INT32 l_x0, l_y0, l_x1, l_y1;
-	OPJ_INT32 l_comp_x0, l_comp_y0, l_comp_x1, l_comp_y1;
+	OPJ_UINT32 l_x0, l_y0, l_x1, l_y1;
+	OPJ_UINT32 l_comp_x0, l_comp_y0, l_comp_x1, l_comp_y1;
 	opj_image_comp_t* l_img_comp = NULL;
 
-	l_x0 = opj_int_max((OPJ_INT32)p_cp->tx0 , (OPJ_INT32)p_image_header->x0);
-	l_y0 = opj_int_max((OPJ_INT32)p_cp->ty0 , (OPJ_INT32)p_image_header->y0);
-	l_x1 = opj_int_min((OPJ_INT32)(p_cp->tx0 + p_cp->tw * p_cp->tdx), (OPJ_INT32)p_image_header->x1);
-	l_y1 = opj_int_min((OPJ_INT32)(p_cp->ty0 + p_cp->th * p_cp->tdy), (OPJ_INT32)p_image_header->y1);
+	l_x0 = opj_uint_max(p_cp->tx0 , p_image_header->x0);
+	l_y0 = opj_uint_max(p_cp->ty0 , p_image_header->y0);
+	l_x1 = p_cp->tx0 + (p_cp->tw - 1U) * p_cp->tdx; /* validity of p_cp members used here checked in opj_j2k_read_siz. Can't overflow. */
+	l_y1 = p_cp->ty0 + (p_cp->th - 1U) * p_cp->tdy; /* can't overflow */
+	l_x1 = opj_uint_min(opj_uint_adds(l_x1, p_cp->tdx), p_image_header->x1); /* use add saturated to prevent overflow */
+	l_y1 = opj_uint_min(opj_uint_adds(l_y1, p_cp->tdy), p_image_header->y1); /* use add saturated to prevent overflow */
 
 	l_img_comp = p_image_header->comps;
 	for	(i = 0; i < p_image_header->numcomps; ++i) {
-		l_comp_x0 = opj_int_ceildiv(l_x0, (OPJ_INT32)l_img_comp->dx);
-		l_comp_y0 = opj_int_ceildiv(l_y0, (OPJ_INT32)l_img_comp->dy);
-		l_comp_x1 = opj_int_ceildiv(l_x1, (OPJ_INT32)l_img_comp->dx);
-		l_comp_y1 = opj_int_ceildiv(l_y1, (OPJ_INT32)l_img_comp->dy);
-		l_width = (OPJ_UINT32)opj_int_ceildivpow2(l_comp_x1 - l_comp_x0, (OPJ_INT32)l_img_comp->factor);
-		l_height = (OPJ_UINT32)opj_int_ceildivpow2(l_comp_y1 - l_comp_y0, (OPJ_INT32)l_img_comp->factor);
+		l_comp_x0 = opj_uint_ceildiv(l_x0, l_img_comp->dx);
+		l_comp_y0 = opj_uint_ceildiv(l_y0, l_img_comp->dy);
+		l_comp_x1 = opj_uint_ceildiv(l_x1, l_img_comp->dx);
+		l_comp_y1 = opj_uint_ceildiv(l_y1, l_img_comp->dy);
+		l_width   = opj_uint_ceildivpow2(l_comp_x1 - l_comp_x0, l_img_comp->factor);
+		l_height  = opj_uint_ceildivpow2(l_comp_y1 - l_comp_y0, l_img_comp->factor);
 		l_img_comp->w = l_width;
 		l_img_comp->h = l_height;
-		l_img_comp->x0 = (OPJ_UINT32)l_comp_x0/*l_x0*/;
-		l_img_comp->y0 = (OPJ_UINT32)l_comp_y0/*l_y0*/;
+		l_img_comp->x0 = l_comp_x0;
+		l_img_comp->y0 = l_comp_y0;
 		++l_img_comp;
 	}
 }
diff --git a/third_party/libopenjpeg20/indexbox_manager.h b/third_party/libopenjpeg20/indexbox_manager.h
index ec5525f..ebcde8f 100644
--- a/third_party/libopenjpeg20/indexbox_manager.h
+++ b/third_party/libopenjpeg20/indexbox_manager.h
@@ -108,7 +108,7 @@
               opj_event_mgr_t * p_manager );
 
 /* 
- * Wriet manifest box (box)
+ * Write manifest box (box)
  *
  * @param[in] second number to be visited
  * @param[in] v      number of boxes
diff --git a/third_party/libopenjpeg20/invert.c b/third_party/libopenjpeg20/invert.c
index 4c1ee78..7efaf6e 100644
--- a/third_party/libopenjpeg20/invert.c
+++ b/third_party/libopenjpeg20/invert.c
@@ -103,7 +103,7 @@
    Local functions
 ==========================================================
 */
-OPJ_BOOL opj_lupDecompose(OPJ_FLOAT32 * matrix,OPJ_UINT32 * permutations, 
+static OPJ_BOOL opj_lupDecompose(OPJ_FLOAT32 * matrix,OPJ_UINT32 * permutations,
                           OPJ_FLOAT32 * p_swap_area,
                           OPJ_UINT32 nb_compo) 
 {
@@ -125,7 +125,7 @@
 	{
     	*tmpPermutations++ = i;
 	}
-	/* now make a pivot with colum switch */
+	/* now make a pivot with column switch */
 	tmpPermutations = permutations;
 	for (k = 0; k < lLastColum; ++k) {
 		p = 0.0;
@@ -204,7 +204,7 @@
     return OPJ_TRUE;
 }
    		
-void opj_lupSolve (OPJ_FLOAT32 * pResult, 
+static void opj_lupSolve (OPJ_FLOAT32 * pResult,
                    OPJ_FLOAT32 * pMatrix, 
                    OPJ_FLOAT32 * pVector, 
                    OPJ_UINT32* pPermutations, 
@@ -266,7 +266,7 @@
 }
     
 
-void opj_lupInvert (OPJ_FLOAT32 * pSrcMatrix,
+static void opj_lupInvert (OPJ_FLOAT32 * pSrcMatrix,
                     OPJ_FLOAT32 * pDestMatrix,
                     OPJ_UINT32 nb_compo,
                     OPJ_UINT32 * pPermutations,
diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c
index 7b4bc58..849d0b4 100644
--- a/third_party/libopenjpeg20/j2k.c
+++ b/third_party/libopenjpeg20/j2k.c
@@ -51,7 +51,7 @@
 /**
  * Sets up the procedures to do on reading header. Developpers wanting to extend the library can add their own reading procedures.
  */
-static void opj_j2k_setup_header_reading (opj_j2k_t *p_j2k);
+static OPJ_BOOL opj_j2k_setup_header_reading (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager);
 
 /**
  * The read header procedure.
@@ -90,19 +90,19 @@
  * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
  * are valid. Developpers wanting to extend the library can add their own validation procedures.
  */
-static void opj_j2k_setup_encoding_validation (opj_j2k_t *p_j2k);
+static OPJ_BOOL opj_j2k_setup_encoding_validation (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager);
 
 /**
  * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
  * are valid. Developpers wanting to extend the library can add their own validation procedures.
  */
-static void opj_j2k_setup_decoding_validation (opj_j2k_t *p_j2k);
+static OPJ_BOOL opj_j2k_setup_decoding_validation (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager);
 
 /**
  * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
  * are valid. Developpers wanting to extend the library can add their own validation procedures.
  */
-static void opj_j2k_setup_end_compress (opj_j2k_t *p_j2k);
+static OPJ_BOOL opj_j2k_setup_end_compress (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager);
 
 /**
  * The mct encoding validation procedure.
@@ -360,7 +360,7 @@
  * Sets up the procedures to do on writing header.
  * Developers wanting to extend the library can add their own writing procedures.
  */
-static void opj_j2k_setup_header_writing (opj_j2k_t *p_j2k);
+static OPJ_BOOL opj_j2k_setup_header_writing (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager);
 
 static OPJ_BOOL opj_j2k_write_first_tile_part(  opj_j2k_t *p_j2k,
                                                                                             OPJ_BYTE * p_data,
@@ -718,28 +718,28 @@
                                     OPJ_UINT32 p_header_size,
                                     opj_event_mgr_t * p_manager );
 
-#if 0
 /**
- * Reads a PPM marker (Packed packet headers, main header)
+ * Reads a PPM marker (Packed headers, main header)
  *
  * @param       p_header_data   the data contained in the POC box.
  * @param       p_j2k                   the jpeg2000 codec.
  * @param       p_header_size   the size of the data contained in the POC marker.
  * @param       p_manager               the user event manager.
-*/
-static OPJ_BOOL j2k_read_ppm_v2 (
-                                                opj_j2k_t *p_j2k,
-                                                OPJ_BYTE * p_header_data,
-                                                OPJ_UINT32 p_header_size,
-                                                struct opj_event_mgr * p_manager
-                                        );
-#endif
+ */
 
-static OPJ_BOOL j2k_read_ppm_v3 (
-                                                opj_j2k_t *p_j2k,
-                                                OPJ_BYTE * p_header_data,
-                                                OPJ_UINT32 p_header_size,
-                                                opj_event_mgr_t * p_manager );
+static OPJ_BOOL opj_j2k_read_ppm (
+																		 opj_j2k_t *p_j2k,
+																		 OPJ_BYTE * p_header_data,
+																		 OPJ_UINT32 p_header_size,
+																		 opj_event_mgr_t * p_manager );
+
+/**
+ * Merges all PPM markers read (Packed headers, main header)
+ *
+ * @param       p_cp      main coding parameters.
+ * @param       p_manager the user event manager.
+ */
+static OPJ_BOOL opj_j2k_merge_ppm ( opj_cp_t *p_cp, opj_event_mgr_t * p_manager );
 
 /**
  * Reads a PPT marker (Packed packet headers, tile-part header)
@@ -753,6 +753,17 @@
                                     OPJ_BYTE * p_header_data,
                                     OPJ_UINT32 p_header_size,
                                     opj_event_mgr_t * p_manager );
+
+/**
+ * Merges all PPT markers read (Packed headers, tile-part header)
+ *
+ * @param       p_tcp   the tile.
+ * @param       p_manager               the user event manager.
+ */
+static OPJ_BOOL opj_j2k_merge_ppt (  opj_tcp_t *p_tcp,
+																	   opj_event_mgr_t * p_manager );
+
+
 /**
  * Writes the TLM marker (Tile Length Marker)
  *
@@ -780,12 +791,32 @@
                                                                         opj_event_mgr_t * p_manager );
 
 /**
- * Reads a PPT marker (Packed packet headers, tile-part header)
+ * Reads values from a SOT marker (Start of tile-part)
  *
- * @param       p_header_data   the data contained in the PPT box.
- * @param       p_j2k                   the jpeg2000 codec.
+ * the j2k decoder state is not affected. No side effects, no checks except for p_header_size.
+ *
+ * @param       p_header_data   the data contained in the SOT marker.
+ * @param       p_header_size   the size of the data contained in the SOT marker.
+ * @param       p_tile_no       Isot.
+ * @param       p_tot_len       Psot.
+ * @param       p_current_part  TPsot.
+ * @param       p_num_parts     TNsot.
+ * @param       p_manager       the user event manager.
+ */
+static OPJ_BOOL opj_j2k_get_sot_values(OPJ_BYTE *  p_header_data,
+																			 OPJ_UINT32  p_header_size,
+																			 OPJ_UINT32* p_tile_no,
+																			 OPJ_UINT32* p_tot_len,
+																			 OPJ_UINT32* p_current_part,
+																			 OPJ_UINT32* p_num_parts,
+																			 opj_event_mgr_t * p_manager );
+/**
+ * Reads a SOT marker (Start of tile-part)
+ *
+ * @param       p_header_data   the data contained in the SOT marker.
+ * @param       p_j2k           the jpeg2000 codec.
  * @param       p_header_size   the size of the data contained in the PPT marker.
- * @param       p_manager               the user event manager.
+ * @param       p_manager       the user event manager.
 */
 static OPJ_BOOL opj_j2k_read_sot (  opj_j2k_t *p_j2k,
                                     OPJ_BYTE * p_header_data,
@@ -821,7 +852,7 @@
                                     opj_stream_private_t *p_stream,
                                     opj_event_mgr_t * p_manager );
 
-void opj_j2k_update_tlm (opj_j2k_t * p_j2k, OPJ_UINT32 p_tile_part_size )
+static void opj_j2k_update_tlm (opj_j2k_t * p_j2k, OPJ_UINT32 p_tile_part_size )
 {
         opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,p_j2k->m_current_tile_number,1);            /* PSOT */
         ++p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current;
@@ -1179,6 +1210,18 @@
 
 static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, opj_event_mgr_t *p_manager);
 
+/**
+ * Checks for invalid number of tile-parts in SOT marker (TPsot==TNsot). See issue 254.
+ *
+ * @param       p_stream            the stream to read data from.
+ * @param       tile_no             tile number we're looking for.
+ * @param       p_correction_needed output value. if true, non conformant codestream needs TNsot correction.
+ * @param       p_manager       the user event manager.
+ *
+ * @return true if the function was successful, false else.
+ */
+static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t *p_stream, OPJ_UINT32 tile_no, OPJ_BOOL* p_correction_needed, opj_event_mgr_t * p_manager );
+
 /*@}*/
 
 /*@}*/
@@ -1189,7 +1232,7 @@
         char str_prog[5];
 }j2k_prog_order_t;
 
-j2k_prog_order_t j2k_prog_order_list[] = {
+static j2k_prog_order_t j2k_prog_order_list[] = {
         {OPJ_CPRL, "CPRL"},
         {OPJ_LRCP, "LRCP"},
         {OPJ_PCRL, "PCRL"},
@@ -1211,7 +1254,7 @@
 
 typedef void (* opj_j2k_mct_function) (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
 
-const opj_j2k_mct_function j2k_mct_read_functions_to_float [] =
+static const opj_j2k_mct_function j2k_mct_read_functions_to_float [] =
 {
         opj_j2k_read_int16_to_float,
         opj_j2k_read_int32_to_float,
@@ -1219,7 +1262,7 @@
         opj_j2k_read_float64_to_float
 };
 
-const opj_j2k_mct_function j2k_mct_read_functions_to_int32 [] =
+static const opj_j2k_mct_function j2k_mct_read_functions_to_int32 [] =
 {
         opj_j2k_read_int16_to_int32,
         opj_j2k_read_int32_to_int32,
@@ -1227,7 +1270,7 @@
         opj_j2k_read_float64_to_int32
 };
 
-const opj_j2k_mct_function j2k_mct_write_functions_from_float [] =
+static const opj_j2k_mct_function j2k_mct_write_functions_from_float [] =
 {
         opj_j2k_write_float_to_int16,
         opj_j2k_write_float_to_int32,
@@ -1249,7 +1292,7 @@
 }
 opj_dec_memory_marker_handler_t;
 
-const opj_dec_memory_marker_handler_t j2k_memory_marker_handler_tab [] =
+static const opj_dec_memory_marker_handler_t j2k_memory_marker_handler_tab [] =
 {
   {J2K_MS_SOT, J2K_STATE_MH | J2K_STATE_TPHSOT, opj_j2k_read_sot},
   {J2K_MS_COD, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_cod},
@@ -1262,7 +1305,7 @@
   {J2K_MS_TLM, J2K_STATE_MH, opj_j2k_read_tlm},
   {J2K_MS_PLM, J2K_STATE_MH, opj_j2k_read_plm},
   {J2K_MS_PLT, J2K_STATE_TPH, opj_j2k_read_plt},
-  {J2K_MS_PPM, J2K_STATE_MH, j2k_read_ppm_v3},
+  {J2K_MS_PPM, J2K_STATE_MH, opj_j2k_read_ppm},
   {J2K_MS_PPT, J2K_STATE_TPH, opj_j2k_read_ppt},
   {J2K_MS_SOP, 0, 0},
   {J2K_MS_CRG, J2K_STATE_MH, opj_j2k_read_crg},
@@ -1286,7 +1329,7 @@
   {J2K_MS_UNK, J2K_STATE_MH | J2K_STATE_TPH, 0}/*opj_j2k_read_unk is directly used*/
 };
 
-void  opj_j2k_read_int16_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+static void  opj_j2k_read_int16_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
 {
         OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
         OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data;
@@ -1302,7 +1345,7 @@
         }
 }
 
-void  opj_j2k_read_int32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+static void  opj_j2k_read_int32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
 {
         OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
         OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data;
@@ -1318,7 +1361,7 @@
         }
 }
 
-void  opj_j2k_read_float32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+static void  opj_j2k_read_float32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
 {
         OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
         OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data;
@@ -1334,7 +1377,7 @@
         }
 }
 
-void  opj_j2k_read_float64_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+static void  opj_j2k_read_float64_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
 {
         OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
         OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data;
@@ -1350,7 +1393,7 @@
         }
 }
 
-void  opj_j2k_read_int16_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+static void  opj_j2k_read_int16_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
 {
         OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
         OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data;
@@ -1366,7 +1409,7 @@
         }
 }
 
-void  opj_j2k_read_int32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+static void  opj_j2k_read_int32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
 {
         OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
         OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data;
@@ -1382,7 +1425,7 @@
         }
 }
 
-void  opj_j2k_read_float32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+static void  opj_j2k_read_float32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
 {
         OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
         OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data;
@@ -1398,7 +1441,7 @@
         }
 }
 
-void  opj_j2k_read_float64_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+static void  opj_j2k_read_float64_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
 {
         OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
         OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data;
@@ -1414,7 +1457,7 @@
         }
 }
 
-void  opj_j2k_write_float_to_int16 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+static void  opj_j2k_write_float_to_int16 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
 {
         OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data;
         OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data;
@@ -1430,7 +1473,7 @@
         }
 }
 
-void opj_j2k_write_float_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+static void opj_j2k_write_float_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
 {
         OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data;
         OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data;
@@ -1446,7 +1489,7 @@
         }
 }
 
-void  opj_j2k_write_float_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+static void  opj_j2k_write_float_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
 {
         OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data;
         OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data;
@@ -1462,7 +1505,7 @@
         }
 }
 
-void  opj_j2k_write_float_to_float64 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+static void  opj_j2k_write_float_to_float64 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
 {
         OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data;
         OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data;
@@ -1488,7 +1531,7 @@
         return po->str_prog;
 }
 
-OPJ_BOOL opj_j2k_check_poc_val( const opj_poc_t *p_pocs,
+static OPJ_BOOL opj_j2k_check_poc_val( const opj_poc_t *p_pocs,
                                                         OPJ_UINT32 p_nb_pocs,
                                                         OPJ_UINT32 p_nb_resolutions,
                                                         OPJ_UINT32 p_num_comps,
@@ -1592,7 +1635,7 @@
 
 /* ----------------------------------------------------------------------- */
 
-OPJ_UINT32 opj_j2k_get_num_tp(opj_cp_t *cp, OPJ_UINT32 pino, OPJ_UINT32 tileno)
+static OPJ_UINT32 opj_j2k_get_num_tp(opj_cp_t *cp, OPJ_UINT32 pino, OPJ_UINT32 tileno)
 {
         const OPJ_CHAR *prog = 00;
         OPJ_INT32 i;
@@ -1650,7 +1693,7 @@
         return tpnum;
 }
 
-OPJ_BOOL opj_j2k_calculate_tp(  opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_calculate_tp(  opj_j2k_t *p_j2k,
                                                         opj_cp_t *cp,
                                                         OPJ_UINT32 * p_nb_tiles,
                                                         opj_image_t *image,
@@ -1728,7 +1771,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_soc(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_soc(     opj_j2k_t *p_j2k,
                                                 opj_stream_private_t *p_stream,
                                                     opj_event_mgr_t * p_manager )
 {
@@ -1806,7 +1849,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_siz(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_siz(     opj_j2k_t *p_j2k,
                                                         opj_stream_private_t *p_stream,
                                                         opj_event_mgr_t * p_manager )
 {
@@ -1999,14 +2042,8 @@
         }
 
         /* 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;
-        }
+        l_tx1 = opj_uint_adds(l_cp->tx0, l_cp->tdx); /* manage overflow */
+        l_ty1 = opj_uint_adds(l_cp->ty0, l_cp->tdy); /* manage overflow */
         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;
@@ -2254,7 +2291,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_com(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_com(     opj_j2k_t *p_j2k,
                                                         opj_stream_private_t *p_stream,
                                                         opj_event_mgr_t * p_manager
                             )
@@ -2328,7 +2365,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_cod(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_cod(     opj_j2k_t *p_j2k,
                                                         opj_stream_private_t *p_stream,
                                                         opj_event_mgr_t * p_manager )
 {
@@ -2514,7 +2551,7 @@
 }
 
 #if 0
-OPJ_BOOL opj_j2k_write_coc( opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_coc( opj_j2k_t *p_j2k,
                                                 OPJ_UINT32 p_comp_no,
                                                 opj_stream_private_t *p_stream,
                                                 opj_event_mgr_t * p_manager )
@@ -2561,7 +2598,7 @@
 #endif
 
 #if 0
-void opj_j2k_write_coc_in_memory(   opj_j2k_t *p_j2k,
+static void opj_j2k_write_coc_in_memory(   opj_j2k_t *p_j2k,
                                                 OPJ_UINT32 p_comp_no,
                                                 OPJ_BYTE * p_data,
                                                 OPJ_UINT32 * p_data_written,
@@ -2607,7 +2644,7 @@
 }
 #endif
 
-OPJ_UINT32 opj_j2k_get_max_coc_size(opj_j2k_t *p_j2k)
+static OPJ_UINT32 opj_j2k_get_max_coc_size(opj_j2k_t *p_j2k)
 {
         OPJ_UINT32 i,j;
         OPJ_UINT32 l_nb_comp;
@@ -2689,7 +2726,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_qcd(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_qcd(     opj_j2k_t *p_j2k,
                                                         opj_stream_private_t *p_stream,
                                                         opj_event_mgr_t * p_manager
                             )
@@ -2780,7 +2817,7 @@
 }
 
 #if 0
-OPJ_BOOL opj_j2k_write_qcc(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_qcc(     opj_j2k_t *p_j2k,
                                                 OPJ_UINT32 p_comp_no,
                                                 opj_stream_private_t *p_stream,
                                                 opj_event_mgr_t * p_manager
@@ -2821,7 +2858,7 @@
 #endif
 
 #if 0
-void opj_j2k_write_qcc_in_memory(   opj_j2k_t *p_j2k,
+static void opj_j2k_write_qcc_in_memory(   opj_j2k_t *p_j2k,
                                                                 OPJ_UINT32 p_comp_no,
                                                                 OPJ_BYTE * p_data,
                                                                 OPJ_UINT32 * p_data_written,
@@ -2871,7 +2908,7 @@
 }
 #endif
 
-OPJ_UINT32 opj_j2k_get_max_qcc_size (opj_j2k_t *p_j2k)
+static OPJ_UINT32 opj_j2k_get_max_qcc_size (opj_j2k_t *p_j2k)
 {
         return opj_j2k_get_max_coc_size(p_j2k);
 }
@@ -2963,7 +3000,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_poc(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_poc(     opj_j2k_t *p_j2k,
                                                         opj_stream_private_t *p_stream,
                                                         opj_event_mgr_t * p_manager
                             )
@@ -3014,7 +3051,7 @@
         return OPJ_TRUE;
 }
 
-void opj_j2k_write_poc_in_memory(   opj_j2k_t *p_j2k,
+static void opj_j2k_write_poc_in_memory(   opj_j2k_t *p_j2k,
                                                                 OPJ_BYTE * p_data,
                                                                 OPJ_UINT32 * p_data_written,
                                                                 opj_event_mgr_t * p_manager
@@ -3089,7 +3126,7 @@
         *p_data_written = l_poc_size;
 }
 
-OPJ_UINT32 opj_j2k_get_max_poc_size(opj_j2k_t *p_j2k)
+static OPJ_UINT32 opj_j2k_get_max_poc_size(opj_j2k_t *p_j2k)
 {
         opj_tcp_t * l_tcp = 00;
         OPJ_UINT32 l_nb_tiles = 0;
@@ -3109,7 +3146,7 @@
         return 4 + 9 * l_max_poc;
 }
 
-OPJ_UINT32 opj_j2k_get_max_toc_size (opj_j2k_t *p_j2k)
+static OPJ_UINT32 opj_j2k_get_max_toc_size (opj_j2k_t *p_j2k)
 {
         OPJ_UINT32 i;
         OPJ_UINT32 l_nb_tiles;
@@ -3128,7 +3165,7 @@
         return 12 * l_max;
 }
 
-OPJ_UINT32 opj_j2k_get_specific_header_sizes(opj_j2k_t *p_j2k)
+static OPJ_UINT32 opj_j2k_get_specific_header_sizes(opj_j2k_t *p_j2k)
 {
         OPJ_UINT32 l_nb_bytes = 0;
         OPJ_UINT32 l_nb_comps;
@@ -3458,382 +3495,220 @@
         return OPJ_TRUE;
 }
 
-#if 0
-OPJ_BOOL j2k_read_ppm_v2 (
-                                                opj_j2k_t *p_j2k,
-                                                OPJ_BYTE * p_header_data,
-                                                OPJ_UINT32 p_header_size,
-                                                struct opj_event_mgr * p_manager
-                                        )
+/**
+ * Reads a PPM marker (Packed packet headers, main header)
+ *
+ * @param       p_header_data   the data contained in the POC box.
+ * @param       p_j2k                   the jpeg2000 codec.
+ * @param       p_header_size   the size of the data contained in the POC marker.
+ * @param       p_manager               the user event manager.
+ */
+
+static OPJ_BOOL opj_j2k_read_ppm (
+																	opj_j2k_t *p_j2k,
+																	OPJ_BYTE * p_header_data,
+																	OPJ_UINT32 p_header_size,
+																	opj_event_mgr_t * p_manager )
 {
+	opj_cp_t *l_cp = 00;
+	OPJ_UINT32 l_Z_ppm;
+	
+	/* preconditions */
+	assert(p_header_data != 00);
+	assert(p_j2k != 00);
+	assert(p_manager != 00);
+	
+	/* We need to have the Z_ppm element + 1 byte of Nppm/Ippm at minimum */
+	if (p_header_size < 2) {
+		opj_event_msg(p_manager, EVT_ERROR, "Error reading PPM marker\n");
+		return OPJ_FALSE;
+	}
+	
+	l_cp = &(p_j2k->m_cp);
+	l_cp->ppm = 1;
+	
+	opj_read_bytes(p_header_data,&l_Z_ppm,1);               /* Z_ppm */
+	++p_header_data;
+	--p_header_size;
+	
+	/* check allocation needed */
+	if (l_cp->ppm_markers == NULL) { /* first PPM marker */
+		OPJ_UINT32 l_newCount = l_Z_ppm + 1U; /* can't overflow, l_Z_ppm is UINT8 */
+		assert(l_cp->ppm_markers_count == 0U);
+		
+		l_cp->ppm_markers = (opj_ppx *) opj_calloc(l_newCount, sizeof(opj_ppx));
+		if (l_cp->ppm_markers == NULL) {
+			opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n");
+			return OPJ_FALSE;
+		}
+		l_cp->ppm_markers_count = l_newCount;
+	} else if (l_cp->ppm_markers_count <= l_Z_ppm) {
+		OPJ_UINT32 l_newCount = l_Z_ppm + 1U; /* can't overflow, l_Z_ppm is UINT8 */
+		opj_ppx *new_ppm_markers;
+		new_ppm_markers = (opj_ppx *) opj_realloc(l_cp->ppm_markers, l_newCount * sizeof(opj_ppx));
+		if (new_ppm_markers == NULL) {
+			/* clean up to be done on l_cp destruction */
+			opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n");
+			return OPJ_FALSE;
+		}
+		l_cp->ppm_markers = new_ppm_markers;
+		memset(l_cp->ppm_markers + l_cp->ppm_markers_count, 0, (l_newCount - l_cp->ppm_markers_count) * sizeof(opj_ppx));
+		l_cp->ppm_markers_count = l_newCount;
+	}
+	
+	if (l_cp->ppm_markers[l_Z_ppm].m_data != NULL) {
+		/* clean up to be done on l_cp destruction */
+		opj_event_msg(p_manager, EVT_ERROR, "Zppm %u already read\n", l_Z_ppm);
+		return OPJ_FALSE;
+	}
+	
+	l_cp->ppm_markers[l_Z_ppm].m_data = opj_malloc(p_header_size);
+	if (l_cp->ppm_markers[l_Z_ppm].m_data == NULL) {
+		/* clean up to be done on l_cp destruction */
+		opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n");
+		return OPJ_FALSE;
+	}
+	l_cp->ppm_markers[l_Z_ppm].m_data_size = p_header_size;
+	memcpy(l_cp->ppm_markers[l_Z_ppm].m_data, p_header_data, p_header_size);
 
-        opj_cp_t *l_cp = 00;
-        OPJ_UINT32 l_remaining_data, l_Z_ppm, l_N_ppm;
-
-        /* preconditions */
-        assert(p_header_data != 00);
-        assert(p_j2k != 00);
-        assert(p_manager != 00);
-
-        if (p_header_size < 1) {
-                opj_event_msg(p_manager, EVT_ERROR, "Error reading PPM marker\n");
-                return OPJ_FALSE;
-        }
-
-        l_cp = &(p_j2k->m_cp);
-        l_cp->ppm = 1;
-
-        opj_read_bytes(p_header_data,&l_Z_ppm,1);               /* Z_ppm */
-        ++p_header_data;
-        --p_header_size;
-
-        /* First PPM marker */
-        if (l_Z_ppm == 0) {
-                if (p_header_size < 4) {
-                        opj_event_msg(p_manager, EVT_ERROR, "Error reading PPM marker\n");
-                        return OPJ_FALSE;
-                }
-
-                opj_read_bytes(p_header_data,&l_N_ppm,4);               /* N_ppm */
-                p_header_data+=4;
-                p_header_size-=4;
-
-                /* First PPM marker: Initialization */
-                l_cp->ppm_len = l_N_ppm;
-                l_cp->ppm_data_size = 0;
-
-                l_cp->ppm_buffer = (OPJ_BYTE *) opj_malloc(l_cp->ppm_len);
-                if (l_cp->ppm_buffer == 00) {
-                        opj_event_msg(p_manager, EVT_ERROR, "Not enough memory reading ppm marker\n");
-                        return OPJ_FALSE;
-                }
-                memset(l_cp->ppm_buffer,0,l_cp->ppm_len);
-
-                l_cp->ppm_data = l_cp->ppm_buffer;
-        }
-
-        while (1) {
-                if (l_cp->ppm_data_size == l_cp->ppm_len) {
-                        if (p_header_size >= 4) {
-                                /* read a N_ppm */
-                                opj_read_bytes(p_header_data,&l_N_ppm,4);               /* N_ppm */
-                                p_header_data+=4;
-                                p_header_size-=4;
-                                l_cp->ppm_len += l_N_ppm ;
-
-                                OPJ_BYTE *new_ppm_buffer = (OPJ_BYTE *) opj_realloc(l_cp->ppm_buffer, l_cp->ppm_len);
-                                if (! new_ppm_buffer) {
-                                        opj_free(l_cp->ppm_buffer);
-                                        l_cp->ppm_buffer = NULL;
-                                        l_cp->ppm_len = 0;
-                                        l_cp->ppm_data = NULL;
-                                        opj_event_msg(p_manager, EVT_ERROR, "Not enough memory reading ppm marker\n");
-                                        return OPJ_FALSE;
-                                }
-                                l_cp->ppm_buffer = new_ppm_buffer;
-                                memset(l_cp->ppm_buffer+l_cp->ppm_data_size,0,l_N_ppm);
-                                l_cp->ppm_data = l_cp->ppm_buffer;
-                        }
-                        else {
-                                return OPJ_FALSE;
-                        }
-                }
-
-                l_remaining_data = l_cp->ppm_len - l_cp->ppm_data_size;
-
-                if (l_remaining_data <= p_header_size) {
-                        /* we must store less information than available in the packet */
-                        memcpy(l_cp->ppm_buffer + l_cp->ppm_data_size , p_header_data , l_remaining_data);
-                        l_cp->ppm_data_size = l_cp->ppm_len;
-                        p_header_size -= l_remaining_data;
-                        p_header_data += l_remaining_data;
-                }
-                else {
-                        memcpy(l_cp->ppm_buffer + l_cp->ppm_data_size , p_header_data , p_header_size);
-                        l_cp->ppm_data_size += p_header_size;
-                        p_header_data += p_header_size;
-                        p_header_size = 0;
-                        break;
-                }
-        }
-
-        return OPJ_TRUE;
+	return OPJ_TRUE;
 }
-#endif
 
-OPJ_BOOL j2k_read_ppm_v3 (
-                                                opj_j2k_t *p_j2k,
-                                                OPJ_BYTE * p_header_data,
-                                                OPJ_UINT32 p_header_size,
-                                                struct opj_event_mgr * p_manager
-                                        )
+/**
+ * Merges all PPM markers read (Packed headers, main header)
+ *
+ * @param       p_cp      main coding parameters.
+ * @param       p_manager the user event manager.
+ */
+static OPJ_BOOL opj_j2k_merge_ppm ( opj_cp_t *p_cp, opj_event_mgr_t * p_manager )
 {
-        opj_cp_t *l_cp = 00;
-        OPJ_UINT32 l_remaining_data, l_Z_ppm, l_N_ppm;
+	OPJ_UINT32 i, l_ppm_data_size, l_N_ppm_remaining;
+	
+	/* preconditions */
+	assert(p_cp != 00);
+	assert(p_manager != 00);
+	assert(p_cp->ppm_buffer == NULL);
+	
+	if (p_cp->ppm == 0U) {
+		return OPJ_TRUE;
+	}
+	
+	l_ppm_data_size = 0U;
+	l_N_ppm_remaining = 0U;
+	for (i = 0U; i < p_cp->ppm_markers_count; ++i) {
+		if (p_cp->ppm_markers[i].m_data != NULL) { /* standard doesn't seem to require contiguous Zppm */
+			OPJ_UINT32 l_N_ppm;
+			OPJ_UINT32 l_data_size = p_cp->ppm_markers[i].m_data_size;
+			const OPJ_BYTE* l_data = p_cp->ppm_markers[i].m_data;
+			
+			if (l_N_ppm_remaining >= l_data_size) {
+				l_N_ppm_remaining -= l_data_size;
+				l_data_size = 0U;
+			} else {
+				l_data += l_N_ppm_remaining;
+				l_data_size -= l_N_ppm_remaining;
+				l_N_ppm_remaining = 0U;
+			}
+			
+			if (l_data_size > 0U) {
+				do
+				{
+					/* read Nppm */
+					if (l_data_size < 4U) {
+						/* clean up to be done on l_cp destruction */
+						opj_event_msg(p_manager, EVT_ERROR, "Not enough bytes to read Nppm\n");
+						return OPJ_FALSE;
+					}
+					opj_read_bytes(l_data, &l_N_ppm, 4);
+					l_data+=4;
+					l_data_size-=4;
+					l_ppm_data_size += l_N_ppm; /* can't overflow, max 256 markers of max 65536 bytes, that is when PPM markers are not corrupted which is checked elsewhere */
+					
+					if (l_data_size >= l_N_ppm) {
+						l_data_size -= l_N_ppm;
+						l_data += l_N_ppm;
+					} else {
+						l_N_ppm_remaining = l_N_ppm - l_data_size;
+						l_data_size = 0U;
+					}
+				} while (l_data_size > 0U);
+			}
+		}
+	}
+	
+	if (l_N_ppm_remaining != 0U) {
+		/* clean up to be done on l_cp destruction */
+		opj_event_msg(p_manager, EVT_ERROR, "Corrupted PPM markers\n");
+		return OPJ_FALSE;
+	}
+	
+	p_cp->ppm_buffer = (OPJ_BYTE *) opj_malloc(l_ppm_data_size);
+	if (p_cp->ppm_buffer == 00) {
+		opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n");
+		return OPJ_FALSE;
+	}
+	p_cp->ppm_len = l_ppm_data_size;
+	l_ppm_data_size = 0U;
+	l_N_ppm_remaining = 0U;
+	for (i = 0U; i < p_cp->ppm_markers_count; ++i) {
+		if (p_cp->ppm_markers[i].m_data != NULL) { /* standard doesn't seem to require contiguous Zppm */
+			OPJ_UINT32 l_N_ppm;
+			OPJ_UINT32 l_data_size = p_cp->ppm_markers[i].m_data_size;
+			const OPJ_BYTE* l_data = p_cp->ppm_markers[i].m_data;
+			
+			if (l_N_ppm_remaining >= l_data_size) {
+				memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_data_size);
+				l_ppm_data_size += l_data_size;
+				l_N_ppm_remaining -= l_data_size;
+				l_data_size = 0U;
+			} else {
+				memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_N_ppm_remaining);
+				l_ppm_data_size += l_N_ppm_remaining;
+				l_data += l_N_ppm_remaining;
+				l_data_size -= l_N_ppm_remaining;
+				l_N_ppm_remaining = 0U;
+			}
 
-        /* preconditions */
-        assert(p_header_data != 00);
-        assert(p_j2k != 00);
-        assert(p_manager != 00);
-
-        /* Minimum size of PPM marker is equal to the size of Zppm element */
-        if (p_header_size < 1) {
-                opj_event_msg(p_manager, EVT_ERROR, "Error reading PPM marker\n");
-                return OPJ_FALSE;
-        }
-
-        l_cp = &(p_j2k->m_cp);
-        l_cp->ppm = 1;
-
-        opj_read_bytes(p_header_data,&l_Z_ppm,1);               /* Z_ppm */
-        ++p_header_data;
-        --p_header_size;
-
-        /* First PPM marker */
-        if (l_Z_ppm == 0) {
-                if (l_cp->ppm_data != NULL) {
-                        opj_event_msg(p_manager, EVT_ERROR, "Zppm O already processed. Found twice.\n");
-                        opj_free(l_cp->ppm_data);
-                        l_cp->ppm_data = NULL;
-                        l_cp->ppm_buffer = NULL;
-                        l_cp->ppm = 0; /* do not use PPM */
-                        return OPJ_FALSE;
-                }
-                /* We need now at least the Nppm^0 element */
-                if (p_header_size < 4) {
-                        opj_event_msg(p_manager, EVT_ERROR, "Error reading PPM marker\n");
-                        return OPJ_FALSE;
-                }
-
-                opj_read_bytes(p_header_data,&l_N_ppm,4);               /* First N_ppm */
-                p_header_data+=4;
-                p_header_size-=4;
-
-                /* sanity check: how much bytes is left for Ippm */
-                if( p_header_size < l_N_ppm )
-                  {
-                  opj_event_msg(p_manager, EVT_ERROR, "Not enough bytes (%u) to hold Ippm series (%u), Index (%d)\n", p_header_size, l_N_ppm, l_Z_ppm );
-                  opj_free(l_cp->ppm_data);
-                  l_cp->ppm_data = NULL;
-                  l_cp->ppm_buffer = NULL;
-                  l_cp->ppm = 0; /* do not use PPM */
-                  return OPJ_FALSE;
-                  }
-
-                /* First PPM marker: Initialization */
-                l_cp->ppm_len = l_N_ppm;
-                l_cp->ppm_data_read = 0;
-
-                l_cp->ppm_data = (OPJ_BYTE *) opj_calloc(1,l_cp->ppm_len);
-                l_cp->ppm_buffer = l_cp->ppm_data;
-                if (l_cp->ppm_data == 00) {
-                        opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read ppm marker\n");
-                        return OPJ_FALSE;
-                }
-
-                l_cp->ppm_data_current = l_cp->ppm_data;
-
-                /*l_cp->ppm_data = l_cp->ppm_buffer;*/
-        }
-        else {
-                if (p_header_size < 4) {
-                        opj_event_msg(p_manager, EVT_WARNING, "Empty PPM marker\n");
-                        return OPJ_TRUE;
-                }
-                else {
-                        /* Uncompleted Ippm series in the previous PPM marker?*/
-                        if (l_cp->ppm_data_read < l_cp->ppm_len) {
-                                /* Get the place where add the remaining Ippm series*/
-                                l_cp->ppm_data_current = &(l_cp->ppm_data[l_cp->ppm_data_read]);
-                                l_N_ppm = l_cp->ppm_len - l_cp->ppm_data_read;
-                        }
-                        else {
-                                OPJ_BYTE *new_ppm_data;
-                                opj_read_bytes(p_header_data,&l_N_ppm,4);               /* First N_ppm */
-                                p_header_data+=4;
-                                p_header_size-=4;
-
-                                /* sanity check: how much bytes is left for Ippm */
-                                if( p_header_size < l_N_ppm )
-                                  {
-                                  opj_event_msg(p_manager, EVT_ERROR, "Not enough bytes (%u) to hold Ippm series (%u), Index (%d)\n", p_header_size, l_N_ppm, l_Z_ppm );
-                                  opj_free(l_cp->ppm_data);
-                                  l_cp->ppm_data = NULL;
-                                  l_cp->ppm_buffer = NULL;
-                                  l_cp->ppm = 0; /* do not use PPM */
-                                  return OPJ_FALSE;
-                                  }
-                                /* Increase the size of ppm_data to add the new Ippm series*/
-                                assert(l_cp->ppm_data == l_cp->ppm_buffer && "We need ppm_data and ppm_buffer to be the same when reallocating");
-                                new_ppm_data = (OPJ_BYTE *) opj_realloc(l_cp->ppm_data, l_cp->ppm_len + l_N_ppm);
-                                if (! new_ppm_data) {
-                                        opj_free(l_cp->ppm_data);
-                                        l_cp->ppm_data = NULL;
-                                        l_cp->ppm_buffer = NULL;  /* TODO: no need for a new local variable: ppm_buffer and ppm_data are enough */
-                                        l_cp->ppm_len = 0;
-                                        opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to increase the size of ppm_data to add the new Ippm series\n");
-                                        return OPJ_FALSE;
-                                }
-                                l_cp->ppm_data = new_ppm_data;
-                                l_cp->ppm_buffer = l_cp->ppm_data;
-
-                                /* Keep the position of the place where concatenate the new series*/
-                                l_cp->ppm_data_current = &(l_cp->ppm_data[l_cp->ppm_len]);
-                                l_cp->ppm_len += l_N_ppm;
-                        }
-                }
-        }
-
-        l_remaining_data = p_header_size;
-
-        while (l_remaining_data >= l_N_ppm) {
-                /* read a complete Ippm series*/
-                memcpy(l_cp->ppm_data_current, p_header_data, l_N_ppm);
-                p_header_size -= l_N_ppm;
-                p_header_data += l_N_ppm;
-
-                l_cp->ppm_data_read += l_N_ppm; /* Increase the number of data read*/
-
-                if (p_header_size)
-                {
-                        if (p_header_size < 4) {
-                                opj_free(l_cp->ppm_data);
-                                l_cp->ppm_data = NULL;
-                                l_cp->ppm_buffer = NULL;  /* TODO: no need for a new local variable: ppm_buffer and ppm_data are enough */
-                                l_cp->ppm_len = 0;
-                                l_cp->ppm = 0;
-                                opj_event_msg(p_manager, EVT_ERROR, "Error reading PPM marker\n");
-                                return OPJ_FALSE;
-                        }
-                        opj_read_bytes(p_header_data,&l_N_ppm,4);               /* N_ppm^i */
-                        p_header_data+=4;
-                        p_header_size-=4;
-                }
-                else {
-                        l_remaining_data = p_header_size;
-                        break;
-                }
-
-                l_remaining_data = p_header_size;
-
-                /* Next Ippm series is a complete series ?*/
-                if (l_remaining_data >= l_N_ppm) {
-                        OPJ_BYTE *new_ppm_data;
-                        /* Increase the size of ppm_data to add the new Ippm series*/
-                        assert(l_cp->ppm_data == l_cp->ppm_buffer && "We need ppm_data and ppm_buffer to be the same when reallocating");
-                        /* Overflow check */
-                        if ((l_cp->ppm_len + l_N_ppm) < l_N_ppm) {
-                                opj_free(l_cp->ppm_data);
-                                l_cp->ppm_data = NULL;
-                                l_cp->ppm_buffer = NULL;  /* TODO: no need for a new local variable: ppm_buffer and ppm_data are enough */
-                                l_cp->ppm_len = 0;
-                                opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to increase the size of ppm_data to add the new (complete) Ippm series\n");
-                                return OPJ_FALSE;
-                        }
-                        new_ppm_data = (OPJ_BYTE *) opj_realloc(l_cp->ppm_data, l_cp->ppm_len + l_N_ppm);
-                        if (! new_ppm_data) {
-                                opj_free(l_cp->ppm_data);
-                                l_cp->ppm_data = NULL;
-                                l_cp->ppm_buffer = NULL;  /* TODO: no need for a new local variable: ppm_buffer and ppm_data are enough */
-                                l_cp->ppm_len = 0;
-                                opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to increase the size of ppm_data to add the new (complete) Ippm series\n");
-                                return OPJ_FALSE;
-                        }
-                        l_cp->ppm_data = new_ppm_data;
-                        l_cp->ppm_buffer = l_cp->ppm_data;
-
-                        /* Keep the position of the place where concatenate the new series */
-                        l_cp->ppm_data_current = &(l_cp->ppm_data[l_cp->ppm_len]);
-                        l_cp->ppm_len += l_N_ppm;
-                }
-
-        }
-
-        /* Need to read an incomplete Ippm series*/
-        if (l_remaining_data) {
-                OPJ_BYTE *new_ppm_data;
-                assert(l_cp->ppm_data == l_cp->ppm_buffer && "We need ppm_data and ppm_buffer to be the same when reallocating");
-
-                /* Overflow check */
-                if ((l_cp->ppm_len + l_N_ppm) < l_N_ppm) {
-                        opj_free(l_cp->ppm_data);
-                        l_cp->ppm_data = NULL;
-                        l_cp->ppm_buffer = NULL;  /* TODO: no need for a new local variable: ppm_buffer and ppm_data are enough */
-                        l_cp->ppm_len = 0;
-                        opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to increase the size of ppm_data to add the new (complete) Ippm series\n");
-                        return OPJ_FALSE;
-                }
-                new_ppm_data = (OPJ_BYTE *) opj_realloc(l_cp->ppm_data, l_cp->ppm_len + l_N_ppm);
-                if (! new_ppm_data) {
-                        opj_free(l_cp->ppm_data);
-                        l_cp->ppm_data = NULL;
-                        l_cp->ppm_buffer = NULL;  /* TODO: no need for a new local variable: ppm_buffer and ppm_data are enough */
-                        l_cp->ppm_len = 0;
-                        opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to increase the size of ppm_data to add the new (incomplete) Ippm series\n");
-                        return OPJ_FALSE;
-                }
-                l_cp->ppm_data = new_ppm_data;
-                l_cp->ppm_buffer = l_cp->ppm_data;
-
-                /* Keep the position of the place where concatenate the new series*/
-                l_cp->ppm_data_current = &(l_cp->ppm_data[l_cp->ppm_len]);
-                l_cp->ppm_len += l_N_ppm;
-
-                /* Read incomplete Ippm series*/
-                memcpy(l_cp->ppm_data_current, p_header_data, l_remaining_data);
-                p_header_size -= l_remaining_data;
-                p_header_data += l_remaining_data;
-
-                l_cp->ppm_data_read += l_remaining_data; /* Increase the number of data read*/
-        }
-
-#ifdef CLEAN_MSD
-
-                if (l_cp->ppm_data_size == l_cp->ppm_len) {
-                        if (p_header_size >= 4) {
-                                /* read a N_ppm*/
-                                opj_read_bytes(p_header_data,&l_N_ppm,4);               /* N_ppm */
-                                p_header_data+=4;
-                                p_header_size-=4;
-                                l_cp->ppm_len += l_N_ppm ;
-
-                                OPJ_BYTE *new_ppm_buffer = (OPJ_BYTE *) opj_realloc(l_cp->ppm_buffer, l_cp->ppm_len);
-                                if (! new_ppm_buffer) {
-                                        opj_free(l_cp->ppm_buffer);
-                                        l_cp->ppm_buffer = NULL;
-                                        l_cp->ppm_len = 0;
-                                        opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read ppm marker\n");
-                                        return OPJ_FALSE;
-                                }
-                                l_cp->ppm_buffer = new_ppm_buffer;
-                                memset(l_cp->ppm_buffer+l_cp->ppm_data_size,0,l_N_ppm);
-
-                                l_cp->ppm_data = l_cp->ppm_buffer;
-                        }
-                        else {
-                                return OPJ_FALSE;
-                        }
-                }
-
-                l_remaining_data = l_cp->ppm_len - l_cp->ppm_data_size;
-
-                if (l_remaining_data <= p_header_size) {
-                        /* we must store less information than available in the packet */
-                        memcpy(l_cp->ppm_buffer + l_cp->ppm_data_size , p_header_data , l_remaining_data);
-                        l_cp->ppm_data_size = l_cp->ppm_len;
-                        p_header_size -= l_remaining_data;
-                        p_header_data += l_remaining_data;
-                }
-                else {
-                        memcpy(l_cp->ppm_buffer + l_cp->ppm_data_size , p_header_data , p_header_size);
-                        l_cp->ppm_data_size += p_header_size;
-                        p_header_data += p_header_size;
-                        p_header_size = 0;
-                        break;
-                }
-        }
-#endif
-        return OPJ_TRUE;
+			if (l_data_size > 0U) {
+				do
+				{
+					/* read Nppm */
+					if (l_data_size < 4U) {
+						/* clean up to be done on l_cp destruction */
+						opj_event_msg(p_manager, EVT_ERROR, "Not enough bytes to read Nppm\n");
+						return OPJ_FALSE;
+					}
+					opj_read_bytes(l_data, &l_N_ppm, 4);
+					l_data+=4;
+					l_data_size-=4;
+					
+					if (l_data_size >= l_N_ppm) {
+						memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_N_ppm);
+						l_ppm_data_size += l_N_ppm;
+						l_data_size -= l_N_ppm;
+						l_data += l_N_ppm;
+					} else {
+						memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_data_size);
+						l_ppm_data_size += l_data_size;
+						l_N_ppm_remaining = l_N_ppm - l_data_size;
+						l_data_size = 0U;
+					}
+				} while (l_data_size > 0U);
+			}
+			opj_free(p_cp->ppm_markers[i].m_data);
+			p_cp->ppm_markers[i].m_data = NULL;
+			p_cp->ppm_markers[i].m_data_size = 0U;
+		}
+	}
+	
+	p_cp->ppm_data = p_cp->ppm_buffer;
+	p_cp->ppm_data_size = p_cp->ppm_len;
+	
+	p_cp->ppm_markers_count = 0U;
+	opj_free(p_cp->ppm_markers);
+	p_cp->ppm_markers = NULL;
+	
+	return OPJ_TRUE;
 }
 
 /**
@@ -3850,77 +3725,127 @@
                                     opj_event_mgr_t * p_manager
                                     )
 {
-        opj_cp_t *l_cp = 00;
-        opj_tcp_t *l_tcp = 00;
-        OPJ_UINT32 l_Z_ppt;
+	opj_cp_t *l_cp = 00;
+	opj_tcp_t *l_tcp = 00;
+	OPJ_UINT32 l_Z_ppt;
 
-        /* preconditions */
-        assert(p_header_data != 00);
-        assert(p_j2k != 00);
-        assert(p_manager != 00);
+	/* preconditions */
+	assert(p_header_data != 00);
+	assert(p_j2k != 00);
+	assert(p_manager != 00);
 
-        /* We need to have the Z_ppt element at minimum */
-        if (p_header_size < 1) {
-                opj_event_msg(p_manager, EVT_ERROR, "Error reading PPT marker\n");
-                return OPJ_FALSE;
-        }
+	/* We need to have the Z_ppt element + 1 byte of Ippt at minimum */
+	if (p_header_size < 2) {
+		opj_event_msg(p_manager, EVT_ERROR, "Error reading PPT marker\n");
+		return OPJ_FALSE;
+	}
 
-        l_cp = &(p_j2k->m_cp);
-        if (l_cp->ppm){
-                opj_event_msg(p_manager, EVT_ERROR, "Error reading PPT marker: packet header have been previously found in the main header (PPM marker).\n");
-                return OPJ_FALSE;
-        }
+	l_cp = &(p_j2k->m_cp);
+	if (l_cp->ppm){
+		opj_event_msg(p_manager, EVT_ERROR, "Error reading PPT marker: packet header have been previously found in the main header (PPM marker).\n");
+		return OPJ_FALSE;
+	}
 
-        l_tcp = &(l_cp->tcps[p_j2k->m_current_tile_number]);
-        l_tcp->ppt = 1;
+	l_tcp = &(l_cp->tcps[p_j2k->m_current_tile_number]);
+	l_tcp->ppt = 1;
 
-        opj_read_bytes(p_header_data,&l_Z_ppt,1);               /* Z_ppt */
-        ++p_header_data;
-        --p_header_size;
-
-        /* Allocate buffer to read the packet header */
-        if (l_Z_ppt == 0) {
-                /* First PPT marker */
-                l_tcp->ppt_data_size = 0;
-                l_tcp->ppt_len = p_header_size;
-
-                opj_free(l_tcp->ppt_buffer);
-                l_tcp->ppt_buffer = (OPJ_BYTE *) opj_calloc(l_tcp->ppt_len, sizeof(OPJ_BYTE) );
-                if (l_tcp->ppt_buffer == 00) {
-                        opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n");
-                        return OPJ_FALSE;
-                }
-                l_tcp->ppt_data = l_tcp->ppt_buffer;
-
-                /* memset(l_tcp->ppt_buffer,0,l_tcp->ppt_len); */
-        }
-        else {
-                OPJ_BYTE *new_ppt_buffer;
-                l_tcp->ppt_len += p_header_size;
-
-                new_ppt_buffer = (OPJ_BYTE *) opj_realloc(l_tcp->ppt_buffer, l_tcp->ppt_len);
-                if (! new_ppt_buffer) {
-                        opj_free(l_tcp->ppt_buffer);
-                        l_tcp->ppt_buffer = NULL;
-                        l_tcp->ppt_len = 0;
-                        opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n");
-                        return OPJ_FALSE;
-                }
-                l_tcp->ppt_buffer = new_ppt_buffer;
-                l_tcp->ppt_data = l_tcp->ppt_buffer;
-
-                memset(l_tcp->ppt_buffer+l_tcp->ppt_data_size,0,p_header_size);
-        }
-
-        /* Read packet header from buffer */
-        memcpy(l_tcp->ppt_buffer+l_tcp->ppt_data_size,p_header_data,p_header_size);
-
-        l_tcp->ppt_data_size += p_header_size;
-
-        return OPJ_TRUE;
+	opj_read_bytes(p_header_data,&l_Z_ppt,1);               /* Z_ppt */
+	++p_header_data;
+	--p_header_size;
+	
+	/* check allocation needed */
+	if (l_tcp->ppt_markers == NULL) { /* first PPT marker */
+		OPJ_UINT32 l_newCount = l_Z_ppt + 1U; /* can't overflow, l_Z_ppt is UINT8 */
+		assert(l_tcp->ppt_markers_count == 0U);
+		
+		l_tcp->ppt_markers = (opj_ppx *) opj_calloc(l_newCount, sizeof(opj_ppx));
+		if (l_tcp->ppt_markers == NULL) {
+			opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n");
+			return OPJ_FALSE;
+		}
+		l_tcp->ppt_markers_count = l_newCount;
+	} else if (l_tcp->ppt_markers_count <= l_Z_ppt) {
+		OPJ_UINT32 l_newCount = l_Z_ppt + 1U; /* can't overflow, l_Z_ppt is UINT8 */
+		opj_ppx *new_ppt_markers;
+		new_ppt_markers = (opj_ppx *) opj_realloc(l_tcp->ppt_markers, l_newCount * sizeof(opj_ppx));
+		if (new_ppt_markers == NULL) {
+			/* clean up to be done on l_tcp destruction */
+			opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n");
+			return OPJ_FALSE;
+		}
+		l_tcp->ppt_markers = new_ppt_markers;
+		memset(l_tcp->ppt_markers + l_tcp->ppt_markers_count, 0, (l_newCount - l_tcp->ppt_markers_count) * sizeof(opj_ppx));
+		l_tcp->ppt_markers_count = l_newCount;
+	}
+	
+	if (l_tcp->ppt_markers[l_Z_ppt].m_data != NULL) {
+		/* clean up to be done on l_tcp destruction */
+		opj_event_msg(p_manager, EVT_ERROR, "Zppt %u already read\n", l_Z_ppt);
+		return OPJ_FALSE;
+	}
+	
+	l_tcp->ppt_markers[l_Z_ppt].m_data = opj_malloc(p_header_size);
+	if (l_tcp->ppt_markers[l_Z_ppt].m_data == NULL) {
+		/* clean up to be done on l_tcp destruction */
+		opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n");
+		return OPJ_FALSE;
+	}
+	l_tcp->ppt_markers[l_Z_ppt].m_data_size = p_header_size;
+	memcpy(l_tcp->ppt_markers[l_Z_ppt].m_data, p_header_data, p_header_size);
+	return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_tlm(     opj_j2k_t *p_j2k,
+/**
+ * Merges all PPT markers read (Packed packet headers, tile-part header)
+ *
+ * @param       p_tcp   the tile.
+ * @param       p_manager               the user event manager.
+ */
+static OPJ_BOOL opj_j2k_merge_ppt(opj_tcp_t *p_tcp, opj_event_mgr_t * p_manager)
+{
+	OPJ_UINT32 i, l_ppt_data_size;
+	/* preconditions */
+	assert(p_tcp != 00);
+	assert(p_manager != 00);
+	assert(p_tcp->ppt_buffer == NULL);
+	
+	if (p_tcp->ppt == 0U) {
+		return OPJ_TRUE;
+	}
+	
+	l_ppt_data_size = 0U;
+	for (i = 0U; i < p_tcp->ppt_markers_count; ++i) {
+		l_ppt_data_size += p_tcp->ppt_markers[i].m_data_size; /* can't overflow, max 256 markers of max 65536 bytes */
+	}
+	
+	p_tcp->ppt_buffer = (OPJ_BYTE *) opj_malloc(l_ppt_data_size);
+	if (p_tcp->ppt_buffer == 00) {
+		opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n");
+		return OPJ_FALSE;
+	}
+	p_tcp->ppt_len = l_ppt_data_size;
+	l_ppt_data_size = 0U;
+	for (i = 0U; i < p_tcp->ppt_markers_count; ++i) {
+		if (p_tcp->ppt_markers[i].m_data != NULL) { /* standard doesn't seem to require contiguous Zppt */
+			memcpy(p_tcp->ppt_buffer + l_ppt_data_size, p_tcp->ppt_markers[i].m_data, p_tcp->ppt_markers[i].m_data_size);
+			l_ppt_data_size += p_tcp->ppt_markers[i].m_data_size; /* can't overflow, max 256 markers of max 65536 bytes */
+			
+			opj_free(p_tcp->ppt_markers[i].m_data);
+			p_tcp->ppt_markers[i].m_data = NULL;
+			p_tcp->ppt_markers[i].m_data_size = 0U;
+		}
+	}
+	
+	p_tcp->ppt_markers_count = 0U;
+	opj_free(p_tcp->ppt_markers);
+	p_tcp->ppt_markers = NULL;
+	
+	p_tcp->ppt_data = p_tcp->ppt_buffer;
+	p_tcp->ppt_data_size = p_tcp->ppt_len;
+	return OPJ_TRUE;
+}
+
+static OPJ_BOOL opj_j2k_write_tlm(     opj_j2k_t *p_j2k,
                                                         opj_stream_private_t *p_stream,
                                                         opj_event_mgr_t * p_manager
                             )
@@ -3974,7 +3899,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_sot(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_sot(     opj_j2k_t *p_j2k,
                                                         OPJ_BYTE * p_data,
                                                         OPJ_UINT32 * p_data_written,
                                                         const opj_stream_private_t *p_stream,
@@ -4018,7 +3943,36 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_read_sot ( opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_get_sot_values(OPJ_BYTE *  p_header_data,
+																			 OPJ_UINT32  p_header_size,
+																			 OPJ_UINT32* p_tile_no,
+																			 OPJ_UINT32* p_tot_len,
+																			 OPJ_UINT32* p_current_part,
+																			 OPJ_UINT32* p_num_parts,
+																			 opj_event_mgr_t * p_manager )
+{
+	/* preconditions */
+	assert(p_header_data != 00);
+	assert(p_manager != 00);
+	
+	/* Size of this marker is fixed = 12 (we have already read marker and its size)*/
+	if (p_header_size != 8) {
+		opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n");
+		return OPJ_FALSE;
+	}
+	
+	opj_read_bytes(p_header_data,p_tile_no,2);      /* Isot */
+	p_header_data+=2;
+	opj_read_bytes(p_header_data,p_tot_len,4);      /* Psot */
+	p_header_data+=4;
+	opj_read_bytes(p_header_data,p_current_part,1); /* TPsot */
+	++p_header_data;
+	opj_read_bytes(p_header_data,p_num_parts ,1);   /* TNsot */
+	++p_header_data;
+	return OPJ_TRUE;
+}
+
+static OPJ_BOOL opj_j2k_read_sot ( opj_j2k_t *p_j2k,
                             OPJ_BYTE * p_header_data,
                             OPJ_UINT32 p_header_size,
                             opj_event_mgr_t * p_manager )
@@ -4030,19 +3984,16 @@
         OPJ_UINT32 l_tile_x,l_tile_y;
 
         /* preconditions */
-        assert(p_header_data != 00);
+	
         assert(p_j2k != 00);
         assert(p_manager != 00);
-
-        /* Size of this marker is fixed = 12 (we have already read marker and its size)*/
-        if (p_header_size != 8) {
+	
+        if (! opj_j2k_get_sot_values(p_header_data, p_header_size, &(p_j2k->m_current_tile_number), &l_tot_len, &l_current_part, &l_num_parts, p_manager)) {
                 opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n");
                 return OPJ_FALSE;
         }
 
         l_cp = &(p_j2k->m_cp);
-        opj_read_bytes(p_header_data,&(p_j2k->m_current_tile_number),2);                /* Isot */
-        p_header_data+=2;
 
         /* testcase 2.pdf.SIGFPE.706.1112 */
         if (p_j2k->m_current_tile_number >= l_cp->tw * l_cp->th) {
@@ -4085,9 +4036,6 @@
         /* Optimization possible here with a more complex data structure and with the removing of tiles */
         /* since the time taken by this function can only grow at the time */
 
-        opj_read_bytes(p_header_data,&l_tot_len,4);             /* Psot */
-        p_header_data+=4;
-
         /* PSot should be equal to zero or >=14 or <= 2^32-1 */
         if ((l_tot_len !=0 ) && (l_tot_len < 14) )
         {
@@ -4130,13 +4078,8 @@
                         p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1;
                 }
 
-                opj_read_bytes(p_header_data,&l_current_part ,1);       /* TPsot */
-                ++p_header_data;
-
-                opj_read_bytes(p_header_data,&l_num_parts ,1);          /* TNsot */
-                ++p_header_data;
-
                 if (l_num_parts != 0) { /* Number of tile-part header is provided by this tile-part header */
+                        l_num_parts += p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction;
                         /* Useful to manage the case of textGBR.jp2 file because two values of TNSot are allowed: the correct numbers of
                          * tile-parts for that tile and zero (A.4.2 of 15444-1 : 2002). */
                         if (l_tcp->m_nb_tile_parts) {
@@ -4286,7 +4229,7 @@
                 return OPJ_TRUE;
         }
 
-OPJ_BOOL opj_j2k_write_sod(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_sod(     opj_j2k_t *p_j2k,
                                                         opj_tcd_t * p_tile_coder,
                                                         OPJ_BYTE * p_data,
                                                         OPJ_UINT32 * p_data_written,
@@ -4360,7 +4303,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_read_sod (opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_read_sod (opj_j2k_t *p_j2k,
                            opj_stream_private_t *p_stream,
                                                    opj_event_mgr_t * p_manager
                            )
@@ -4408,7 +4351,7 @@
             }
             if (! *l_current_data) {
                 /* LH: oddly enough, in this path, l_tile_len!=0.
-                 * TODO: If this was consistant, we could simplify the code to only use realloc(), as realloc(0,...) default to malloc(0,...).
+                 * TODO: If this was consistent, we could simplify the code to only use realloc(), as realloc(0,...) default to malloc(0,...).
                  */
                 *l_current_data = (OPJ_BYTE*) opj_malloc(p_j2k->m_specific_param.m_decoder.m_sot_length);
             }
@@ -4481,7 +4424,7 @@
         return OPJ_TRUE;
 }
 
- OPJ_BOOL opj_j2k_write_rgn(opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_rgn(opj_j2k_t *p_j2k,
                             OPJ_UINT32 p_tile_no,
                             OPJ_UINT32 p_comp_no,
                             OPJ_UINT32 nb_comps,
@@ -4538,7 +4481,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_eoc(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_eoc(     opj_j2k_t *p_j2k,
                             opj_stream_private_t *p_stream,
                             opj_event_mgr_t * p_manager
                             )
@@ -4648,18 +4591,18 @@
 
 }
 
-OPJ_FLOAT32 opj_j2k_get_tp_stride (opj_tcp_t * p_tcp)
+static OPJ_FLOAT32 opj_j2k_get_tp_stride (opj_tcp_t * p_tcp)
 {
         return (OPJ_FLOAT32) ((p_tcp->m_nb_tile_parts - 1) * 14);
 }
 
-OPJ_FLOAT32 opj_j2k_get_default_stride (opj_tcp_t * p_tcp)
+static OPJ_FLOAT32 opj_j2k_get_default_stride (opj_tcp_t * p_tcp)
 {
     (void)p_tcp;
     return 0;
 }
 
-OPJ_BOOL opj_j2k_update_rates(  opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_update_rates(  opj_j2k_t *p_j2k,
                                                             opj_stream_private_t *p_stream,
                                                             opj_event_mgr_t * p_manager )
 {
@@ -4822,7 +4765,7 @@
 }
 
 #if 0
-OPJ_BOOL opj_j2k_read_eoc (     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_read_eoc (     opj_j2k_t *p_j2k,
                                                         opj_stream_private_t *p_stream,
                                                         opj_event_mgr_t * p_manager )
 {
@@ -4872,7 +4815,7 @@
 }
 #endif
 
-OPJ_BOOL opj_j2k_get_end_header(opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_get_end_header(opj_j2k_t *p_j2k,
                                                         struct opj_stream_private *p_stream,
                                                         struct opj_event_mgr * p_manager )
 {
@@ -4886,7 +4829,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_mct_data_group(  opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_mct_data_group(  opj_j2k_t *p_j2k,
                                                                         struct opj_stream_private *p_stream,
                                                                         struct opj_event_mgr * p_manager )
 {
@@ -4935,7 +4878,7 @@
 }
 
 #if 0
-OPJ_BOOL opj_j2k_write_all_coc(opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_all_coc(opj_j2k_t *p_j2k,
                                                                         struct opj_stream_private *p_stream,
                                                                         struct opj_event_mgr * p_manager )
 {
@@ -4958,7 +4901,7 @@
 #endif
 
 #if 0
-OPJ_BOOL opj_j2k_write_all_qcc(opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_all_qcc(opj_j2k_t *p_j2k,
                                                                         struct opj_stream_private *p_stream,
                                                                         struct opj_event_mgr * p_manager )
 {
@@ -4981,7 +4924,7 @@
 #endif
 
 
-OPJ_BOOL opj_j2k_write_regions( opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_regions( opj_j2k_t *p_j2k,
                                                         struct opj_stream_private *p_stream,
                                                         struct opj_event_mgr * p_manager )
 {
@@ -4995,7 +4938,7 @@
 
         l_tccp = p_j2k->m_cp.tcps->tccps;
 
-        for     (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno)  {
+        for (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno)  {
                 if (l_tccp->roishift) {
 
                         if (! opj_j2k_write_rgn(p_j2k,0,compno,p_j2k->m_private_image->numcomps,p_stream,p_manager)) {
@@ -5009,7 +4952,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_epc(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_epc(     opj_j2k_t *p_j2k,
                                                 struct opj_stream_private *p_stream,
                                                 struct opj_event_mgr * p_manager )
 {
@@ -5047,7 +4990,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_read_unk (     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_read_unk (     opj_j2k_t *p_j2k,
                                                         opj_stream_private_t *p_stream,
                                                         OPJ_UINT32 *output_marker,
                                                         opj_event_mgr_t * p_manager
@@ -5064,7 +5007,7 @@
 
         opj_event_msg(p_manager, EVT_WARNING, "Unknown marker\n");
 
-        while(1) {
+		for (;;) {
                 /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer*/
                 if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) {
                         opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n");
@@ -5109,7 +5052,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_mct_record(      opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_mct_record(      opj_j2k_t *p_j2k,
                                                                 opj_mct_data_t * p_mct_record,
                                                                 struct opj_stream_private *p_stream,
                                                                 struct opj_event_mgr * p_manager )
@@ -5281,7 +5224,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_mcc_record(      opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_mcc_record(      opj_j2k_t *p_j2k,
                                                                 struct opj_simple_mcc_decorrelation_data * p_mcc_record,
                                                                 struct opj_stream_private *p_stream,
                                                                 struct opj_event_mgr * p_manager )
@@ -5384,7 +5327,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_read_mcc (     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_read_mcc (     opj_j2k_t *p_j2k,
                                                 OPJ_BYTE * p_header_data,
                                                 OPJ_UINT32 p_header_size,
                                                 opj_event_mgr_t * p_manager )
@@ -5599,7 +5542,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_mco(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_mco(     opj_j2k_t *p_j2k,
                                                 struct opj_stream_private *p_stream,
                                                 struct opj_event_mgr * p_manager
                                   )
@@ -5616,8 +5559,7 @@
         assert(p_stream != 00);
 
         l_tcp =&(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]);
-        l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
-
+	
         l_mco_size = 5 + l_tcp->m_nb_mcc_records;
         if (l_mco_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
 
@@ -5632,6 +5574,8 @@
                 p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
                 p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mco_size;
         }
+        l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
+
 
         opj_write_bytes(l_current_data,J2K_MS_MCO,2);                   /* MCO */
         l_current_data += 2;
@@ -5639,14 +5583,13 @@
         opj_write_bytes(l_current_data,l_mco_size-2,2);                 /* Lmco */
         l_current_data += 2;
 
-        opj_write_bytes(l_current_data,l_tcp->m_nb_mcc_records,1);      /* Nmco : only one tranform stage*/
+        opj_write_bytes(l_current_data,l_tcp->m_nb_mcc_records,1);      /* Nmco : only one transform stage*/
         ++l_current_data;
 
         l_mcc_record = l_tcp->m_mcc_records;
-        for     (i=0;i<l_tcp->m_nb_mcc_records;++i) {
+        for (i=0;i<l_tcp->m_nb_mcc_records;++i) {
                 opj_write_bytes(l_current_data,l_mcc_record->m_index,1);/* Imco -> use the mcc indicated by 1*/
                 ++l_current_data;
-
                 ++l_mcc_record;
         }
 
@@ -5692,7 +5635,7 @@
                 return OPJ_FALSE;
         }
 
-        opj_read_bytes(p_header_data,&l_nb_stages,1);                           /* Nmco : only one tranform stage*/
+        opj_read_bytes(p_header_data,&l_nb_stages,1);                           /* Nmco : only one transform stage*/
         ++p_header_data;
 
         if (l_nb_stages > 1) {
@@ -5729,7 +5672,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_add_mct(opj_tcp_t * p_tcp, opj_image_t * p_image, OPJ_UINT32 p_index)
+static OPJ_BOOL opj_j2k_add_mct(opj_tcp_t * p_tcp, opj_image_t * p_image, OPJ_UINT32 p_index)
 {
         OPJ_UINT32 i;
         opj_simple_mcc_decorrelation_data_t * l_mcc_record;
@@ -5811,7 +5754,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_cbd( opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_cbd( opj_j2k_t *p_j2k,
                                                 struct opj_stream_private *p_stream,
                                                 struct opj_event_mgr * p_manager )
 {
@@ -5977,7 +5920,7 @@
         return l_j2k;
 }
 
-int opj_j2k_initialise_4K_poc(opj_poc_t *POC, int numres){
+static int opj_j2k_initialise_4K_poc(opj_poc_t *POC, int numres){
     POC[0].tile  = 1;
     POC[0].resno0  = 0;
     POC[0].compno0 = 0;
@@ -5995,7 +5938,7 @@
     return 2;
 }
 
-void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, opj_image_t *image, opj_event_mgr_t *p_manager)
+static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, opj_image_t *image, opj_event_mgr_t *p_manager)
 {
     /* Configure cinema parameters */
     int i;
@@ -6132,7 +6075,7 @@
 
 }
 
-OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, opj_event_mgr_t *p_manager)
+static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, opj_event_mgr_t *p_manager)
 {
     OPJ_UINT32 i;
 
@@ -6797,7 +6740,11 @@
         }
 
         /* customization of the validation */
-        opj_j2k_setup_decoding_validation(p_j2k);
+        if (! opj_j2k_setup_decoding_validation(p_j2k, p_manager)) {
+                opj_image_destroy(p_j2k->m_private_image);
+                p_j2k->m_private_image = NULL;
+                return OPJ_FALSE;
+        }
 
         /* validation of the parameters codec */
         if (! opj_j2k_exec(p_j2k, p_j2k->m_validation_list, p_stream,p_manager)) {
@@ -6807,7 +6754,11 @@
         }
 
         /* customization of the encoding */
-        opj_j2k_setup_header_reading(p_j2k);
+        if (! opj_j2k_setup_header_reading(p_j2k, p_manager)) {
+                opj_image_destroy(p_j2k->m_private_image);
+                p_j2k->m_private_image = NULL;
+                return OPJ_FALSE;
+        }
 
         /* read header */
         if (! opj_j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) {
@@ -6832,30 +6783,42 @@
         return OPJ_TRUE;
 }
 
-void opj_j2k_setup_header_reading (opj_j2k_t *p_j2k)
+static OPJ_BOOL opj_j2k_setup_header_reading (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager)
 {
         /* preconditions*/
         assert(p_j2k != 00);
+        assert(p_manager != 00);
 
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_read_header_procedure);
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_read_header_procedure, p_manager)) {
+                return OPJ_FALSE;
+        }
 
         /* DEVELOPER CORNER, add your custom procedures */
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_copy_default_tcp_and_create_tcd);
-
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_copy_default_tcp_and_create_tcd, p_manager))  {
+                return OPJ_FALSE;
+        }
+	
+        return OPJ_TRUE;
 }
 
-void opj_j2k_setup_decoding_validation (opj_j2k_t *p_j2k)
+static OPJ_BOOL opj_j2k_setup_decoding_validation (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager)
 {
         /* preconditions*/
         assert(p_j2k != 00);
+        assert(p_manager != 00);
 
-        opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_build_decoder);
-        opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_decoding_validation);
+        if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list,(opj_procedure)opj_j2k_build_decoder, p_manager)) {
+                return OPJ_FALSE;
+        }
+        if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list,(opj_procedure)opj_j2k_decoding_validation, p_manager)) {
+                return OPJ_FALSE;
+        }
+
         /* DEVELOPER CORNER, add your custom validation procedure */
-
+        return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_mct_validation (       opj_j2k_t * p_j2k,
+static OPJ_BOOL opj_j2k_mct_validation (       opj_j2k_t * p_j2k,
                                                                 opj_stream_private_t *p_stream,
                                                                 opj_event_mgr_t * p_manager )
 {
@@ -7041,7 +7004,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_build_decoder (opj_j2k_t * p_j2k,
+static OPJ_BOOL opj_j2k_build_decoder (opj_j2k_t * p_j2k,
                                                             opj_stream_private_t *p_stream,
                                                             opj_event_mgr_t * p_manager )
 {
@@ -7053,7 +7016,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_build_encoder (opj_j2k_t * p_j2k,
+static OPJ_BOOL opj_j2k_build_encoder (opj_j2k_t * p_j2k,
                                                         opj_stream_private_t *p_stream,
                                                         opj_event_mgr_t * p_manager )
 {
@@ -7065,7 +7028,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_encoding_validation (  opj_j2k_t * p_j2k,
+static OPJ_BOOL opj_j2k_encoding_validation (  opj_j2k_t * p_j2k,
                                                                             opj_stream_private_t *p_stream,
                                                                             opj_event_mgr_t * p_manager )
 {
@@ -7108,7 +7071,7 @@
         return l_is_valid;
 }
 
-OPJ_BOOL opj_j2k_decoding_validation (  opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_decoding_validation (  opj_j2k_t *p_j2k,
                                         opj_stream_private_t *p_stream,
                                         opj_event_mgr_t * p_manager
                                         )
@@ -7138,7 +7101,7 @@
         return l_is_valid;
 }
 
-OPJ_BOOL opj_j2k_read_header_procedure( opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_read_header_procedure( opj_j2k_t *p_j2k,
                                                                             opj_stream_private_t *p_stream,
                                                                             opj_event_mgr_t * p_manager)
 {
@@ -7284,6 +7247,11 @@
             opj_event_msg(p_manager, EVT_ERROR, "required QCD marker not found in main header\n");
             return OPJ_FALSE;
         }
+	
+        if (! opj_j2k_merge_ppm(&(p_j2k->m_cp), p_manager)) {
+            opj_event_msg(p_manager, EVT_ERROR, "Failed to merge PPM data\n");
+            return OPJ_FALSE;
+        }
 
         opj_event_msg(p_manager, EVT_INFO, "Main header has been correctly decoded.\n");
 
@@ -7296,7 +7264,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_exec ( opj_j2k_t * p_j2k,
+static OPJ_BOOL opj_j2k_exec ( opj_j2k_t * p_j2k,
                                         opj_procedure_list_t * p_procedure_list,
                                         opj_stream_private_t *p_stream,
                                         opj_event_mgr_t * p_manager )
@@ -7464,7 +7432,7 @@
         return OPJ_TRUE;
 }
 
-const opj_dec_memory_marker_handler_t * opj_j2k_get_marker_handler (OPJ_UINT32 p_id)
+static const opj_dec_memory_marker_handler_t * opj_j2k_get_marker_handler (OPJ_UINT32 p_id)
 {
         const opj_dec_memory_marker_handler_t *e;
         for (e = j2k_memory_marker_handler_tab; e->id != 0; ++e) {
@@ -7577,66 +7545,78 @@
         }
 }
 
-void opj_j2k_tcp_destroy (opj_tcp_t *p_tcp)
+static void opj_j2k_tcp_destroy (opj_tcp_t *p_tcp)
 {
-        if (p_tcp == 00) {
-                return;
-        }
+	if (p_tcp == 00) {
+		return;
+	}
+	
+	if (p_tcp->ppt_markers != 00) {
+		OPJ_UINT32 i;
+		for (i = 0U; i < p_tcp->ppt_markers_count; ++i) {
+			if (p_tcp->ppt_markers[i].m_data != NULL) {
+				opj_free(p_tcp->ppt_markers[i].m_data);
+			}
+		}
+		p_tcp->ppt_markers_count = 0U;
+		opj_free(p_tcp->ppt_markers);
+		p_tcp->ppt_markers = NULL;
+	}
+	
+	if (p_tcp->ppt_buffer != 00) {
+		opj_free(p_tcp->ppt_buffer);
+		p_tcp->ppt_buffer = 00;
+	}
+	
+	if (p_tcp->tccps != 00) {
+		opj_free(p_tcp->tccps);
+		p_tcp->tccps = 00;
+	}
+	
+	if (p_tcp->m_mct_coding_matrix != 00) {
+		opj_free(p_tcp->m_mct_coding_matrix);
+		p_tcp->m_mct_coding_matrix = 00;
+	}
+	
+	if (p_tcp->m_mct_decoding_matrix != 00) {
+		opj_free(p_tcp->m_mct_decoding_matrix);
+		p_tcp->m_mct_decoding_matrix = 00;
+	}
+	
+	if (p_tcp->m_mcc_records) {
+		opj_free(p_tcp->m_mcc_records);
+		p_tcp->m_mcc_records = 00;
+		p_tcp->m_nb_max_mcc_records = 0;
+		p_tcp->m_nb_mcc_records = 0;
+	}
+	
+	if (p_tcp->m_mct_records) {
+		opj_mct_data_t * l_mct_data = p_tcp->m_mct_records;
+		OPJ_UINT32 i;
+		
+		for (i=0;i<p_tcp->m_nb_mct_records;++i) {
+			if (l_mct_data->m_data) {
+				opj_free(l_mct_data->m_data);
+				l_mct_data->m_data = 00;
+			}
+			
+			++l_mct_data;
+		}
+		
+		opj_free(p_tcp->m_mct_records);
+		p_tcp->m_mct_records = 00;
+	}
 
-        if (p_tcp->ppt_buffer != 00) {
-                opj_free(p_tcp->ppt_buffer);
-                p_tcp->ppt_buffer = 00;
-        }
+	if (p_tcp->mct_norms != 00) {
+		opj_free(p_tcp->mct_norms);
+		p_tcp->mct_norms = 00;
+	}
 
-        if (p_tcp->tccps != 00) {
-                opj_free(p_tcp->tccps);
-                p_tcp->tccps = 00;
-        }
-
-        if (p_tcp->m_mct_coding_matrix != 00) {
-                opj_free(p_tcp->m_mct_coding_matrix);
-                p_tcp->m_mct_coding_matrix = 00;
-        }
-
-        if (p_tcp->m_mct_decoding_matrix != 00) {
-                opj_free(p_tcp->m_mct_decoding_matrix);
-                p_tcp->m_mct_decoding_matrix = 00;
-        }
-
-        if (p_tcp->m_mcc_records) {
-                opj_free(p_tcp->m_mcc_records);
-                p_tcp->m_mcc_records = 00;
-                p_tcp->m_nb_max_mcc_records = 0;
-                p_tcp->m_nb_mcc_records = 0;
-        }
-
-        if (p_tcp->m_mct_records) {
-                opj_mct_data_t * l_mct_data = p_tcp->m_mct_records;
-                OPJ_UINT32 i;
-
-                for (i=0;i<p_tcp->m_nb_mct_records;++i) {
-                        if (l_mct_data->m_data) {
-                                opj_free(l_mct_data->m_data);
-                                l_mct_data->m_data = 00;
-                        }
-
-                        ++l_mct_data;
-                }
-
-                opj_free(p_tcp->m_mct_records);
-                p_tcp->m_mct_records = 00;
-        }
-
-        if (p_tcp->mct_norms != 00) {
-                opj_free(p_tcp->mct_norms);
-                p_tcp->mct_norms = 00;
-        }
-
-        opj_j2k_tcp_data_destroy(p_tcp);
+	opj_j2k_tcp_data_destroy(p_tcp);
 
 }
 
-void opj_j2k_tcp_data_destroy (opj_tcp_t *p_tcp)
+static void opj_j2k_tcp_data_destroy (opj_tcp_t *p_tcp)
 {
         if (p_tcp->m_data) {
                 opj_free(p_tcp->m_data);
@@ -7645,39 +7625,148 @@
         }
 }
 
-void opj_j2k_cp_destroy (opj_cp_t *p_cp)
+static void opj_j2k_cp_destroy (opj_cp_t *p_cp)
 {
-        OPJ_UINT32 l_nb_tiles;
-        opj_tcp_t * l_current_tile = 00;
-        OPJ_UINT32 i;
+	OPJ_UINT32 l_nb_tiles;
+	opj_tcp_t * l_current_tile = 00;
 
-        if (p_cp == 00)
-        {
-                return;
-        }
-        if (p_cp->tcps != 00)
-        {
-                l_current_tile = p_cp->tcps;
-                l_nb_tiles = p_cp->th * p_cp->tw;
+	if (p_cp == 00)
+	{
+		return;
+	}
+	if (p_cp->tcps != 00)
+	{
+		OPJ_UINT32 i;
+		l_current_tile = p_cp->tcps;
+		l_nb_tiles = p_cp->th * p_cp->tw;
+		
+		for (i = 0U; i < l_nb_tiles; ++i)
+		{
+			opj_j2k_tcp_destroy(l_current_tile);
+			++l_current_tile;
+		}
+		opj_free(p_cp->tcps);
+		p_cp->tcps = 00;
+	}
+	if (p_cp->ppm_markers != 00) {
+		OPJ_UINT32 i;
+		for (i = 0U; i < p_cp->ppm_markers_count; ++i) {
+			if (p_cp->ppm_markers[i].m_data != NULL) {
+				opj_free(p_cp->ppm_markers[i].m_data);
+			}
+		}
+		p_cp->ppm_markers_count = 0U;
+		opj_free(p_cp->ppm_markers);
+		p_cp->ppm_markers = NULL;
+	}
+	opj_free(p_cp->ppm_buffer);
+	p_cp->ppm_buffer = 00;
+	p_cp->ppm_data = NULL; /* ppm_data belongs to the allocated buffer pointed by ppm_buffer */
+	opj_free(p_cp->comment);
+	p_cp->comment = 00;
+	if (! p_cp->m_is_decoder)
+	{
+		opj_free(p_cp->m_specific_param.m_enc.m_matrice);
+		p_cp->m_specific_param.m_enc.m_matrice = 00;
+	}
+}
 
-                for (i = 0; i < l_nb_tiles; ++i)
-                {
-                        opj_j2k_tcp_destroy(l_current_tile);
-                        ++l_current_tile;
-                }
-                opj_free(p_cp->tcps);
-                p_cp->tcps = 00;
-        }
-        opj_free(p_cp->ppm_buffer);
-        p_cp->ppm_buffer = 00;
-        p_cp->ppm_data = NULL; /* ppm_data belongs to the allocated buffer pointed by ppm_buffer */
-        opj_free(p_cp->comment);
-        p_cp->comment = 00;
-        if (! p_cp->m_is_decoder)
-        {
-                opj_free(p_cp->m_specific_param.m_enc.m_matrice);
-                p_cp->m_specific_param.m_enc.m_matrice = 00;
-        }
+static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t *p_stream, OPJ_UINT32 tile_no, OPJ_BOOL* p_correction_needed, opj_event_mgr_t * p_manager )
+{
+	OPJ_BYTE   l_header_data[10];
+	OPJ_OFF_T  l_stream_pos_backup;
+	OPJ_UINT32 l_current_marker;
+	OPJ_UINT32 l_marker_size;
+	OPJ_UINT32 l_tile_no, l_tot_len, l_current_part, l_num_parts;
+	
+	/* initialize to no correction needed */
+	*p_correction_needed = OPJ_FALSE;
+	
+	l_stream_pos_backup = opj_stream_tell(p_stream);
+	if (l_stream_pos_backup == -1) {
+		/* let's do nothing */
+		return OPJ_TRUE;
+	}
+	
+	for (;;) {
+		/* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */
+		if (opj_stream_read_data(p_stream,l_header_data, 2, p_manager) != 2) {
+			/* assume all is OK */
+			if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) {
+				return OPJ_FALSE;
+			}
+			return OPJ_TRUE;
+		}
+		
+		/* Read 2 bytes from buffer as the new marker ID */
+		opj_read_bytes(l_header_data, &l_current_marker, 2);
+		
+		if (l_current_marker != J2K_MS_SOT) {
+			/* assume all is OK */
+			if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) {
+				return OPJ_FALSE;
+			}
+			return OPJ_TRUE;
+		}
+		
+		/* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */
+		if (opj_stream_read_data(p_stream, l_header_data, 2, p_manager) != 2) {
+			opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n");
+			return OPJ_FALSE;
+		}
+		
+		/* Read 2 bytes from the buffer as the marker size */
+		opj_read_bytes(l_header_data, &l_marker_size, 2);
+		
+		/* Check marker size for SOT Marker */
+		if (l_marker_size != 10) {
+			opj_event_msg(p_manager, EVT_ERROR, "Inconsistent marker size\n");
+			return OPJ_FALSE;
+		}
+		l_marker_size -= 2;
+		
+		if (opj_stream_read_data(p_stream, l_header_data, l_marker_size, p_manager) != l_marker_size) {
+			opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n");
+			return OPJ_FALSE;
+		}
+		
+		if (! opj_j2k_get_sot_values(l_header_data, l_marker_size, &l_tile_no, &l_tot_len, &l_current_part, &l_num_parts, p_manager)) {
+			return OPJ_FALSE;
+		}
+		
+		if (l_tile_no == tile_no) {
+			/* we found what we were looking for */
+			break;
+		}
+		
+		if ((l_tot_len == 0U) || (l_tot_len < 14U)) {
+			/* last SOT until EOC or invalid Psot value */
+			/* assume all is OK */
+			if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) {
+				return OPJ_FALSE;
+			}
+			return OPJ_TRUE;
+		}
+		l_tot_len -= 12U;
+		/* look for next SOT marker */
+		if (opj_stream_skip(p_stream, (OPJ_OFF_T)(l_tot_len), p_manager) != (OPJ_OFF_T)(l_tot_len)) {
+			/* assume all is OK */
+			if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) {
+				return OPJ_FALSE;
+			}
+			return OPJ_TRUE;
+		}
+	}
+	
+	/* check for correction */
+	if (l_current_part == l_num_parts) {
+		*p_correction_needed = OPJ_TRUE;
+	}
+	
+	if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) {
+		return OPJ_FALSE;
+	}
+	return OPJ_TRUE;
 }
 
 OPJ_BOOL opj_j2k_read_tile_header(      opj_j2k_t * p_j2k,
@@ -7694,7 +7783,6 @@
         OPJ_UINT32 l_marker_size;
         const opj_dec_memory_marker_handler_t * l_marker_handler = 00;
         opj_tcp_t * l_tcp = NULL;
-        OPJ_UINT32 l_nb_tiles;
 
         /* preconditions */
         assert(p_stream != 00);
@@ -7844,7 +7932,30 @@
                         if (! opj_j2k_read_sod(p_j2k, p_stream, p_manager)) {
                                 return OPJ_FALSE;
                         }
+                        if (p_j2k->m_specific_param.m_decoder.m_can_decode && !p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked) {
+                                /* Issue 254 */
+                                OPJ_BOOL l_correction_needed;
+													
+                                p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1;
+                                if(!opj_j2k_need_nb_tile_parts_correction(p_stream, p_j2k->m_current_tile_number, &l_correction_needed, p_manager)) {
+                                        opj_event_msg(p_manager, EVT_ERROR, "opj_j2k_apply_nb_tile_parts_correction error\n");
+                                        return OPJ_FALSE;
+                                }
+                                if (l_correction_needed) {
+                                        OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th;
+                                        OPJ_UINT32 l_tile_no;
 
+                                        p_j2k->m_specific_param.m_decoder.m_can_decode = 0;
+                                        p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction = 1;
+                                        /* correct tiles */
+                                        for (l_tile_no = 0U; l_tile_no < l_nb_tiles; ++l_tile_no) {
+                                                if (p_j2k->m_cp.tcps[l_tile_no].m_nb_tile_parts != 0U) {
+                                                        p_j2k->m_cp.tcps[l_tile_no].m_nb_tile_parts+=1;
+                                                }
+                                        }
+                                        opj_event_msg(p_manager, EVT_WARNING, "Non conformant codestream TPsot==TNsot.\n");
+                                }
+                        }
                         if (! p_j2k->m_specific_param.m_decoder.m_can_decode){
                                 /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */
                                 if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) {
@@ -7883,8 +7994,8 @@
 
         /* FIXME DOC ???*/
         if ( ! p_j2k->m_specific_param.m_decoder.m_can_decode) {
+                OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
                 l_tcp = p_j2k->m_cp.tcps + p_j2k->m_current_tile_number;
-                l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
 
                 while( (p_j2k->m_current_tile_number < l_nb_tiles) && (l_tcp->m_data == 00) ) {
                         ++p_j2k->m_current_tile_number;
@@ -7897,8 +8008,12 @@
                 }
         }
 
+        if (! opj_j2k_merge_ppt(p_j2k->m_cp.tcps + p_j2k->m_current_tile_number, p_manager)) {
+                opj_event_msg(p_manager, EVT_ERROR, "Failed to merge PPT data\n");
+                return OPJ_FALSE;
+        }
         /*FIXME ???*/
-        if (! opj_tcd_init_decode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number)) {
+        if (! opj_tcd_init_decode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number, p_manager)) {
                 opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n");
                 return OPJ_FALSE;
         }
@@ -7951,7 +8066,7 @@
                                                                 l_tcp->m_data,
                                                                 l_tcp->m_data_size,
                                                                 p_tile_index,
-                                                                p_j2k->cstr_index) ) {
+                                                                p_j2k->cstr_index, p_manager) ) {
                 opj_j2k_tcp_destroy(l_tcp);
                 p_j2k->m_specific_param.m_decoder.m_state |= 0x8000;/*FIXME J2K_DEC_STATE_ERR;*/
                 opj_event_msg(p_manager, EVT_ERROR, "Failed to decode.\n");
@@ -8003,16 +8118,16 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data, opj_image_t* p_output_image)
+static OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data, opj_image_t* p_output_image)
 {
         OPJ_UINT32 i,j,k = 0;
         OPJ_UINT32 l_width_src,l_height_src;
         OPJ_UINT32 l_width_dest,l_height_dest;
         OPJ_INT32 l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src;
-        OPJ_INT32 l_start_offset_src, l_line_offset_src, l_end_offset_src ;
+        OPJ_SIZE_T l_start_offset_src, l_line_offset_src, l_end_offset_src ;
         OPJ_UINT32 l_start_x_dest , l_start_y_dest;
         OPJ_UINT32 l_x0_dest, l_y0_dest, l_x1_dest, l_y1_dest;
-        OPJ_INT32 l_start_offset_dest, l_line_offset_dest;
+        OPJ_SIZE_T l_start_offset_dest, l_line_offset_dest;
 
         opj_image_comp_t * l_img_comp_src = 00;
         opj_image_comp_t * l_img_comp_dest = 00;
@@ -8038,8 +8153,8 @@
                     const OPJ_UINT32 MAX_SIZE = UINT32_MAX / sizeof(OPJ_INT32);
                     if (height == 0 || width > MAX_SIZE / height) {
                         return OPJ_FALSE;
-                    } 
-                    l_img_comp_dest->data = (OPJ_INT32*) opj_calloc(width * height, sizeof(OPJ_INT32));
+                    }
+                    l_img_comp_dest->data = (OPJ_INT32*)opj_calloc(width * height, sizeof(OPJ_INT32));
                     if (!l_img_comp_dest->data) {
                         return OPJ_FALSE;
                     }
@@ -8073,9 +8188,9 @@
                 l_height_src = (OPJ_UINT32)(l_res->y1 - l_res->y0);
 
                 /* Border of the current output component*/
-                l_x0_dest = (OPJ_UINT32)opj_int_ceildivpow2((OPJ_INT32)l_img_comp_dest->x0, (OPJ_INT32)l_img_comp_dest->factor);
-                l_y0_dest = (OPJ_UINT32)opj_int_ceildivpow2((OPJ_INT32)l_img_comp_dest->y0, (OPJ_INT32)l_img_comp_dest->factor);
-                l_x1_dest = l_x0_dest + l_img_comp_dest->w;
+                l_x0_dest = opj_uint_ceildivpow2(l_img_comp_dest->x0, l_img_comp_dest->factor);
+                l_y0_dest = opj_uint_ceildivpow2(l_img_comp_dest->y0, l_img_comp_dest->factor);
+                l_x1_dest = l_x0_dest + l_img_comp_dest->w; /* can't overflow given that image->x1 is uint32 */
                 l_y1_dest = l_y0_dest + l_img_comp_dest->h;
 
                 /*if (i == 0) {
@@ -8106,7 +8221,7 @@
                         }
                 }
                 else {
-                        l_start_x_dest = 0 ;
+                        l_start_x_dest = 0U;
                         l_offset_x0_src = (OPJ_INT32)l_x0_dest - l_res->x0;
 
                         if ( l_x1_dest >= (OPJ_UINT32)l_res->x1 ) {
@@ -8133,7 +8248,7 @@
                         }
                 }
                 else {
-                        l_start_y_dest = 0 ;
+                        l_start_y_dest = 0U;
                         l_offset_y0_src = (OPJ_INT32)l_y0_dest - l_res->y0;
 
                         if ( l_y1_dest >= (OPJ_UINT32)l_res->y1 ) {
@@ -8156,13 +8271,13 @@
                 /*-----*/
 
                 /* Compute the input buffer offset */
-                l_start_offset_src = l_offset_x0_src + l_offset_y0_src * (OPJ_INT32)l_width_src;
-                l_line_offset_src = l_offset_x1_src + l_offset_x0_src;
-                l_end_offset_src = l_offset_y1_src * (OPJ_INT32)l_width_src - l_offset_x0_src;
+                l_start_offset_src = (OPJ_SIZE_T)l_offset_x0_src + (OPJ_SIZE_T)l_offset_y0_src * (OPJ_SIZE_T)l_width_src;
+                l_line_offset_src  = (OPJ_SIZE_T)l_offset_x1_src + (OPJ_SIZE_T)l_offset_x0_src;
+                l_end_offset_src   = (OPJ_SIZE_T)l_offset_y1_src * (OPJ_SIZE_T)l_width_src - (OPJ_SIZE_T)l_offset_x0_src;
 
                 /* Compute the output buffer offset */
-                l_start_offset_dest = (OPJ_INT32)(l_start_x_dest + l_start_y_dest * l_img_comp_dest->w);
-                l_line_offset_dest = (OPJ_INT32)(l_img_comp_dest->w - l_width_dest);
+                l_start_offset_dest = (OPJ_SIZE_T)l_start_x_dest + (OPJ_SIZE_T)l_start_y_dest * (OPJ_SIZE_T)l_img_comp_dest->w;
+                l_line_offset_dest  = (OPJ_SIZE_T)l_img_comp_dest->w - (OPJ_SIZE_T)l_width_dest;
 
                 /* Move the output buffer to the first place where we will write*/
                 l_dest_ptr = l_img_comp_dest->data + l_start_offset_dest;
@@ -8436,6 +8551,10 @@
         l_j2k->m_is_decoder = 1;
         l_j2k->m_cp.m_is_decoder = 1;
 
+#ifdef OPJ_DISABLE_TPSOT_FIX
+        l_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1;
+#endif
+
         l_j2k->m_specific_param.m_decoder.m_default_tcp = (opj_tcp_t*) opj_calloc(1,sizeof(opj_tcp_t));
         if (!l_j2k->m_specific_param.m_decoder.m_default_tcp) {
                 opj_j2k_destroy(l_j2k);
@@ -8478,7 +8597,7 @@
         return l_j2k;
 }
 
-opj_codestream_index_t* opj_j2k_create_cstr_index(void)
+static opj_codestream_index_t* opj_j2k_create_cstr_index(void)
 {
         opj_codestream_index_t* cstr_index = (opj_codestream_index_t*)
                         opj_calloc(1,sizeof(opj_codestream_index_t));
@@ -8489,15 +8608,17 @@
         cstr_index->marknum = 0;
         cstr_index->marker = (opj_marker_info_t*)
                         opj_calloc(cstr_index->maxmarknum, sizeof(opj_marker_info_t));
-        if (!cstr_index-> marker)
+        if (!cstr_index-> marker) {
+                opj_free(cstr_index);
                 return NULL;
+        }
 
         cstr_index->tile_index = NULL;
 
         return cstr_index;
 }
 
-OPJ_UINT32 opj_j2k_get_SPCod_SPCoc_size (       opj_j2k_t *p_j2k,
+static OPJ_UINT32 opj_j2k_get_SPCod_SPCoc_size (       opj_j2k_t *p_j2k,
                                                                                 OPJ_UINT32 p_tile_no,
                                                                                 OPJ_UINT32 p_comp_no )
 {
@@ -8524,7 +8645,7 @@
         }
 }
 
-OPJ_BOOL opj_j2k_write_SPCod_SPCoc(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_SPCod_SPCoc(     opj_j2k_t *p_j2k,
                                                                     OPJ_UINT32 p_tile_no,
                                                                     OPJ_UINT32 p_comp_no,
                                                                     OPJ_BYTE * p_data,
@@ -8590,7 +8711,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_read_SPCod_SPCoc(  opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_read_SPCod_SPCoc(  opj_j2k_t *p_j2k,
                                                                 OPJ_UINT32 compno,
                                                                 OPJ_BYTE * p_header_data,
                                                                 OPJ_UINT32 * p_header_size,
@@ -8713,7 +8834,7 @@
         return OPJ_TRUE;
 }
 
-void opj_j2k_copy_tile_component_parameters( opj_j2k_t *p_j2k )
+static void opj_j2k_copy_tile_component_parameters( opj_j2k_t *p_j2k )
 {
         /* loop */
         OPJ_UINT32 i;
@@ -8746,7 +8867,7 @@
         }
 }
 
-OPJ_UINT32 opj_j2k_get_SQcd_SQcc_size ( opj_j2k_t *p_j2k,
+static OPJ_UINT32 opj_j2k_get_SQcd_SQcc_size ( opj_j2k_t *p_j2k,
                                                                         OPJ_UINT32 p_tile_no,
                                                                         OPJ_UINT32 p_comp_no )
 {
@@ -8777,7 +8898,7 @@
         }
 }
 
-OPJ_BOOL opj_j2k_write_SQcd_SQcc(       opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_SQcd_SQcc(       opj_j2k_t *p_j2k,
                                                                 OPJ_UINT32 p_tile_no,
                                                                 OPJ_UINT32 p_comp_no,
                                                                 OPJ_BYTE * p_data,
@@ -8850,7 +8971,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k,
                                                             OPJ_UINT32 p_comp_no,
                                                             OPJ_BYTE* p_header_data,
                                                             OPJ_UINT32 * p_header_size,
@@ -8967,7 +9088,7 @@
         return OPJ_TRUE;
 }
 
-void opj_j2k_copy_tile_quantization_parameters( opj_j2k_t *p_j2k )
+static void opj_j2k_copy_tile_quantization_parameters( opj_j2k_t *p_j2k )
 {
         OPJ_UINT32 i;
         opj_cp_t *l_cp = NULL;
@@ -9094,7 +9215,7 @@
 
 }
 
-void opj_j2k_dump_MH_index(opj_j2k_t* p_j2k, FILE* out_stream)
+static void opj_j2k_dump_MH_index(opj_j2k_t* p_j2k, FILE* out_stream)
 {
         opj_codestream_index_t* cstr_index = p_j2k->cstr_index;
         OPJ_UINT32 it_marker, it_tile, it_tile_part;
@@ -9163,7 +9284,7 @@
 }
 
 
-void opj_j2k_dump_MH_info(opj_j2k_t* p_j2k, FILE* out_stream)
+static void opj_j2k_dump_MH_info(opj_j2k_t* p_j2k, FILE* out_stream)
 {
 
         fprintf(out_stream, "Codestream info from main header: {\n");
@@ -9403,7 +9524,7 @@
         return l_cstr_index;
 }
 
-OPJ_BOOL opj_j2k_allocate_tile_element_cstr_index(opj_j2k_t *p_j2k)
+static OPJ_BOOL opj_j2k_allocate_tile_element_cstr_index(opj_j2k_t *p_j2k)
 {
         OPJ_UINT32 it_tile=0;
 
@@ -9424,7 +9545,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_decode_tiles ( opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_decode_tiles ( opj_j2k_t *p_j2k,
                                                             opj_stream_private_t *p_stream,
                                                             opj_event_mgr_t * p_manager)
 {
@@ -9443,7 +9564,7 @@
         }
         l_max_data_size = 1000;
 
-        while (OPJ_TRUE) {
+		for (;;) {
                 if (! opj_j2k_read_tile_header( p_j2k,
                                         &l_current_tile_no,
                                         &l_data_size,
@@ -9500,14 +9621,18 @@
 /**
  * Sets up the procedures to do on decoding data. Developpers wanting to extend the library can add their own reading procedures.
  */
-static void opj_j2k_setup_decoding (opj_j2k_t *p_j2k)
+static OPJ_BOOL opj_j2k_setup_decoding (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager)
 {
         /* preconditions*/
         assert(p_j2k != 00);
+        assert(p_manager != 00);
 
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_decode_tiles);
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_decode_tiles, p_manager)) {
+                return OPJ_FALSE;
+        }
         /* DEVELOPER CORNER, add your custom procedures */
 
+        return OPJ_TRUE;
 }
 
 /*
@@ -9550,14 +9675,14 @@
                                  *  so move to the last SOT read */
                                 if ( !(opj_stream_read_seek(p_stream, p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos+2, p_manager)) ){
                                         opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n");
-                        opj_free(l_current_data);
+                                        opj_free(l_current_data);
                                         return OPJ_FALSE;
                                 }
                         }
                         else{
                                 if ( !(opj_stream_read_seek(p_stream, p_j2k->cstr_index->tile_index[l_tile_no_to_dec].tp_index[0].start_pos+2, p_manager)) ) {
                                         opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n");
-                        opj_free(l_current_data);
+                                        opj_free(l_current_data);
                                         return OPJ_FALSE;
                                 }
                         }
@@ -9566,7 +9691,7 @@
                                 p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT;
                 }
 
-        while (OPJ_TRUE) {
+		for (;;) {
                 if (! opj_j2k_read_tile_header( p_j2k,
                                         &l_current_tile_no,
                                         &l_data_size,
@@ -9615,6 +9740,7 @@
                         /* move into the codestream to the the first SOT (FIXME or not move?)*/
                         if (!(opj_stream_read_seek(p_stream, p_j2k->cstr_index->main_head_end + 2, p_manager) ) ) {
                                 opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n");
+                                opj_free(l_current_data);
                                 return OPJ_FALSE;
                         }
                         break;
@@ -9633,14 +9759,18 @@
 /**
  * Sets up the procedures to do on decoding one tile. Developpers wanting to extend the library can add their own reading procedures.
  */
-static void opj_j2k_setup_decoding_tile (opj_j2k_t *p_j2k)
+static OPJ_BOOL opj_j2k_setup_decoding_tile (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager)
 {
         /* preconditions*/
         assert(p_j2k != 00);
+        assert(p_manager != 00);
 
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_decode_one_tile);
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_decode_one_tile, p_manager)) {
+                return OPJ_FALSE;
+        }
         /* DEVELOPER CORNER, add your custom procedures */
 
+        return OPJ_TRUE;
 }
 
 OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k,
@@ -9652,7 +9782,7 @@
 
         if (!p_image)
                 return OPJ_FALSE;
-
+	
         p_j2k->m_output_image = opj_image_create0();
         if (! (p_j2k->m_output_image)) {
                 return OPJ_FALSE;
@@ -9660,7 +9790,7 @@
         opj_copy_image_header(p_image, p_j2k->m_output_image);
 
         /* customization of the decoding */
-        opj_j2k_setup_decoding(p_j2k);
+        opj_j2k_setup_decoding(p_j2k, p_manager);
 
         /* Decode the codestream */
         if (! opj_j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) {
@@ -9756,7 +9886,7 @@
         p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = (OPJ_INT32)tile_index;
 
         /* customization of the decoding */
-        opj_j2k_setup_decoding_tile(p_j2k);
+        opj_j2k_setup_decoding_tile(p_j2k, p_manager);
 
         /* Decode the codestream */
         if (! opj_j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) {
@@ -9851,7 +9981,6 @@
 												                }
 												                return OPJ_FALSE;
 												        }
-												        opj_alloc_tile_component_data(l_tilec);
                         }
                 }
                 l_current_tile_size = opj_tcd_get_encoded_tile_size(p_j2k->m_tcd);
@@ -9877,11 +10006,15 @@
                         /* now copy this data into the tile component */
                         if (! opj_tcd_copy_tile_data(p_j2k->m_tcd,l_current_data,l_current_tile_size)) {
 																opj_event_msg(p_manager, EVT_ERROR, "Size mismatch between tile data and sent data." );
+																opj_free(l_current_data);
 																return OPJ_FALSE;
                         }
                 }
 
                 if (! opj_j2k_post_write_tile (p_j2k,p_stream,p_manager)) {
+                        if (l_current_data) {
+                                opj_free(l_current_data);
+                        }
                         return OPJ_FALSE;
                 }
         }
@@ -9897,7 +10030,9 @@
                                                         opj_event_mgr_t * p_manager)
 {
         /* customization of the encoding */
-        opj_j2k_setup_end_compress(p_j2k);
+        if (! opj_j2k_setup_end_compress(p_j2k, p_manager)) {
+                return OPJ_FALSE;
+        }
 
         if (! opj_j2k_exec (p_j2k, p_j2k->m_procedure_list, p_stream, p_manager))
         {
@@ -9937,7 +10072,9 @@
         }
 
         /* customization of the validation */
-        opj_j2k_setup_encoding_validation (p_j2k);
+        if (! opj_j2k_setup_encoding_validation (p_j2k, p_manager)) {
+                return OPJ_FALSE;
+        }
 
         /* validation of the parameters codec */
         if (! opj_j2k_exec(p_j2k,p_j2k->m_validation_list,p_stream,p_manager)) {
@@ -9945,7 +10082,9 @@
         }
 
         /* customization of the encoding */
-        opj_j2k_setup_header_writing(p_j2k);
+        if (! opj_j2k_setup_header_writing(p_j2k, p_manager)) {
+                return OPJ_FALSE;
+        }
 
         /* write header */
         if (! opj_j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) {
@@ -9955,7 +10094,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_pre_write_tile (       opj_j2k_t * p_j2k,
+static OPJ_BOOL opj_j2k_pre_write_tile (       opj_j2k_t * p_j2k,
                                                                 OPJ_UINT32 p_tile_index,
                                                                 opj_stream_private_t *p_stream,
                                                                 opj_event_mgr_t * p_manager )
@@ -9973,14 +10112,14 @@
         p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = 0;
 
         /* initialisation before tile encoding  */
-        if (! opj_tcd_init_encode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number)) {
+        if (! opj_tcd_init_encode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number, p_manager)) {
                 return OPJ_FALSE;
         }
 
         return OPJ_TRUE;
 }
 
-void opj_get_tile_dimensions(opj_image_t * l_image,
+static void opj_get_tile_dimensions(opj_image_t * l_image,
                              opj_tcd_tilecomp_t * l_tilec,
                              opj_image_comp_t * l_img_comp,
                              OPJ_UINT32* l_size_comp,
@@ -10011,7 +10150,7 @@
 	*l_tile_offset = ((OPJ_UINT32)l_tilec->x0 - *l_offset_x) + ((OPJ_UINT32)l_tilec->y0 - *l_offset_y) * *l_image_width;
 }
 
-void opj_j2k_get_tile_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data)
+static void opj_j2k_get_tile_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data)
 {
         OPJ_UINT32 i,j,k = 0;
 
@@ -10104,7 +10243,7 @@
         }
 }
 
-OPJ_BOOL opj_j2k_post_write_tile (      opj_j2k_t * p_j2k,
+static OPJ_BOOL opj_j2k_post_write_tile (      opj_j2k_t * p_j2k,
                                                                 opj_stream_private_t *p_stream,
                                                                 opj_event_mgr_t * p_manager )
 {
@@ -10146,79 +10285,133 @@
         return OPJ_TRUE;
 }
 
-void opj_j2k_setup_end_compress (opj_j2k_t *p_j2k)
+static OPJ_BOOL opj_j2k_setup_end_compress (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager)
 {
         /* preconditions */
         assert(p_j2k != 00);
+        assert(p_manager != 00);
 
         /* DEVELOPER CORNER, insert your custom procedures */
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_eoc );
-
-        if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz)) {
-                opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_updated_tlm);
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_eoc, p_manager)) {
+                return OPJ_FALSE;
         }
 
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_epc );
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_end_encoding );
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_destroy_header_memory);
-}
-
-void opj_j2k_setup_encoding_validation (opj_j2k_t *p_j2k)
-{
-        /* preconditions */
-        assert(p_j2k != 00);
-
-        opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_build_encoder);
-        opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_encoding_validation);
-
-        /* DEVELOPER CORNER, add your custom validation procedure */
-        opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_mct_validation);
-}
-
-void opj_j2k_setup_header_writing (opj_j2k_t *p_j2k)
-{
-        /* preconditions */
-        assert(p_j2k != 00);
-
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_init_info );
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_soc );
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_siz );
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_cod );
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_qcd );
-
         if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz)) {
-                /* No need for COC or QCC, QCD and COD are used
-                opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_all_coc );
-                opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_all_qcc );
-                */
-                opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_tlm );
-
-                if (p_j2k->m_cp.rsiz == OPJ_PROFILE_CINEMA_4K) {
-                        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_poc );
+                if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_updated_tlm, p_manager)) {
+                        return OPJ_FALSE;
                 }
         }
 
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_regions);
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_epc, p_manager)) {
+                return OPJ_FALSE;
+        }
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_end_encoding, p_manager)) {
+                return OPJ_FALSE;
+        }
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_destroy_header_memory, p_manager)) {
+                return OPJ_FALSE;
+        }
+        return OPJ_TRUE;
+}
+
+static OPJ_BOOL opj_j2k_setup_encoding_validation (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager)
+{
+        /* preconditions */
+        assert(p_j2k != 00);
+        assert(p_manager != 00);
+
+        if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_build_encoder, p_manager)) {
+                return OPJ_FALSE;
+        }
+        if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_encoding_validation, p_manager)) {
+                return OPJ_FALSE;
+				}
+
+        /* DEVELOPER CORNER, add your custom validation procedure */
+        if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_mct_validation, p_manager)) {
+                return OPJ_FALSE;
+        }
+	
+        return OPJ_TRUE;
+}
+
+static OPJ_BOOL opj_j2k_setup_header_writing (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager)
+{
+        /* preconditions */
+        assert(p_j2k != 00);
+        assert(p_manager != 00);
+
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_init_info, p_manager)) {
+                return OPJ_FALSE;
+        }
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_soc, p_manager)) {
+                return OPJ_FALSE;
+        }
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_siz, p_manager)) {
+                return OPJ_FALSE;
+        }
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_cod, p_manager)) {
+                return OPJ_FALSE;
+        }
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_qcd, p_manager)) {
+                return OPJ_FALSE;
+        }
+
+        if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz)) {
+                /* No need for COC or QCC, QCD and COD are used
+                if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_all_coc, p_manager)) {
+                        return OPJ_FALSE;
+                }
+                if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_all_qcc, p_manager)) {
+                        return OPJ_FALSE;
+                }
+                */
+                if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_tlm, p_manager)) {
+                        return OPJ_FALSE;
+                }
+
+                if (p_j2k->m_cp.rsiz == OPJ_PROFILE_CINEMA_4K) {
+                        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_poc, p_manager)) {
+                                return OPJ_FALSE;
+                        }
+                }
+        }
+
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_regions, p_manager)) {
+                return OPJ_FALSE;
+        }
 
         if (p_j2k->m_cp.comment != 00)  {
-                opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_com);
+                if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_com, p_manager)) {
+                        return OPJ_FALSE;
+                }
         }
 
         /* DEVELOPER CORNER, insert your custom procedures */
         if (p_j2k->m_cp.rsiz & OPJ_EXTENSION_MCT) {
-                opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_mct_data_group );
+                if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_mct_data_group, p_manager)) {
+                        return OPJ_FALSE;
+                }
         }
         /* End of Developer Corner */
 
         if (p_j2k->cstr_index) {
-                opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_get_end_header );
+                if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_get_end_header, p_manager)) {
+                        return OPJ_FALSE;
+                }
         }
 
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_create_tcd);
-        opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_update_rates);
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_create_tcd, p_manager)) {
+                return OPJ_FALSE;
+        }
+        if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_update_rates, p_manager)) {
+                return OPJ_FALSE;
+        }
+
+        return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_first_tile_part (opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_first_tile_part (opj_j2k_t *p_j2k,
                                                                         OPJ_BYTE * p_data,
                                                                         OPJ_UINT32 * p_data_written,
                                                                         OPJ_UINT32 p_total_data_size,
@@ -10298,7 +10491,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_all_tile_parts(  opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_all_tile_parts(  opj_j2k_t *p_j2k,
                                                                         OPJ_BYTE * p_data,
                                                                         OPJ_UINT32 * p_data_written,
                                                                         OPJ_UINT32 p_total_data_size,
@@ -10409,7 +10602,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_write_updated_tlm( opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_write_updated_tlm( opj_j2k_t *p_j2k,
                                                                     struct opj_stream_private *p_stream,
                                                                     struct opj_event_mgr * p_manager )
 {
@@ -10440,7 +10633,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_end_encoding(  opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_end_encoding(  opj_j2k_t *p_j2k,
                                                         struct opj_stream_private *p_stream,
                                                         struct opj_event_mgr * p_manager )
 {
@@ -10491,7 +10684,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_j2k_init_info(     opj_j2k_t *p_j2k,
+static OPJ_BOOL opj_j2k_init_info(     opj_j2k_t *p_j2k,
                                                 struct opj_stream_private *p_stream,
                                                 struct opj_event_mgr * p_manager )
 {
diff --git a/third_party/libopenjpeg20/j2k.h b/third_party/libopenjpeg20/j2k.h
index 10e22aa..358e073 100644
--- a/third_party/libopenjpeg20/j2k.h
+++ b/third_party/libopenjpeg20/j2k.h
@@ -232,6 +232,12 @@
 }
 opj_simple_mcc_decorrelation_data_t;
 
+typedef struct opj_ppx_struct
+{
+	OPJ_BYTE*   m_data; /* m_data == NULL => Zppx not read yet */
+	OPJ_UINT32	m_data_size;
+} opj_ppx;
+
 /**
 Tile coding parameters :
 this structure is used to store coding/decoding parameters common to all
@@ -254,7 +260,13 @@
 	OPJ_UINT32 numpocs;
 	/** progression order changes */
 	opj_poc_t pocs[32];
-	/** packet header store there for futur use in t2_decode_packet */
+	
+	/** number of ppt markers (reserved size) */
+	OPJ_UINT32 ppt_markers_count;
+	/** ppt markers data (table indexed by Zppt) */
+	opj_ppx* ppt_markers;
+	
+	/** packet header store there for future use in t2_decode_packet */
 	OPJ_BYTE *ppt_data;
 	/** used to keep a track of the allocated memory */
 	OPJ_BYTE *ppt_buffer;
@@ -359,7 +371,12 @@
 	/** number of tiles in heigth */
 	OPJ_UINT32 th;
 
-	/** packet header store there for futur use in t2_decode_packet */
+	/** number of ppm markers (reserved size) */
+	OPJ_UINT32 ppm_markers_count;
+	/** ppm markers data (table indexed by Zppm) */
+	opj_ppx* ppm_markers;
+	
+	/** packet header store there for future use in t2_decode_packet */
 	OPJ_BYTE *ppm_data;
 	/** size of the ppm_data*/
 	OPJ_UINT32 ppm_len;
@@ -483,6 +500,9 @@
 	OPJ_UINT32 m_can_decode			: 1;
 	OPJ_UINT32 m_discard_tiles		: 1;
 	OPJ_UINT32 m_skip_data			: 1;
+	/** TNsot correction : see issue 254 **/
+	OPJ_UINT32 m_nb_tile_parts_correction_checked : 1;
+	OPJ_UINT32 m_nb_tile_parts_correction : 1;
 
 } opj_j2k_dec_t;
 
@@ -569,7 +589,6 @@
 
 	/** the current tile coder/decoder **/
 	struct opj_tcd *	m_tcd;
-
 }
 opj_j2k_t;
 
diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c
index aafbe19..47f83a1 100644
--- a/third_party/libopenjpeg20/jp2.c
+++ b/third_party/libopenjpeg20/jp2.c
@@ -106,7 +106,7 @@
 									OPJ_UINT32 p_cdef_header_size,
 									opj_event_mgr_t * p_manager );
 
-static void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color);
+static void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color, opj_event_mgr_t *);
 
 /**
  * Writes the Channel Definition box.
@@ -158,7 +158,7 @@
 									OPJ_UINT32 p_header_size,
 									opj_event_mgr_t * p_manager );
 
-OPJ_BOOL opj_jp2_skip_jp2c(	opj_jp2_t *jp2,
+static OPJ_BOOL opj_jp2_skip_jp2c(	opj_jp2_t *jp2,
 						    opj_stream_private_t *cio,
 						    opj_event_mgr_t * p_manager );
 
@@ -170,7 +170,7 @@
  * @param	p_header_size	the size of the data contained in the file header box.
  * @param	p_manager		the user event manager.
  *
- * @return true if the JP2 Header box was successfully reconized.
+ * @return true if the JP2 Header box was successfully recognized.
 */
 static OPJ_BOOL opj_jp2_read_jp2h(  opj_jp2_t *jp2,
                                     OPJ_BYTE *p_header_data,
@@ -178,6 +178,19 @@
                                     opj_event_mgr_t * p_manager );
 
 /**
+ * Writes the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box).
+ *
+ * @param  jp2      the jpeg2000 file codec.
+ * @param  stream      the stream to write data to.
+ * @param  p_manager  user event manager.
+ *
+ * @return true if writing was successful.
+ */
+static OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2,
+														opj_stream_private_t *stream,
+														opj_event_mgr_t * p_manager );
+
+/**
  * Writes the Jpeg2000 codestream Header box - JP2C Header box. This function must be called AFTER the coding has been done.
  *
  * @param	cio			the stream to write data to.
@@ -313,13 +326,13 @@
  * Sets up the procedures to do on writing header after the codestream.
  * Developpers wanting to extend the library can add their own writing procedures.
  */
-static void opj_jp2_setup_end_header_writing (opj_jp2_t *jp2);
+static OPJ_BOOL opj_jp2_setup_end_header_writing (opj_jp2_t *jp2, opj_event_mgr_t * p_manager);
 
 /**
  * Sets up the procedures to do on reading header after the codestream.
  * Developpers wanting to extend the library can add their own writing procedures.
  */
-static void opj_jp2_setup_end_header_reading (opj_jp2_t *jp2);
+static OPJ_BOOL opj_jp2_setup_end_header_reading (opj_jp2_t *jp2, opj_event_mgr_t * p_manager);
 
 /**
  * Reads a jpeg2000 file header structure.
@@ -357,7 +370,7 @@
  * @param	p_number_bytes_read		pointer to an int that will store the number of bytes read from the stream (shoul usually be 2).
  * @param	p_manager				user event manager.
  *
- * @return	true if the box is reconized, false otherwise
+ * @return	true if the box is recognized, false otherwise
 */
 static OPJ_BOOL opj_jp2_read_boxhdr(opj_jp2_box_t *box,
                                     OPJ_UINT32 * p_number_bytes_read,
@@ -368,14 +381,14 @@
  * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
  * are valid. Developpers wanting to extend the library can add their own validation procedures.
  */
-static void opj_jp2_setup_encoding_validation (opj_jp2_t *jp2);
+static OPJ_BOOL opj_jp2_setup_encoding_validation (opj_jp2_t *jp2, opj_event_mgr_t * p_manager);
 
 /**
  * Sets up the procedures to do on writing header. Developpers wanting to extend the library can add their own writing procedures.
  */
-static void opj_jp2_setup_header_writing (opj_jp2_t *jp2);
+static OPJ_BOOL opj_jp2_setup_header_writing (opj_jp2_t *jp2, opj_event_mgr_t * p_manager);
 
-OPJ_BOOL opj_jp2_default_validation (	opj_jp2_t * jp2,
+static OPJ_BOOL opj_jp2_default_validation (	opj_jp2_t * jp2,
                                         opj_stream_private_t *cio,
                                         opj_event_mgr_t * p_manager );
 
@@ -397,14 +410,14 @@
  */
 static const opj_jp2_header_handler_t * opj_jp2_find_handler (OPJ_UINT32 p_id );
 
-const opj_jp2_header_handler_t jp2_header [] =
+static const opj_jp2_header_handler_t jp2_header [] =
 {
 	{JP2_JP,opj_jp2_read_jp},
 	{JP2_FTYP,opj_jp2_read_ftyp},
 	{JP2_JP2H,opj_jp2_read_jp2h}
 };
 
-const opj_jp2_header_handler_t jp2_img_header [] =
+static const opj_jp2_header_handler_t jp2_img_header [] =
 {
 	{JP2_IHDR,opj_jp2_read_ihdr},
 	{JP2_COLR,opj_jp2_read_colr},
@@ -424,7 +437,7 @@
  * @param	p_box_max_size			the maximum number of bytes in the box.
  * @param	p_manager         FIXME DOC
  *
- * @return	true if the box is reconized, false otherwise
+ * @return	true if the box is recognized, false otherwise
 */
 static OPJ_BOOL opj_jp2_read_boxhdr_char(   opj_jp2_box_t *box,
                                             OPJ_BYTE * p_data,
@@ -436,16 +449,16 @@
  * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
  * are valid. Developpers wanting to extend the library can add their own validation procedures.
  */
-static void opj_jp2_setup_decoding_validation (opj_jp2_t *jp2);
+static OPJ_BOOL opj_jp2_setup_decoding_validation (opj_jp2_t *jp2, opj_event_mgr_t * p_manager);
 
 /**
  * Sets up the procedures to do on reading header.
  * Developpers wanting to extend the library can add their own writing procedures.
  */
-static void opj_jp2_setup_header_reading (opj_jp2_t *jp2);
+static OPJ_BOOL opj_jp2_setup_header_reading (opj_jp2_t *jp2, opj_event_mgr_t * p_manager);
 
 /* ----------------------------------------------------------------------- */
- OPJ_BOOL opj_jp2_read_boxhdr(opj_jp2_box_t *box,
+static OPJ_BOOL opj_jp2_read_boxhdr(opj_jp2_box_t *box,
                               OPJ_UINT32 * p_number_bytes_read,
                               opj_stream_private_t *cio,
                               opj_event_mgr_t * p_manager )
@@ -525,7 +538,7 @@
 }
 #endif
 
-OPJ_BOOL opj_jp2_read_ihdr( opj_jp2_t *jp2,
+static OPJ_BOOL opj_jp2_read_ihdr( opj_jp2_t *jp2,
                             OPJ_BYTE *p_image_header_data,
                             OPJ_UINT32 p_image_header_size,
                             opj_event_mgr_t * p_manager )
@@ -573,7 +586,7 @@
 	return OPJ_TRUE;
 }
 
-OPJ_BYTE * opj_jp2_write_ihdr(opj_jp2_t *jp2,
+static OPJ_BYTE * opj_jp2_write_ihdr(opj_jp2_t *jp2,
                               OPJ_UINT32 * p_nb_bytes_written
                               )
 {
@@ -623,7 +636,7 @@
 	return l_ihdr_data;
 }
 
-OPJ_BYTE * opj_jp2_write_bpcc(	opj_jp2_t *jp2,
+static OPJ_BYTE * opj_jp2_write_bpcc(	opj_jp2_t *jp2,
 						        OPJ_UINT32 * p_nb_bytes_written
                                 )
 {
@@ -659,7 +672,7 @@
 	return l_bpcc_data;
 }
 
-OPJ_BOOL opj_jp2_read_bpcc( opj_jp2_t *jp2,
+static OPJ_BOOL opj_jp2_read_bpcc( opj_jp2_t *jp2,
                             OPJ_BYTE * p_bpc_header_data,
                             OPJ_UINT32 p_bpc_header_size,
                             opj_event_mgr_t * p_manager
@@ -741,7 +754,7 @@
 	return l_cdef_data;
 }
 
-OPJ_BYTE * opj_jp2_write_colr(  opj_jp2_t *jp2,
+static OPJ_BYTE * opj_jp2_write_colr(  opj_jp2_t *jp2,
 							    OPJ_UINT32 * p_nb_bytes_written
                                 )
 {
@@ -805,7 +818,7 @@
 	return l_colr_data;
 }
 
-void opj_jp2_free_pclr(opj_jp2_color_t *color)
+static void opj_jp2_free_pclr(opj_jp2_color_t *color)
 {
     opj_free(color->jp2_pclr->channel_sign);
     opj_free(color->jp2_pclr->channel_size);
@@ -836,6 +849,8 @@
 				opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", info[i].cn, nr_channels);
 				return OPJ_FALSE;
 			}
+			if (info[i].asoc == 65535U) continue;
+
 			if (info[i].asoc > 0 && (OPJ_UINT32)(info[i].asoc - 1) >= nr_channels) {
 				opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", info[i].asoc - 1, nr_channels);
 				return OPJ_FALSE;
@@ -907,6 +922,23 @@
 				is_sane = OPJ_FALSE;
 			}
 		}
+		/* Issue 235/447 weird cmap */
+		if (1 && is_sane && (image->numcomps==1U)) {
+			for (i = 0; i < nr_channels; i++) {
+				if (!pcol_usage[i]) {
+					is_sane = 0U;
+					opj_event_msg(p_manager, EVT_WARNING, "Component mapping seems wrong. Trying to correct.\n", i);
+					break;
+				}
+			}
+			if (!is_sane) {
+				is_sane = OPJ_TRUE;
+				for (i = 0; i < nr_channels; i++) {
+					cmap[i].mtyp = 1U;
+					cmap[i].pcol = (OPJ_BYTE) i;
+				}
+			}
+		}
 		opj_free(pcol_usage);
 		if (!is_sane) {
 			return OPJ_FALSE;
@@ -917,7 +949,7 @@
 }
 
 /* file9.jp2 */
-void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color)
+static void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color)
 {
 	opj_image_comp_t *old_comps, *new_comps;
 	OPJ_BYTE *channel_size, *channel_sign;
@@ -1013,7 +1045,7 @@
 
 }/* apply_pclr() */
 
-OPJ_BOOL opj_jp2_read_pclr(	opj_jp2_t *jp2,
+static OPJ_BOOL opj_jp2_read_pclr(	opj_jp2_t *jp2,
                             OPJ_BYTE * p_pclr_header_data,
                             OPJ_UINT32 p_pclr_header_size,
                             opj_event_mgr_t * p_manager
@@ -1120,7 +1152,7 @@
 	return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_jp2_read_cmap(	opj_jp2_t * jp2,
+static OPJ_BOOL opj_jp2_read_cmap(	opj_jp2_t * jp2,
                             OPJ_BYTE * p_cmap_header_data,
                             OPJ_UINT32 p_cmap_header_size,
                             opj_event_mgr_t * p_manager
@@ -1180,7 +1212,7 @@
 	return OPJ_TRUE;
 }
 
-void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color)
+static void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color, opj_event_mgr_t *manager)
 {
 	opj_jp2_cdef_info_t *info;
 	OPJ_UINT16 i, n, cn, asoc, acn;
@@ -1196,7 +1228,7 @@
 		
 		if( cn >= image->numcomps)
 		{
-			fprintf(stderr, "cn=%d, numcomps=%d\n", cn, image->numcomps);
+			opj_event_msg(manager, EVT_WARNING, "opj_jp2_apply_cdef: cn=%d, numcomps=%d\n", cn, image->numcomps);
 			continue;
 		}
 		if(asoc == 0 || asoc == 65535)
@@ -1208,7 +1240,7 @@
 		acn = (OPJ_UINT16)(asoc - 1);
 		if( acn >= image->numcomps )
 		{
-			fprintf(stderr, "acn=%d, numcomps=%d\n", acn, image->numcomps);
+			opj_event_msg(manager, EVT_WARNING, "opj_jp2_apply_cdef: acn=%d, numcomps=%d\n", acn, image->numcomps);
 			continue;
 		}
 		
@@ -1244,7 +1276,7 @@
 	
 }/* jp2_apply_cdef() */
 
-OPJ_BOOL opj_jp2_read_cdef(	opj_jp2_t * jp2,
+static OPJ_BOOL opj_jp2_read_cdef(	opj_jp2_t * jp2,
                             OPJ_BYTE * p_cdef_header_data,
 							OPJ_UINT32 p_cdef_header_size,
 							opj_event_mgr_t * p_manager
@@ -1283,15 +1315,15 @@
 	}
 
 	cdef_info = (opj_jp2_cdef_info_t*) opj_malloc(l_value * sizeof(opj_jp2_cdef_info_t));
-    if (!cdef_info)
-        return OPJ_FALSE;
+	if (!cdef_info)
+		return OPJ_FALSE;
 
 	jp2->color.jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t));
-    if(!jp2->color.jp2_cdef)
-    {
-        opj_free(cdef_info);
-        return OPJ_FALSE;
-    }
+	if(!jp2->color.jp2_cdef)
+	{
+		opj_free(cdef_info);
+		return OPJ_FALSE;
+	}
 	jp2->color.jp2_cdef->info = cdef_info;
 	jp2->color.jp2_cdef->n = (OPJ_UINT16) l_value;
 
@@ -1312,7 +1344,7 @@
 	return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_jp2_read_colr( opj_jp2_t *jp2,
+static OPJ_BOOL opj_jp2_read_colr( opj_jp2_t *jp2,
                             OPJ_BYTE * p_colr_header_data,
                             OPJ_UINT32 p_colr_header_size,
                             opj_event_mgr_t * p_manager
@@ -1353,14 +1385,59 @@
 			opj_event_msg(p_manager, EVT_ERROR, "Bad COLR header box (bad size: %d)\n", p_colr_header_size);
 			return OPJ_FALSE;
 		}
-		if (p_colr_header_size > 7) {
+		if ((p_colr_header_size > 7) && (jp2->enumcs != 14)) { /* handled below for CIELab) */
 			/* testcase Altona_Technical_v20_x4.pdf */
 			opj_event_msg(p_manager, EVT_WARNING, "Bad COLR header box (bad size: %d)\n", p_colr_header_size);
 		}
 
 		opj_read_bytes(p_colr_header_data,&jp2->enumcs ,4);			/* EnumCS */
-        
-        jp2->color.jp2_has_colr = 1;
+
+		p_colr_header_data += 4;
+
+		if(jp2->enumcs == 14)/* CIELab */
+		{
+			OPJ_UINT32 *cielab;
+			OPJ_UINT32 rl, ol, ra, oa, rb, ob, il;
+
+			cielab = (OPJ_UINT32*)opj_malloc(9 * sizeof(OPJ_UINT32));
+			cielab[0] = 14; /* enumcs */
+			
+			/* default values */
+			rl = ra = rb = ol = oa = ob = 0;
+			il = 0x00443530; /* D50 */
+			cielab[1] = 0x44454600;/* DEF */
+
+			if(p_colr_header_size == 35)
+			{
+				opj_read_bytes(p_colr_header_data, &rl, 4);
+				p_colr_header_data += 4;
+				opj_read_bytes(p_colr_header_data, &ol, 4);
+				p_colr_header_data += 4;
+				opj_read_bytes(p_colr_header_data, &ra, 4);
+				p_colr_header_data += 4;
+				opj_read_bytes(p_colr_header_data, &oa, 4);
+				p_colr_header_data += 4;
+				opj_read_bytes(p_colr_header_data, &rb, 4);
+				p_colr_header_data += 4;
+				opj_read_bytes(p_colr_header_data, &ob, 4);
+				p_colr_header_data += 4;
+				opj_read_bytes(p_colr_header_data, &il, 4);
+				p_colr_header_data += 4;
+				
+				cielab[1] = 0;
+			}
+			else if(p_colr_header_size != 7)
+			{
+				opj_event_msg(p_manager, EVT_WARNING, "Bad COLR header box (CIELab, bad size: %d)\n", p_colr_header_size);
+			}
+			cielab[2] = rl; cielab[4] = ra; cielab[6] = rb;
+			cielab[3] = ol; cielab[5] = oa; cielab[7] = ob;
+			cielab[8] = il;
+
+			jp2->color.icc_profile_buf = (OPJ_BYTE*)cielab;
+			jp2->color.icc_profile_len = 0;
+		}
+		jp2->color.jp2_has_colr = 1;
 	}
 	else if (jp2->meth == 2) {
 		/* ICC profile */
@@ -1369,11 +1446,11 @@
 
 		jp2->color.icc_profile_len = (OPJ_UINT32)icc_len;
 		jp2->color.icc_profile_buf = (OPJ_BYTE*) opj_calloc(1,(size_t)icc_len);
-        if (!jp2->color.icc_profile_buf)
-        {
-            jp2->color.icc_profile_len = 0;
-            return OPJ_FALSE;
-        }
+		if (!jp2->color.icc_profile_buf)
+		{
+			jp2->color.icc_profile_len = 0;
+			return OPJ_FALSE;
+		}
 
 		for (it_icc_value = 0; it_icc_value < icc_len; ++it_icc_value)
 		{
@@ -1382,16 +1459,16 @@
 			jp2->color.icc_profile_buf[it_icc_value] = (OPJ_BYTE) l_value;
 		}
 	    
-        jp2->color.jp2_has_colr = 1;
+		jp2->color.jp2_has_colr = 1;
 	}
 	else if (jp2->meth > 2)
-    {
-        /*	ISO/IEC 15444-1:2004 (E), Table I.9 Legal METH values:
-        conforming JP2 reader shall ignore the entire Colour Specification box.*/
-        opj_event_msg(p_manager, EVT_INFO, "COLR BOX meth value is not a regular value (%d), " 
-            "so we will ignore the entire Colour Specification box. \n", jp2->meth);
-    }
-    return OPJ_TRUE;
+	{
+		/*	ISO/IEC 15444-1:2004 (E), Table I.9 Legal METH values:
+		conforming JP2 reader shall ignore the entire Colour Specification box.*/
+		opj_event_msg(p_manager, EVT_INFO, "COLR BOX meth value is not a regular value (%d), "
+			"so we will ignore the entire Colour Specification box. \n", jp2->meth);
+	}
+	return OPJ_TRUE;
 }
 
 OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
@@ -1408,47 +1485,49 @@
 		return OPJ_FALSE;
 	}
 
-    if (!jp2->ignore_pclr_cmap_cdef){
-	    if (!opj_jp2_check_color(p_image, &(jp2->color), p_manager)) {
-		    return OPJ_FALSE;
-	    }
+	if (!jp2->ignore_pclr_cmap_cdef){
+		if (!opj_jp2_check_color(p_image, &(jp2->color), p_manager)) {
+			return OPJ_FALSE;
+		}
 
-	    /* Set Image Color Space */
-	    if (jp2->enumcs == 16)
-		    p_image->color_space = OPJ_CLRSPC_SRGB;
-	    else if (jp2->enumcs == 17)
-		    p_image->color_space = OPJ_CLRSPC_GRAY;
-	    else if (jp2->enumcs == 18)
-		    p_image->color_space = OPJ_CLRSPC_SYCC;
-            else if (jp2->enumcs == 24)
-                    p_image->color_space = OPJ_CLRSPC_EYCC;
-	    else
-		    p_image->color_space = OPJ_CLRSPC_UNKNOWN;
+		/* Set Image Color Space */
+		if (jp2->enumcs == 16)
+			p_image->color_space = OPJ_CLRSPC_SRGB;
+		else if (jp2->enumcs == 17)
+			p_image->color_space = OPJ_CLRSPC_GRAY;
+		else if (jp2->enumcs == 18)
+			p_image->color_space = OPJ_CLRSPC_SYCC;
+		else if (jp2->enumcs == 24)
+			p_image->color_space = OPJ_CLRSPC_EYCC;
+		else if (jp2->enumcs == 12)
+			p_image->color_space = OPJ_CLRSPC_CMYK;
+		else
+			p_image->color_space = OPJ_CLRSPC_UNKNOWN;
 
-	    if(jp2->color.jp2_pclr) {
-		    /* Part 1, I.5.3.4: Either both or none : */
-		    if( !jp2->color.jp2_pclr->cmap)
-			    opj_jp2_free_pclr(&(jp2->color));
-		    else
-			    opj_jp2_apply_pclr(p_image, &(jp2->color));
-	    }
+		if(jp2->color.jp2_pclr) {
+			/* Part 1, I.5.3.4: Either both or none : */
+			if( !jp2->color.jp2_pclr->cmap)
+				opj_jp2_free_pclr(&(jp2->color));
+			else if (p_image->pdfium_use_colorspace)
+				opj_jp2_apply_pclr(p_image, &(jp2->color));
+		}
 
-	    /* Apply the color space if needed */
-	    if(jp2->color.jp2_cdef) {
-		    opj_jp2_apply_cdef(p_image, &(jp2->color));
-	    }
+		/* Apply the color space if needed */
+		if(jp2->color.jp2_cdef) {
+			opj_jp2_apply_cdef(p_image, &(jp2->color), p_manager);
+		}
 
-	    if(jp2->color.icc_profile_buf) {
-		    p_image->icc_profile_buf = jp2->color.icc_profile_buf;
-		    p_image->icc_profile_len = jp2->color.icc_profile_len;
-		    jp2->color.icc_profile_buf = NULL;
-	    }
-    }
+		if(jp2->color.icc_profile_buf) {
+			p_image->icc_profile_buf = jp2->color.icc_profile_buf;
+			p_image->icc_profile_len = jp2->color.icc_profile_len;
+			jp2->color.icc_profile_buf = NULL;
+		}
+	}
 
 	return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2,
+static OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2,
                             opj_stream_private_t *stream,
                             opj_event_mgr_t * p_manager
                             )
@@ -1551,7 +1630,7 @@
 	return l_result;
 }
 
-OPJ_BOOL opj_jp2_write_ftyp(opj_jp2_t *jp2,
+static OPJ_BOOL opj_jp2_write_ftyp(opj_jp2_t *jp2,
 							opj_stream_private_t *cio,
 							opj_event_mgr_t * p_manager )
 {
@@ -1601,7 +1680,7 @@
 	return l_result;
 }
 
-OPJ_BOOL opj_jp2_write_jp2c(opj_jp2_t *jp2,
+static OPJ_BOOL opj_jp2_write_jp2c(opj_jp2_t *jp2,
 							opj_stream_private_t *cio,
 							opj_event_mgr_t * p_manager )
 {
@@ -1638,7 +1717,7 @@
 	return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_jp2_write_jp(	opj_jp2_t *jp2,
+static OPJ_BOOL opj_jp2_write_jp(	opj_jp2_t *jp2,
 			    		    opj_stream_private_t *cio,
 				    		opj_event_mgr_t * p_manager )
 {
@@ -1869,7 +1948,9 @@
 	assert(p_manager != 00);
 
 	/* customization of the end encoding */
-	opj_jp2_setup_end_header_reading(jp2);
+	if (! opj_jp2_setup_end_header_reading(jp2, p_manager)) {
+		return OPJ_FALSE;
+	}
 
 	/* write header */
 	if (! opj_jp2_exec (jp2,jp2->m_procedure_list,cio,p_manager)) {
@@ -1890,7 +1971,9 @@
 	assert(p_manager != 00);
 
 	/* customization of the end encoding */
-	opj_jp2_setup_end_header_writing(jp2);
+	if (! opj_jp2_setup_end_header_writing(jp2, p_manager)) {
+		return OPJ_FALSE;
+	}
 
 	if (! opj_j2k_end_compress(jp2->j2k,cio,p_manager)) {
 		return OPJ_FALSE;
@@ -1900,35 +1983,52 @@
 	return opj_jp2_exec(jp2,jp2->m_procedure_list,cio,p_manager);
 }
 
-void opj_jp2_setup_end_header_writing (opj_jp2_t *jp2)
+static OPJ_BOOL opj_jp2_setup_end_header_writing (opj_jp2_t *jp2, opj_event_mgr_t * p_manager)
 {
 	/* preconditions */
 	assert(jp2 != 00);
+	assert(p_manager != 00);
 
 #ifdef USE_JPIP
-  if( jp2->jpip_on )
-    opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jpip_write_iptr );
+	if( jp2->jpip_on ) {
+		if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jpip_write_iptr, p_manager)) {
+			return OPJ_FALSE;
+		}
+	}
 #endif
-	opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_jp2c );
+	if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_jp2c, p_manager)) {
+		return OPJ_FALSE;
+	}
 	/* DEVELOPER CORNER, add your custom procedures */
 #ifdef USE_JPIP
   if( jp2->jpip_on )
-    {
-    opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jpip_write_cidx );
-    opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jpip_write_fidx );
-    }
+	{
+		if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jpip_write_cidx, p_manager)) {
+			return OPJ_FALSE;
+		}
+		if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jpip_write_fidx, p_manager)) {
+			return OPJ_FALSE;
+		}
+	}
 #endif
+	return OPJ_TRUE;
 }
 
-void opj_jp2_setup_end_header_reading (opj_jp2_t *jp2)
+static OPJ_BOOL opj_jp2_setup_end_header_reading (opj_jp2_t *jp2, opj_event_mgr_t * p_manager)
 {
 	/* preconditions */
 	assert(jp2 != 00);
-	opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_read_header_procedure );
+	assert(p_manager != 00);
+	
+	if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_read_header_procedure, p_manager)) {
+		return OPJ_FALSE;
+	}
 	/* DEVELOPER CORNER, add your custom procedures */
+	
+	return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_jp2_default_validation (	opj_jp2_t * jp2,
+static OPJ_BOOL opj_jp2_default_validation (	opj_jp2_t * jp2,
                                         opj_stream_private_t *cio,
                                         opj_event_mgr_t * p_manager
                                         )
@@ -1982,7 +2082,7 @@
 	return l_is_valid;
 }
 
-OPJ_BOOL opj_jp2_read_header_procedure(  opj_jp2_t *jp2,
+static OPJ_BOOL opj_jp2_read_header_procedure(  opj_jp2_t *jp2,
                                                 opj_stream_private_t *stream,
                                                 opj_event_mgr_t * p_manager
                                                 )
@@ -1990,6 +2090,7 @@
 	opj_jp2_box_t box;
 	OPJ_UINT32 l_nb_bytes_read;
 	const opj_jp2_header_handler_t * l_current_handler;
+	const opj_jp2_header_handler_t * l_current_handler_misplaced;
 	OPJ_UINT32 l_last_data_size = OPJ_BOX_SIZE;
 	OPJ_UINT32 l_current_data_size;
 	OPJ_BYTE * l_current_data = 00;
@@ -2033,9 +2134,26 @@
 		}
 
 		l_current_handler = opj_jp2_find_handler(box.type);
+		l_current_handler_misplaced = opj_jp2_img_find_handler(box.type);
 		l_current_data_size = box.length - l_nb_bytes_read;
 
-		if (l_current_handler != 00) {
+		if ((l_current_handler != 00) || (l_current_handler_misplaced != 00)) {
+			if (l_current_handler == 00) {
+				opj_event_msg(p_manager, EVT_WARNING, "Found a misplaced '%c%c%c%c' box outside jp2h box\n", (OPJ_BYTE)(box.type>>24), (OPJ_BYTE)(box.type>>16), (OPJ_BYTE)(box.type>>8), (OPJ_BYTE)(box.type>>0));
+				if (jp2->jp2_state & JP2_STATE_HEADER) {
+					/* read anyway, we already have jp2h */
+					l_current_handler = l_current_handler_misplaced;
+				} else {
+					opj_event_msg(p_manager, EVT_WARNING, "JPEG2000 Header box not read yet, '%c%c%c%c' box will be ignored\n", (OPJ_BYTE)(box.type>>24), (OPJ_BYTE)(box.type>>16), (OPJ_BYTE)(box.type>>8), (OPJ_BYTE)(box.type>>0));
+					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");
+							opj_free(l_current_data);
+							return OPJ_FALSE;
+					}
+					continue;
+				}
+			}
 			if ((OPJ_OFF_T)l_current_data_size > opj_stream_get_number_byte_left(stream)) {
 				/* do not even try to malloc if we can't read */
 				opj_event_msg(p_manager, EVT_ERROR, "Invalid box size %d for box '%c%c%c%c'. Need %d bytes, %d bytes remaining \n", box.length, (OPJ_BYTE)(box.type>>24), (OPJ_BYTE)(box.type>>16), (OPJ_BYTE)(box.type>>8), (OPJ_BYTE)(box.type>>0), l_current_data_size, (OPJ_UINT32)opj_stream_get_number_byte_left(stream));
@@ -2142,7 +2260,9 @@
 	assert(p_manager != 00);
 
 	/* customization of the validation */
-	opj_jp2_setup_encoding_validation (jp2);
+	if (! opj_jp2_setup_encoding_validation (jp2, p_manager)) {
+		return OPJ_FALSE;
+	}
 
 	/* validation of the parameters codec */
 	if (! opj_jp2_exec(jp2,jp2->m_validation_list,stream,p_manager)) {
@@ -2150,7 +2270,9 @@
 	}
 
 	/* customization of the encoding */
-	opj_jp2_setup_header_writing(jp2);
+	if (! opj_jp2_setup_header_writing(jp2, p_manager)) {
+		return OPJ_FALSE;
+	}
 
 	/* write header */
 	if (! opj_jp2_exec (jp2,jp2->m_procedure_list,stream,p_manager)) {
@@ -2160,7 +2282,7 @@
 	return opj_j2k_start_compress(jp2->j2k,stream,p_image,p_manager);
 }
 
-const opj_jp2_header_handler_t * opj_jp2_find_handler (OPJ_UINT32 p_id)
+static const opj_jp2_header_handler_t * opj_jp2_find_handler (OPJ_UINT32 p_id)
 {
 	OPJ_UINT32 i, l_handler_size = sizeof(jp2_header) / sizeof(opj_jp2_header_handler_t);
 
@@ -2308,7 +2430,7 @@
 	return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_jp2_skip_jp2c(	opj_jp2_t *jp2,
+static OPJ_BOOL opj_jp2_skip_jp2c(	opj_jp2_t *jp2,
 					    	opj_stream_private_t *stream,
 					    	opj_event_mgr_t * p_manager )
 {
@@ -2352,7 +2474,7 @@
  * @param	p_header_size	the size of the data contained in the file header box.
  * @param	p_manager		the user event manager.
  *
- * @return true if the JP2 Header box was successfully reconized.
+ * @return true if the JP2 Header box was successfully recognized.
 */
 static OPJ_BOOL opj_jp2_read_jp2h(  opj_jp2_t *jp2,
                                     OPJ_BYTE *p_header_data,
@@ -2422,7 +2544,7 @@
 	return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_jp2_read_boxhdr_char(   opj_jp2_box_t *box,
+static OPJ_BOOL opj_jp2_read_boxhdr_char(   opj_jp2_box_t *box,
                                      OPJ_BYTE * p_data,
                                      OPJ_UINT32 * p_number_bytes_read,
                                      OPJ_UINT32 p_box_max_size,
@@ -2504,10 +2626,14 @@
 	assert(p_manager != 00);
 
 	/* customization of the validation */
-	opj_jp2_setup_decoding_validation (jp2);
+	if (! opj_jp2_setup_decoding_validation (jp2, p_manager)) {
+		return OPJ_FALSE;
+	}
 
 	/* customization of the encoding */
-	opj_jp2_setup_header_reading(jp2);
+	if (! opj_jp2_setup_header_reading(jp2, p_manager)) {
+		return OPJ_FALSE;
+	}
 
 	/* validation of the parameters codec */
 	if (! opj_jp2_exec(jp2,jp2->m_validation_list,p_stream,p_manager)) {
@@ -2525,45 +2651,73 @@
 							p_manager);
 }
 
-void opj_jp2_setup_encoding_validation (opj_jp2_t *jp2)
+static OPJ_BOOL opj_jp2_setup_encoding_validation (opj_jp2_t *jp2, opj_event_mgr_t * p_manager)
 {
 	/* preconditions */
 	assert(jp2 != 00);
+	assert(p_manager != 00);
 
-	opj_procedure_list_add_procedure(jp2->m_validation_list, (opj_procedure)opj_jp2_default_validation);
+	if (! opj_procedure_list_add_procedure(jp2->m_validation_list, (opj_procedure)opj_jp2_default_validation, p_manager)) {
+		return OPJ_FALSE;
+	}
 	/* DEVELOPER CORNER, add your custom validation procedure */
+	
+	return OPJ_TRUE;
 }
 
-void opj_jp2_setup_decoding_validation (opj_jp2_t *jp2)
+static OPJ_BOOL opj_jp2_setup_decoding_validation (opj_jp2_t *jp2, opj_event_mgr_t * p_manager)
 {
 	/* preconditions */
 	assert(jp2 != 00);
+	assert(p_manager != 00);
+	
 	/* DEVELOPER CORNER, add your custom validation procedure */
+	
+	return OPJ_TRUE;
 }
 
-void opj_jp2_setup_header_writing (opj_jp2_t *jp2)
+static OPJ_BOOL opj_jp2_setup_header_writing (opj_jp2_t *jp2, opj_event_mgr_t * p_manager)
 {
 	/* preconditions */
 	assert(jp2 != 00);
+	assert(p_manager != 00);
 
-	opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_jp );
-	opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_ftyp );
-	opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_jp2h );
-  if( jp2->jpip_on )
-    opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jpip_skip_iptr );
-	opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_skip_jp2c );
+	if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_jp, p_manager)) {
+		return OPJ_FALSE;
+	}
+	if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_ftyp, p_manager)) {
+		return OPJ_FALSE;
+	}
+	if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_jp2h, p_manager)) {
+		return OPJ_FALSE;
+	}
+	if( jp2->jpip_on ) {
+		if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jpip_skip_iptr, p_manager)) {
+			return OPJ_FALSE;
+		}
+	}
+	if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_skip_jp2c,p_manager)) {
+		return OPJ_FALSE;
+	}
 
 	/* DEVELOPER CORNER, insert your custom procedures */
 
+	return OPJ_TRUE;
 }
 
-void opj_jp2_setup_header_reading (opj_jp2_t *jp2)
+static OPJ_BOOL opj_jp2_setup_header_reading (opj_jp2_t *jp2, opj_event_mgr_t * p_manager)
 {
 	/* preconditions */
 	assert(jp2 != 00);
+	assert(p_manager != 00);
 
-	opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_read_header_procedure );
+	if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_read_header_procedure, p_manager)) {
+		return OPJ_FALSE;
+	}
+	
 	/* DEVELOPER CORNER, add your custom procedures */
+	
+	return OPJ_TRUE;
 }
 
 OPJ_BOOL opj_jp2_read_tile_header ( opj_jp2_t * p_jp2,
@@ -2719,6 +2873,10 @@
 		p_image->color_space = OPJ_CLRSPC_GRAY;
 	else if (p_jp2->enumcs == 18)
 		p_image->color_space = OPJ_CLRSPC_SYCC;
+	else if (p_jp2->enumcs == 24)
+		p_image->color_space = OPJ_CLRSPC_EYCC;
+	else if (p_jp2->enumcs == 12)
+		p_image->color_space = OPJ_CLRSPC_CMYK;
 	else
 		p_image->color_space = OPJ_CLRSPC_UNKNOWN;
 
@@ -2732,7 +2890,7 @@
 	
 	/* Apply the color space if needed */
 	if(p_jp2->color.jp2_cdef) {
-		opj_jp2_apply_cdef(p_image, &(p_jp2->color));
+		opj_jp2_apply_cdef(p_image, &(p_jp2->color), p_manager);
 	}
 
 	if(p_jp2->color.icc_profile_buf) {
diff --git a/third_party/libopenjpeg20/jp2.h b/third_party/libopenjpeg20/jp2.h
index 1e41fb6..9413883 100644
--- a/third_party/libopenjpeg20/jp2.h
+++ b/third_party/libopenjpeg20/jp2.h
@@ -90,7 +90,7 @@
 JP2_IMG_STATE;
 
 /** 
-Channel description: channel index, type, assocation
+Channel description: channel index, type, association
 */
 typedef struct opj_jp2_cdef_info
 {
@@ -236,19 +236,6 @@
 /* ----------------------------------------------------------------------- */
 
 /**
- * Writes the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box).
- *
- * @param  jp2      the jpeg2000 file codec.
- * @param  stream      the stream to write data to.
- * @param  p_manager  user event manager.
- *
- * @return true if writing was successful.
-*/
-OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2,
-                            opj_stream_private_t *stream,
-                            opj_event_mgr_t * p_manager );
-
-/**
 Setup the decoder decoding parameters using user parameters.
 Decoding parameters are returned in jp2->j2k->cp.
 @param jp2 JP2 decompressor handle
diff --git a/third_party/libopenjpeg20/mct.c b/third_party/libopenjpeg20/mct.c
index a0da099..8b0276f 100644
--- a/third_party/libopenjpeg20/mct.c
+++ b/third_party/libopenjpeg20/mct.c
@@ -70,7 +70,7 @@
 }
 
 /* <summary> */
-/* Foward reversible MCT. */
+/* Forward reversible MCT. */
 /* </summary> */
 #ifdef __SSE2__
 void opj_mct_encode(
@@ -202,7 +202,7 @@
 }
 
 /* <summary> */
-/* Foward irreversible MCT. */
+/* Forward irreversible MCT. */
 /* </summary> */
 #ifdef __SSE4_1__
 void opj_mct_encode_real(
diff --git a/third_party/libopenjpeg20/mqc.c b/third_party/libopenjpeg20/mqc.c
index 075594b..7e0f563 100644
--- a/third_party/libopenjpeg20/mqc.c
+++ b/third_party/libopenjpeg20/mqc.c
@@ -202,7 +202,7 @@
 ==========================================================
 */
 
-void opj_mqc_byteout(opj_mqc_t *mqc) {
+static void opj_mqc_byteout(opj_mqc_t *mqc) {
 	if (*mqc->bp == 0xff) {
 		mqc->bp++;
 		*mqc->bp = (OPJ_BYTE)(mqc->c >> 20);
@@ -232,7 +232,7 @@
 	}
 }
 
-void opj_mqc_renorme(opj_mqc_t *mqc) {
+static void opj_mqc_renorme(opj_mqc_t *mqc) {
 	do {
 		mqc->a <<= 1;
 		mqc->c <<= 1;
@@ -243,7 +243,7 @@
 	} while ((mqc->a & 0x8000) == 0);
 }
 
-void opj_mqc_codemps(opj_mqc_t *mqc) {
+static void opj_mqc_codemps(opj_mqc_t *mqc) {
 	mqc->a -= (*mqc->curctx)->qeval;
 	if ((mqc->a & 0x8000) == 0) {
 		if (mqc->a < (*mqc->curctx)->qeval) {
@@ -258,7 +258,7 @@
 	}
 }
 
-void opj_mqc_codelps(opj_mqc_t *mqc) {
+static void opj_mqc_codelps(opj_mqc_t *mqc) {
 	mqc->a -= (*mqc->curctx)->qeval;
 	if (mqc->a < (*mqc->curctx)->qeval) {
 		mqc->c += (*mqc->curctx)->qeval;
@@ -269,7 +269,7 @@
 	opj_mqc_renorme(mqc);
 }
 
-void opj_mqc_setbits(opj_mqc_t *mqc) {
+static void opj_mqc_setbits(opj_mqc_t *mqc) {
 	OPJ_UINT32 tempc = mqc->c + mqc->a;
 	mqc->c |= 0xffff;
 	if (mqc->c >= tempc) {
diff --git a/third_party/libopenjpeg20/openjpeg.c b/third_party/libopenjpeg20/openjpeg.c
index 4907c0c..5114cc1 100644
--- a/third_party/libopenjpeg20/openjpeg.c
+++ b/third_party/libopenjpeg20/openjpeg.c
@@ -524,14 +524,12 @@
 	opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
 
 	if ( !l_codec ){
-		fprintf(stderr, "[ERROR] Input parameters of the setup_decoder function are incorrect.\n");
 		return OPJ_FALSE;
 	}
 
-	l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor(l_codec->m_codec, 
+	return l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor(l_codec->m_codec,
 																			res_factor,
 																			&(l_codec->m_event_mgr) );
-	return OPJ_TRUE;
 }
 
 /* ---------------------------------------------------------------------- */
@@ -700,11 +698,10 @@
 		opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
 
 		if (! l_codec->is_decompressor) {
-			l_codec->m_codec_data.m_compression.opj_setup_encoder(	l_codec->m_codec,
+			return l_codec->m_codec_data.m_compression.opj_setup_encoder(	l_codec->m_codec,
 																	parameters,
 																	p_image,
 																	&(l_codec->m_event_mgr) );
-			return OPJ_TRUE;
 		}
 	}
 
@@ -869,7 +866,8 @@
 		return;
 	}
 
-	fprintf(stderr, "[ERROR] Input parameter of the dump_codec function are incorrect.\n");
+	/* TODO return error */
+	/* fprintf(stderr, "[ERROR] Input parameter of the dump_codec function are incorrect.\n"); */
 	return;
 }
 
diff --git a/third_party/libopenjpeg20/openjpeg.h b/third_party/libopenjpeg20/openjpeg.h
index 4a8e75c..e571672 100644
--- a/third_party/libopenjpeg20/openjpeg.h
+++ b/third_party/libopenjpeg20/openjpeg.h
@@ -97,7 +97,7 @@
 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
+OPJ_API functions as being imported from a DLL, whereas this DLL sees symbols
 defined with this macro as being exported.
 */
 #	if defined(OPJ_EXPORTS) || defined(DLL_EXPORT)
@@ -677,6 +677,9 @@
 	OPJ_BYTE *icc_profile_buf;
 	/** size of ICC profile */
 	OPJ_UINT32 icc_profile_len;
+
+	/** Whether to apply PCLR or not */
+	OPJ_BOOL pdfium_use_colorspace;
 } opj_image_t;
 
 
@@ -850,7 +853,7 @@
 } opj_codestream_info_t;
 
 /* <----------------------------------------------------------- */
-/* new output managment of the codestream information and index */
+/* new output management of the codestream information and index */
 
 /**
  * Tile-component coding parameters information
@@ -1347,7 +1350,7 @@
 												opj_stream_t *p_stream );
 
 /**
- * Reads a tile header. This function is compulsory and allows one to know the size of the tile thta will be decoded.
+ * Reads a tile header. This function is compulsory and allows one to know the size of the tile that will be decoded.
  * The user may need to refer to the image got by opj_read_header to understand the size being taken by the tile.
  *
  * @param	p_codec			the jpeg2000 codec.
diff --git a/third_party/libopenjpeg20/opj_includes.h b/third_party/libopenjpeg20/opj_includes.h
index e3d4686..f855b7c 100644
--- a/third_party/libopenjpeg20/opj_includes.h
+++ b/third_party/libopenjpeg20/opj_includes.h
@@ -118,33 +118,65 @@
 	#endif
 #endif
 
+
+
 /* MSVC before 2013 and Borland C do not have lrintf */
-#if defined(_MSC_VER) && (_MSC_VER < 1800) || defined(__BORLANDC__)
-static INLINE long lrintf(float f){
+#if defined(_MSC_VER)
+#include <intrin.h>
+static INLINE long opj_lrintf(float f){
 #ifdef _M_X64
-    return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f));
-#else
+	return _mm_cvt_ss2si(_mm_load_ss(&f));
+
+	/* commented out line breaks many tests */
+  /* return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f)); */
+#elif defined(_M_IX86)
     int i;
- 
-    _asm{
+     _asm{
         fld f
         fistp i
     };
  
     return i;
+#else 
+	return (long)((f>0.0f) ? (f + 0.5f) : (f - 0.5f));
 #endif
 }
+#elif defined(__BORLANDC__)
+static INLINE long opj_lrintf(float f) {
+#ifdef _M_X64
+     return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f));
+#else
+	int i;
+
+	_asm {
+		fld f
+			fistp i
+	};
+
+	return i;
+#endif
+}
+#else
+static INLINE long opj_lrintf(float f) {
+	return lrintf(f);
+}
 #endif
 
 #if defined(_MSC_VER) && (_MSC_VER < 1400)
 	#define vsnprintf _vsnprintf
 #endif
 
+/* MSVC x86 is really bad at doing int64 = int32 * int32 on its own. Use intrinsic. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER) && defined(_M_IX86)
+#	include <intrin.h>
+#	pragma intrinsic(__emul)
+#endif
+
 #include "opj_inttypes.h"
 #include "opj_clock.h"
 #include "opj_malloc.h"
-#include "function_list.h"
 #include "event.h"
+#include "function_list.h"
 #include "bio.h"
 #include "cio.h"
 
diff --git a/third_party/libopenjpeg20/opj_intmath.h b/third_party/libopenjpeg20/opj_intmath.h
index 4e29946..3f7934c 100644
--- a/third_party/libopenjpeg20/opj_intmath.h
+++ b/third_party/libopenjpeg20/opj_intmath.h
@@ -87,7 +87,7 @@
  */
 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;
+	return (OPJ_UINT32)(-(OPJ_INT32)(sum >> 32)) | (OPJ_UINT32)sum;
 }
 
 /**
@@ -135,8 +135,25 @@
 @return Returns a divided by 2^b
 */
 static INLINE OPJ_INT32 opj_int_ceildivpow2(OPJ_INT32 a, OPJ_INT32 b) {
-	return (OPJ_INT32)((a + (OPJ_INT64)(1 << b) - 1) >> b);
+	return (OPJ_INT32)((a + ((OPJ_INT64)1 << b) - 1) >> b);
 }
+
+/**
+ Divide a 64bits integer by a power of 2 and round upwards
+ @return Returns a divided by 2^b
+ */
+static INLINE OPJ_INT32 opj_int64_ceildivpow2(OPJ_INT64 a, OPJ_INT32 b) {
+	return (OPJ_INT32)((a + ((OPJ_INT64)1 << b) - 1) >> b);
+}
+
+/**
+ Divide an integer by a power of 2 and round upwards
+ @return Returns a divided by 2^b
+ */
+static INLINE OPJ_UINT32 opj_uint_ceildivpow2(OPJ_UINT32 a, OPJ_UINT32 b) {
+	return (OPJ_UINT32)((a + ((OPJ_UINT64)1U << b) - 1U) >> b);
+}
+
 /**
 Divide an integer by a power of 2 and round downwards
 @return Returns a divided by 2^b
@@ -175,7 +192,11 @@
 @return Returns a * b
 */
 static INLINE OPJ_INT32 opj_int_fix_mul(OPJ_INT32 a, OPJ_INT32 b) {
+#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER) && defined(_M_IX86)
+	OPJ_INT64 temp = __emul(a, b);
+#else
 	OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ;
+#endif
 	temp += 4096;
 	assert((temp >> 13) <= (OPJ_INT64)0x7FFFFFFF);
 	assert((temp >> 13) >= (-(OPJ_INT64)0x7FFFFFFF - (OPJ_INT64)1));
@@ -183,7 +204,11 @@
 }
 
 static INLINE OPJ_INT32 opj_int_fix_mul_t1(OPJ_INT32 a, OPJ_INT32 b) {
+#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER) && defined(_M_IX86)
+	OPJ_INT64 temp = __emul(a, b);
+#else
 	OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ;
+#endif
 	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));
diff --git a/third_party/libopenjpeg20/opj_malloc.h b/third_party/libopenjpeg20/opj_malloc.h
index 5007b0c..517707f 100644
--- a/third_party/libopenjpeg20/opj_malloc.h
+++ b/third_party/libopenjpeg20/opj_malloc.h
@@ -79,7 +79,7 @@
 #endif
 
 /**
-Allocate memory aligned to a 16 byte boundry
+Allocate memory aligned to a 16 byte boundary
 @param size Bytes to allocate
 @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
 */
diff --git a/third_party/libopenjpeg20/pi.c b/third_party/libopenjpeg20/pi.c
index d2ba3a1..06f1e41 100644
--- a/third_party/libopenjpeg20/pi.c
+++ b/third_party/libopenjpeg20/pi.c
@@ -215,7 +215,7 @@
 /**
  * FIXME DOC
  */
-OPJ_BOOL opj_pi_check_next_level(	OPJ_INT32 pos,
+static OPJ_BOOL opj_pi_check_next_level(	OPJ_INT32 pos,
 								opj_cp_t *cp,
 								OPJ_UINT32 tileno,
 								OPJ_UINT32 pino,
@@ -231,7 +231,7 @@
 ==========================================================
 */
 
-OPJ_BOOL opj_pi_next_lrcp(opj_pi_iterator_t * pi) {
+static OPJ_BOOL opj_pi_next_lrcp(opj_pi_iterator_t * pi) {
 	opj_pi_comp_t *comp = NULL;
 	opj_pi_resolution_t *res = NULL;
 	OPJ_UINT32 index = 0;
@@ -271,7 +271,7 @@
 	return OPJ_FALSE;
 }
 
-OPJ_BOOL opj_pi_next_rlcp(opj_pi_iterator_t * pi) {
+static OPJ_BOOL opj_pi_next_rlcp(opj_pi_iterator_t * pi) {
 	opj_pi_comp_t *comp = NULL;
 	opj_pi_resolution_t *res = NULL;
 	OPJ_UINT32 index = 0;
@@ -310,7 +310,7 @@
 	return OPJ_FALSE;
 }
 
-OPJ_BOOL opj_pi_next_rpcl(opj_pi_iterator_t * pi) {
+static OPJ_BOOL opj_pi_next_rpcl(opj_pi_iterator_t * pi) {
 	opj_pi_comp_t *comp = NULL;
 	opj_pi_resolution_t *res = NULL;
 	OPJ_UINT32 index = 0;
@@ -393,7 +393,7 @@
 	return OPJ_FALSE;
 }
 
-OPJ_BOOL opj_pi_next_pcrl(opj_pi_iterator_t * pi) {
+static OPJ_BOOL opj_pi_next_pcrl(opj_pi_iterator_t * pi) {
 	opj_pi_comp_t *comp = NULL;
 	opj_pi_resolution_t *res = NULL;
 	OPJ_UINT32 index = 0;
@@ -474,7 +474,7 @@
 	return OPJ_FALSE;
 }
 
-OPJ_BOOL opj_pi_next_cprl(opj_pi_iterator_t * pi) {
+static OPJ_BOOL opj_pi_next_cprl(opj_pi_iterator_t * pi) {
 	opj_pi_comp_t *comp = NULL;
 	opj_pi_resolution_t *res = NULL;
 	OPJ_UINT32 index = 0;
@@ -553,7 +553,7 @@
 	return OPJ_FALSE;
 }
 
-void opj_get_encoding_parameters(	const opj_image_t *p_image,
+static void opj_get_encoding_parameters(	const opj_image_t *p_image,
                                     const opj_cp_t *p_cp,
                                     OPJ_UINT32 p_tileno,
                                     OPJ_INT32 * p_tx0,
@@ -667,7 +667,7 @@
 }
 
 
-void opj_get_all_encoding_parameters(   const opj_image_t *p_image,
+static void opj_get_all_encoding_parameters(   const opj_image_t *p_image,
                                         const opj_cp_t *p_cp,
                                         OPJ_UINT32 tileno,
                                         OPJ_INT32 * p_tx0,
@@ -790,7 +790,7 @@
 	}
 }
 
-opj_pi_iterator_t * opj_pi_create(	const opj_image_t *image,
+static opj_pi_iterator_t * opj_pi_create(	const opj_image_t *image,
                                     const opj_cp_t *cp,
                                     OPJ_UINT32 tileno )
 {
@@ -851,7 +851,7 @@
 	return l_pi;
 }
 
-void opj_pi_update_encode_poc_and_final (   opj_cp_t *p_cp,
+static void opj_pi_update_encode_poc_and_final (   opj_cp_t *p_cp,
                                             OPJ_UINT32 p_tileno,
                                             OPJ_INT32 p_tx0,
                                             OPJ_INT32 p_tx1,
@@ -929,7 +929,7 @@
 	}
 }
 
-void opj_pi_update_encode_not_poc (	opj_cp_t *p_cp,
+static void opj_pi_update_encode_not_poc (	opj_cp_t *p_cp,
                                     OPJ_UINT32 p_num_comps,
                                     OPJ_UINT32 p_tileno,
                                     OPJ_INT32 p_tx0,
@@ -984,7 +984,7 @@
 	}
 }
 
-void opj_pi_update_decode_poc (opj_pi_iterator_t * p_pi,
+static void opj_pi_update_decode_poc (opj_pi_iterator_t * p_pi,
                                opj_tcp_t * p_tcp,
                                OPJ_UINT32 p_max_precision,
                                OPJ_UINT32 p_max_res)
@@ -1026,7 +1026,7 @@
 	}
 }
 
-void opj_pi_update_decode_not_poc (opj_pi_iterator_t * p_pi,
+static void opj_pi_update_decode_not_poc (opj_pi_iterator_t * p_pi,
                                    opj_tcp_t * p_tcp,
                                    OPJ_UINT32 p_max_precision,
                                    OPJ_UINT32 p_max_res)
@@ -1063,7 +1063,7 @@
 
 
 
-OPJ_BOOL opj_pi_check_next_level(	OPJ_INT32 pos,
+static OPJ_BOOL opj_pi_check_next_level(	OPJ_INT32 pos,
 								opj_cp_t *cp,
 								OPJ_UINT32 tileno,
 								OPJ_UINT32 pino,
@@ -1241,7 +1241,7 @@
 	if
 		(l_step_l && l_tcp->numlayers < UINT_MAX / l_step_l - 1)
 	{
-		l_current_pi->include = (OPJ_INT16*) opj_calloc((l_tcp->numlayers + 1) * l_step_l, sizeof(OPJ_INT16));
+		l_current_pi->include = (OPJ_INT16*)opj_calloc((l_tcp->numlayers + 1) * l_step_l, sizeof(OPJ_INT16));
 	}
 
 	if
@@ -1437,7 +1437,7 @@
 	l_step_l = l_max_res * l_step_r;
 
 	/* set values for first packet iterator*/
-	l_pi->tp_on = p_cp->m_specific_param.m_enc.m_tp_on;
+	l_pi->tp_on = (OPJ_BYTE)p_cp->m_specific_param.m_enc.m_tp_on;
 	l_current_pi = l_pi;
 
 	/* memory allocation for include*/
diff --git a/third_party/libopenjpeg20/pi.h b/third_party/libopenjpeg20/pi.h
index f239679..265d5b1 100644
--- a/third_party/libopenjpeg20/pi.h
+++ b/third_party/libopenjpeg20/pi.h
@@ -73,7 +73,7 @@
 typedef struct opj_pi_iterator {
   /** Enabling Tile part generation*/
   OPJ_BYTE tp_on;
-  /** precise if the packet has been already used (usefull for progression order change) */
+  /** precise if the packet has been already used (useful for progression order change) */
   OPJ_INT16 *include;
   /** layer step used to localize the packet in the include vector */
   OPJ_UINT32 step_l;
diff --git a/third_party/libopenjpeg20/t1.c b/third_party/libopenjpeg20/t1.c
index 8cb230f..108ce78 100644
--- a/third_party/libopenjpeg20/t1.c
+++ b/third_party/libopenjpeg20/t1.c
@@ -295,7 +295,7 @@
                                     OPJ_UINT32 roishift,
                                     OPJ_UINT32 cblksty);
 
-OPJ_BOOL opj_t1_allocate_buffers(   opj_t1_t *t1,
+static OPJ_BOOL opj_t1_allocate_buffers(   opj_t1_t *t1,
                                     OPJ_UINT32 w,
                                     OPJ_UINT32 h);
 
@@ -305,41 +305,41 @@
 
 /* ----------------------------------------------------------------------- */
 
-OPJ_BYTE opj_t1_getctxno_zc(OPJ_UINT32 f, OPJ_UINT32 orient) {
+static OPJ_BYTE opj_t1_getctxno_zc(OPJ_UINT32 f, OPJ_UINT32 orient) {
 	return lut_ctxno_zc[(orient << 8) | (f & T1_SIG_OTH)];
 }
 
-OPJ_BYTE opj_t1_getctxno_sc(OPJ_UINT32 f) {
+static OPJ_BYTE opj_t1_getctxno_sc(OPJ_UINT32 f) {
 	return lut_ctxno_sc[(f & (T1_SIG_PRIM | T1_SGN)) >> 4];
 }
 
-OPJ_UINT32 opj_t1_getctxno_mag(OPJ_UINT32 f) {
+static OPJ_UINT32 opj_t1_getctxno_mag(OPJ_UINT32 f) {
 	OPJ_UINT32 tmp1 = (f & T1_SIG_OTH) ? T1_CTXNO_MAG + 1 : T1_CTXNO_MAG;
 	OPJ_UINT32 tmp2 = (f & T1_REFINE) ? T1_CTXNO_MAG + 2 : tmp1;
 	return (tmp2);
 }
 
-OPJ_BYTE opj_t1_getspb(OPJ_UINT32 f) {
+static OPJ_BYTE opj_t1_getspb(OPJ_UINT32 f) {
 	return lut_spb[(f & (T1_SIG_PRIM | T1_SGN)) >> 4];
 }
 
-OPJ_INT16 opj_t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos) {
-	if (bitpos > T1_NMSEDEC_FRACBITS) {
-		return lut_nmsedec_sig[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)];
+static OPJ_INT16 opj_t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos) {
+	if (bitpos > 0) {
+		return lut_nmsedec_sig[(x >> (bitpos)) & ((1 << T1_NMSEDEC_BITS) - 1)];
 	}
 	
 	return lut_nmsedec_sig0[x & ((1 << T1_NMSEDEC_BITS) - 1)];
 }
 
-OPJ_INT16 opj_t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos) {
-	if (bitpos > T1_NMSEDEC_FRACBITS) {
-		return lut_nmsedec_ref[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)];
+static OPJ_INT16 opj_t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos) {
+	if (bitpos > 0) {
+		return lut_nmsedec_ref[(x >> (bitpos)) & ((1 << T1_NMSEDEC_BITS) - 1)];
 	}
 
     return lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)];
 }
 
-void opj_t1_updateflags(opj_flag_t *flagsp, OPJ_UINT32 s, OPJ_UINT32 stride) {
+static void opj_t1_updateflags(opj_flag_t *flagsp, OPJ_UINT32 s, OPJ_UINT32 stride) {
 	opj_flag_t *np = flagsp - stride;
 	opj_flag_t *sp = flagsp + stride;
 
@@ -363,7 +363,7 @@
 	sp[1]  |= T1_SIG_NW;
 }
 
-void opj_t1_enc_sigpass_step(   opj_t1_t *t1,
+static void opj_t1_enc_sigpass_step(   opj_t1_t *t1,
                                 opj_flag_t *flagsp,
                                 OPJ_INT32 *datap,
                                 OPJ_UINT32 orient,
@@ -390,7 +390,7 @@
 		}
 		if (v) {
 			v = *datap < 0 ? 1 : 0;
-			*nmsedec +=	opj_t1_getnmsedec_sig((OPJ_UINT32)opj_int_abs(*datap), (OPJ_UINT32)(bpno + T1_NMSEDEC_FRACBITS));
+			*nmsedec +=	opj_t1_getnmsedec_sig((OPJ_UINT32)opj_int_abs(*datap), (OPJ_UINT32)(bpno));
 			opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc(flag));	/* ESSAI */
 			if (type == T1_TYPE_RAW) {	/* BYPASS/LAZY MODE */
 				opj_mqc_bypass_enc(mqc, (OPJ_UINT32)v);
@@ -427,7 +427,7 @@
         }
 }      
 
-INLINE void opj_t1_dec_sigpass_step_mqc(
+static INLINE void opj_t1_dec_sigpass_step_mqc(
                 opj_t1_t *t1,
                 opj_flag_t *flagsp,
                 OPJ_INT32 *datap,
@@ -451,7 +451,7 @@
         }
 }                               /* VSC and  BYPASS by Antonin */
 
-INLINE void opj_t1_dec_sigpass_step_mqc_vsc(
+static INLINE void opj_t1_dec_sigpass_step_mqc_vsc(
                 opj_t1_t *t1,
                 opj_flag_t *flagsp,
                 OPJ_INT32 *datap,
@@ -478,7 +478,7 @@
 
 
 
-void opj_t1_enc_sigpass(opj_t1_t *t1,
+static void opj_t1_enc_sigpass(opj_t1_t *t1,
                         OPJ_INT32 bpno,
                         OPJ_UINT32 orient,
                         OPJ_INT32 *nmsedec,
@@ -510,7 +510,7 @@
 	}
 }
 
-void opj_t1_dec_sigpass_raw(
+static void opj_t1_dec_sigpass_raw(
                 opj_t1_t *t1,
                 OPJ_INT32 bpno,
                 OPJ_INT32 orient,
@@ -537,7 +537,7 @@
         }
 }                               /* VSC and  BYPASS by Antonin */
 
-void opj_t1_dec_sigpass_mqc(
+static void opj_t1_dec_sigpass_mqc(
                 opj_t1_t *t1,
                 OPJ_INT32 bpno,
                 OPJ_INT32 orient)
@@ -580,7 +580,7 @@
         }
 }                               /* VSC and  BYPASS by Antonin */
 
-void opj_t1_dec_sigpass_mqc_vsc(
+static void opj_t1_dec_sigpass_mqc_vsc(
                 opj_t1_t *t1,
                 OPJ_INT32 bpno,
                 OPJ_INT32 orient)
@@ -608,7 +608,7 @@
 
 
 
-void opj_t1_enc_refpass_step(   opj_t1_t *t1,
+static void opj_t1_enc_refpass_step(   opj_t1_t *t1,
                                 opj_flag_t *flagsp,
                                 OPJ_INT32 *datap,
                                 OPJ_INT32 bpno,
@@ -624,7 +624,7 @@
 	
 	flag = vsc ? (OPJ_UINT32)((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (OPJ_UINT32)(*flagsp);
 	if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) {
-		*nmsedec += opj_t1_getnmsedec_ref((OPJ_UINT32)opj_int_abs(*datap), (OPJ_UINT32)(bpno + T1_NMSEDEC_FRACBITS));
+		*nmsedec += opj_t1_getnmsedec_ref((OPJ_UINT32)opj_int_abs(*datap), (OPJ_UINT32)(bpno));
 		v = opj_int_abs(*datap) & one ? 1 : 0;
 		opj_mqc_setcurctx(mqc, opj_t1_getctxno_mag(flag));	/* ESSAI */
 		if (type == T1_TYPE_RAW) {	/* BYPASS/LAZY MODE */
@@ -636,7 +636,7 @@
 	}
 }
 
-INLINE void opj_t1_dec_refpass_step_raw(
+static INLINE void opj_t1_dec_refpass_step_raw(
                 opj_t1_t *t1,
                 opj_flag_t *flagsp,
                 OPJ_INT32 *datap,
@@ -657,7 +657,7 @@
         }
 }                               /* VSC and  BYPASS by Antonin  */
 
-INLINE void opj_t1_dec_refpass_step_mqc(
+static INLINE void opj_t1_dec_refpass_step_mqc(
                 opj_t1_t *t1,
                 opj_flag_t *flagsp,
                 OPJ_INT32 *datap,
@@ -678,7 +678,7 @@
                 }
 }                               /* VSC and  BYPASS by Antonin  */
 
-INLINE void opj_t1_dec_refpass_step_mqc_vsc(
+static INLINE void opj_t1_dec_refpass_step_mqc_vsc(
                 opj_t1_t *t1,
                 opj_flag_t *flagsp,
                 OPJ_INT32 *datap,
@@ -701,7 +701,7 @@
 }                               /* VSC and  BYPASS by Antonin  */
 
 
-void opj_t1_enc_refpass(
+static void opj_t1_enc_refpass(
 		opj_t1_t *t1,
 		OPJ_INT32 bpno,
 		OPJ_INT32 *nmsedec,
@@ -731,7 +731,7 @@
 	}
 }
 
-void opj_t1_dec_refpass_raw(
+static void opj_t1_dec_refpass_raw(
                 opj_t1_t *t1,
                 OPJ_INT32 bpno,
                 OPJ_INT32 cblksty)
@@ -758,7 +758,7 @@
         }
 }                               /* VSC and  BYPASS by Antonin */
 
-void opj_t1_dec_refpass_mqc(
+static void opj_t1_dec_refpass_mqc(
                 opj_t1_t *t1,
                 OPJ_INT32 bpno)
 {
@@ -800,7 +800,7 @@
         }
 }                               /* VSC and  BYPASS by Antonin */
 
-void opj_t1_dec_refpass_mqc_vsc(
+static void opj_t1_dec_refpass_mqc_vsc(
                 opj_t1_t *t1,
                 OPJ_INT32 bpno)
 {
@@ -827,7 +827,7 @@
 }                               /* VSC and  BYPASS by Antonin */
 
 
-void opj_t1_enc_clnpass_step(
+static void opj_t1_enc_clnpass_step(
 		opj_t1_t *t1,
 		opj_flag_t *flagsp,
 		OPJ_INT32 *datap,
@@ -853,7 +853,7 @@
 		opj_mqc_encode(mqc, (OPJ_UINT32)v);
 		if (v) {
 LABEL_PARTIAL:
-			*nmsedec += opj_t1_getnmsedec_sig((OPJ_UINT32)opj_int_abs(*datap), (OPJ_UINT32)(bpno + T1_NMSEDEC_FRACBITS));
+			*nmsedec += opj_t1_getnmsedec_sig((OPJ_UINT32)opj_int_abs(*datap), (OPJ_UINT32)(bpno));
 			opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc(flag));
 			v = *datap < 0 ? 1 : 0;
 			opj_mqc_encode(mqc, (OPJ_UINT32)(v ^ opj_t1_getspb((OPJ_UINT32)flag)));
@@ -937,7 +937,7 @@
 	*flagsp &= ~T1_VISIT;
 }
 
-void opj_t1_enc_clnpass(
+static void opj_t1_enc_clnpass(
 		opj_t1_t *t1,
 		OPJ_INT32 bpno,
 		OPJ_UINT32 orient,
@@ -962,10 +962,10 @@
 						|| (MACRO_t1_flags(1 + k + 3,1 + i) 
 						& (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW |	T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
 				} else {
-					agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
-						|| MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
-						|| MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
-						|| MACRO_t1_flags(1 + k + 3,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
+					agg = !((MACRO_t1_flags(1 + k,1 + i) | 
+						    MACRO_t1_flags(1 + k + 1,1 + i) |
+						    MACRO_t1_flags(1 + k + 2,1 + i) | 
+						     MACRO_t1_flags(1 + k + 3,1 + i)) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
 				}
 			} else {
 				agg = 0;
@@ -1061,10 +1061,10 @@
 			for (i = 0; i < t1->w; ++i) {
 				OPJ_INT32 *data2 = data1 + i;
 				opj_flag_t *flags2 = flags1 + i;
-				agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
-					|| MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
-					|| MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
-					|| MACRO_t1_flags(1 + k + 3,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
+				agg = !((MACRO_t1_flags(1 + k, 1 + i) |
+							MACRO_t1_flags(1 + k + 1, 1 + i) |
+							MACRO_t1_flags(1 + k + 2, 1 + i) |
+							MACRO_t1_flags(1 + k + 3, 1 + i)) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
 				if (agg) {
 					opj_mqc_setcurctx(mqc, T1_CTXNO_AGG);
 					if (!opj_mqc_decode(mqc)) {
@@ -1075,9 +1075,9 @@
 					runlen = (runlen << 1) | opj_mqc_decode(mqc);
 					flags2 += (OPJ_UINT32)runlen * t1->flags_stride;
 					data2 += (OPJ_UINT32)runlen * t1->w;
-					for (j = k + (OPJ_UINT32)runlen; j < k + 4 && j < t1->h; ++j) {
+					for (j = (OPJ_UINT32)runlen; j < 4 && j < t1->h; ++j) {
 						flags2 += t1->flags_stride;
-						if (agg && (j == k + (OPJ_UINT32)runlen)) {
+						if (agg && (j == (OPJ_UINT32)runlen)) {
 							opj_t1_dec_clnpass_step_partial(t1, flags2, data2, orient, oneplushalf);
 						} else {
 							opj_t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf);
@@ -1161,7 +1161,7 @@
 	return wmsedec;
 }
 
-OPJ_BOOL opj_t1_allocate_buffers(
+static OPJ_BOOL opj_t1_allocate_buffers(
 		opj_t1_t *t1,
 		OPJ_UINT32 w,
 		OPJ_UINT32 h)
@@ -1288,7 +1288,6 @@
 				for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) {
 					opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno];
 					OPJ_INT32* restrict datap;
-					/*void* restrict tiledp;*/
 					OPJ_UINT32 cblk_w, cblk_h;
 					OPJ_INT32 x, y;
 					OPJ_UINT32 i, j;
@@ -1330,14 +1329,12 @@
 							}
 						}
 					}
-
-					/*tiledp=(void*)&tilec->data[(y * tile_w) + x];*/
 					if (tccp->qmfbid == 1) {
                         OPJ_INT32* restrict tiledp = &tilec->data[(OPJ_UINT32)y * tile_w + (OPJ_UINT32)x];
 						for (j = 0; j < cblk_h; ++j) {
 							for (i = 0; i < cblk_w; ++i) {
 								OPJ_INT32 tmp = datap[(j * cblk_w) + i];
-								((OPJ_INT32*)tiledp)[(j * tile_w) + i] = tmp / 2;
+								((OPJ_INT32*)tiledp)[(j * tile_w) + i] = tmp/2;
 							}
 						}
 					} else {		/* if (tccp->qmfbid == 0) */
@@ -1349,18 +1346,11 @@
                                 *tiledp2 = tmp;
                                 datap++;
                                 tiledp2++;
-								/*float tmp = datap[(j * cblk_w) + i] * band->stepsize;
-								((float*)tiledp)[(j * tile_w) + i] = tmp;*/
-
 							}
                             tiledp += tile_w;
 						}
 					}
-                    /*opj_free(cblk->data);
-					opj_free(cblk->segs);*/
-					/*cblk->segs = 00;*/
 				} /* cblkno */
-                /*opj_free(precinct->cblks.dec);*/
 			} /* precno */
 		} /* bandno */
 	} /* resno */
@@ -1368,7 +1358,7 @@
 }
 
 
-OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1,
+static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1,
                             opj_tcd_cblk_dec_t* cblk,
                             OPJ_UINT32 orient,
                             OPJ_UINT32 roishift,
@@ -1377,7 +1367,7 @@
 	opj_raw_t *raw = t1->raw;	/* RAW component */
 	opj_mqc_t *mqc = t1->mqc;	/* MQC component */
 
-	OPJ_INT32 bpno;
+	OPJ_INT32 bpno_plus_one;
 	OPJ_UINT32 passtype;
 	OPJ_UINT32 segno, passno;
 	OPJ_BYTE type = T1_TYPE_MQ; /* BYPASS mode */
@@ -1390,7 +1380,7 @@
 		return OPJ_FALSE;
 	}
 
-	bpno = (OPJ_INT32)(roishift + cblk->numbps - 1);
+	bpno_plus_one = (OPJ_INT32)(roishift + cblk->numbps);
 	passtype = 2;
 
 	opj_mqc_resetstates(mqc);
@@ -1402,7 +1392,7 @@
 		opj_tcd_seg_t *seg = &cblk->segs[segno];
 
 		/* BYPASS mode */
-		type = ((bpno <= ((OPJ_INT32) (cblk->numbps) - 1) - 4) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
+		type = ((bpno_plus_one <= ((OPJ_INT32) (cblk->numbps)) - 4) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
 		/* FIXME: slviewer gets here with a null pointer. Why? Partially downloaded and/or corrupt textures? */
 		if(seg->data == 00){
 			continue;
@@ -1419,28 +1409,28 @@
             switch (passtype) {
                 case 0:
                     if (type == T1_TYPE_RAW) {
-                        opj_t1_dec_sigpass_raw(t1, bpno+1, (OPJ_INT32)orient, (OPJ_INT32)cblksty);
+                        opj_t1_dec_sigpass_raw(t1, bpno_plus_one, (OPJ_INT32)orient, (OPJ_INT32)cblksty);
                     } else {
                         if (cblksty & J2K_CCP_CBLKSTY_VSC) {
-                            opj_t1_dec_sigpass_mqc_vsc(t1, bpno+1, (OPJ_INT32)orient);
+                            opj_t1_dec_sigpass_mqc_vsc(t1, bpno_plus_one, (OPJ_INT32)orient);
                         } else {
-                            opj_t1_dec_sigpass_mqc(t1, bpno+1, (OPJ_INT32)orient);
+                            opj_t1_dec_sigpass_mqc(t1, bpno_plus_one, (OPJ_INT32)orient);
                         }
                     }
                     break;
                 case 1:
                     if (type == T1_TYPE_RAW) {
-                            opj_t1_dec_refpass_raw(t1, bpno+1, (OPJ_INT32)cblksty);
+                            opj_t1_dec_refpass_raw(t1, bpno_plus_one, (OPJ_INT32)cblksty);
                     } else {
                         if (cblksty & J2K_CCP_CBLKSTY_VSC) {
-                            opj_t1_dec_refpass_mqc_vsc(t1, bpno+1);
+                            opj_t1_dec_refpass_mqc_vsc(t1, bpno_plus_one);
                         } else {
-                            opj_t1_dec_refpass_mqc(t1, bpno+1);
+                            opj_t1_dec_refpass_mqc(t1, bpno_plus_one);
                         }
                     }
                     break;
                 case 2:
-                    opj_t1_dec_clnpass(t1, bpno+1, (OPJ_INT32)orient, (OPJ_INT32)cblksty);
+                    opj_t1_dec_clnpass(t1, bpno_plus_one, (OPJ_INT32)orient, (OPJ_INT32)cblksty);
                     break;
             }
 
@@ -1452,11 +1442,11 @@
 			}
 			if (++passtype == 3) {
 				passtype = 0;
-				bpno--;
+				bpno_plus_one--;
 			}
 		}
 	}
-        return OPJ_TRUE;
+    return OPJ_TRUE;
 }
 
 
@@ -1566,7 +1556,7 @@
 }
 
 /** mod fixed_quality */
-void opj_t1_encode_cblk(opj_t1_t *t1,
+static void opj_t1_encode_cblk(opj_t1_t *t1,
                         opj_tcd_cblk_enc_t* cblk,
                         OPJ_UINT32 orient,
                         OPJ_UINT32 compno,
@@ -1706,7 +1696,7 @@
 }
 
 #if 0
-void opj_t1_dec_refpass_step(   opj_t1_t *t1,
+static void opj_t1_dec_refpass_step(   opj_t1_t *t1,
                                 opj_flag_t *flagsp,
                                 OPJ_INT32 *datap,
                                 OPJ_INT32 poshalf,
@@ -1738,7 +1728,7 @@
 
 
 #if 0
-void opj_t1_dec_sigpass_step(   opj_t1_t *t1,
+static void opj_t1_dec_sigpass_step(   opj_t1_t *t1,
                                 opj_flag_t *flagsp,
                                 OPJ_INT32 *datap,
                                 OPJ_UINT32 orient,
diff --git a/third_party/libopenjpeg20/t2.c b/third_party/libopenjpeg20/t2.c
index 6f0ac91..5af1a69 100644
--- a/third_party/libopenjpeg20/t2.c
+++ b/third_party/libopenjpeg20/t2.c
@@ -97,7 +97,8 @@
                                         OPJ_BYTE *src,
                                         OPJ_UINT32 * data_read,
                                         OPJ_UINT32 max_length,
-                                        opj_packet_info_t *pack_info);
+                                        opj_packet_info_t *pack_info,
+                                        opj_event_mgr_t *p_manager);
 
 static OPJ_BOOL opj_t2_skip_packet( opj_t2_t* p_t2,
                                     opj_tcd_tile_t *p_tile,
@@ -106,7 +107,8 @@
                                     OPJ_BYTE *p_src,
                                     OPJ_UINT32 * p_data_read,
                                     OPJ_UINT32 p_max_length,
-                                    opj_packet_info_t *p_pack_info);
+                                    opj_packet_info_t *p_pack_info,
+                                    opj_event_mgr_t *p_manager);
 
 static OPJ_BOOL opj_t2_read_packet_header(  opj_t2_t* p_t2,
                                             opj_tcd_tile_t *p_tile,
@@ -116,7 +118,8 @@
                                             OPJ_BYTE *p_src_data,
                                             OPJ_UINT32 * p_data_read,
                                             OPJ_UINT32 p_max_length,
-                                            opj_packet_info_t *p_pack_info);
+                                            opj_packet_info_t *p_pack_info,
+                                            opj_event_mgr_t *p_manager);
 
 static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2,
                                         opj_tcd_tile_t *p_tile,
@@ -124,14 +127,16 @@
                                         OPJ_BYTE *p_src_data,
                                         OPJ_UINT32 * p_data_read,
                                         OPJ_UINT32 p_max_length,
-                                        opj_packet_info_t *pack_info);
+                                        opj_packet_info_t *pack_info,
+                                        opj_event_mgr_t *p_manager);
 
 static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2,
                                         opj_tcd_tile_t *p_tile,
                                         opj_pi_iterator_t *p_pi,
                                         OPJ_UINT32 * p_data_read,
                                         OPJ_UINT32 p_max_length,
-                                        opj_packet_info_t *pack_info);
+                                        opj_packet_info_t *pack_info,
+                                        opj_event_mgr_t *p_manager);
 
 /**
 @param cblk
@@ -158,7 +163,7 @@
         opj_bio_write(bio, 0, 1);
 }
 
-OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio) 
+static OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio)
 {
     OPJ_UINT32 n = 0;
     while (opj_bio_read(bio, 1)) {
@@ -167,7 +172,7 @@
     return n;
 }
 
-void opj_t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n) {
+static void opj_t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n) {
         if (n == 1) {
                 opj_bio_write(bio, 0, 1);
         } else if (n == 2) {
@@ -181,7 +186,7 @@
         }
 }
 
-OPJ_UINT32 opj_t2_getnumpasses(opj_bio_t *bio) {
+static OPJ_UINT32 opj_t2_getnumpasses(opj_bio_t *bio) {
         OPJ_UINT32 n;
         if (!opj_bio_read(bio, 1))
                 return 1;
@@ -345,7 +350,8 @@
                                 OPJ_BYTE *p_src,
                                 OPJ_UINT32 * p_data_read,
                                 OPJ_UINT32 p_max_len,
-                                opj_codestream_index_t *p_cstr_index)
+                                opj_codestream_index_t *p_cstr_index,
+                                opj_event_mgr_t *p_manager)
 {
         OPJ_BYTE *l_current_data = p_src;
         opj_pi_iterator_t *l_pi = 00;
@@ -413,7 +419,7 @@
 
                                 first_pass_failed[l_current_pi->compno] = OPJ_FALSE;
 
-                                if (! opj_t2_decode_packet(p_t2,p_tile,l_tcp,l_current_pi,l_current_data,&l_nb_bytes_read,p_max_len,l_pack_info)) {
+                                if (! opj_t2_decode_packet(p_t2,p_tile,l_tcp,l_current_pi,l_current_data,&l_nb_bytes_read,p_max_len,l_pack_info, p_manager)) {
                                         opj_pi_destroy(l_pi,l_nb_pocs);
                                         opj_free(first_pass_failed);
                                         return OPJ_FALSE;
@@ -424,7 +430,7 @@
                         }
                         else {
                                 l_nb_bytes_read = 0;
-                                if (! opj_t2_skip_packet(p_t2,p_tile,l_tcp,l_current_pi,l_current_data,&l_nb_bytes_read,p_max_len,l_pack_info)) {
+                                if (! opj_t2_skip_packet(p_t2,p_tile,l_tcp,l_current_pi,l_current_data,&l_nb_bytes_read,p_max_len,l_pack_info, p_manager)) {
                                         opj_pi_destroy(l_pi,l_nb_pocs);
                                         opj_free(first_pass_failed);
                                         return OPJ_FALSE;
@@ -511,14 +517,15 @@
         }
 }
 
-OPJ_BOOL opj_t2_decode_packet(  opj_t2_t* p_t2,
+static OPJ_BOOL opj_t2_decode_packet(  opj_t2_t* p_t2,
                                 opj_tcd_tile_t *p_tile,
                                 opj_tcp_t *p_tcp,
                                 opj_pi_iterator_t *p_pi,
                                 OPJ_BYTE *p_src,
                                 OPJ_UINT32 * p_data_read,
                                 OPJ_UINT32 p_max_length,
-                                opj_packet_info_t *p_pack_info)
+                                opj_packet_info_t *p_pack_info,
+                                opj_event_mgr_t *p_manager)
 {
         OPJ_BOOL l_read_data;
         OPJ_UINT32 l_nb_bytes_read = 0;
@@ -526,7 +533,7 @@
 
         *p_data_read = 0;
 
-        if (! opj_t2_read_packet_header(p_t2,p_tile,p_tcp,p_pi,&l_read_data,p_src,&l_nb_bytes_read,p_max_length,p_pack_info)) {
+        if (! opj_t2_read_packet_header(p_t2,p_tile,p_tcp,p_pi,&l_read_data,p_src,&l_nb_bytes_read,p_max_length,p_pack_info, p_manager)) {
                 return OPJ_FALSE;
         }
 
@@ -538,7 +545,7 @@
         if (l_read_data) {
                 l_nb_bytes_read = 0;
 
-                if (! opj_t2_read_packet_data(p_t2,p_tile,p_pi,p_src,&l_nb_bytes_read,p_max_length,p_pack_info)) {
+                if (! opj_t2_read_packet_data(p_t2,p_tile,p_pi,p_src,&l_nb_bytes_read,p_max_length,p_pack_info, p_manager)) {
                         return OPJ_FALSE;
                 }
 
@@ -550,7 +557,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_t2_encode_packet(  OPJ_UINT32 tileno,
+static OPJ_BOOL opj_t2_encode_packet(  OPJ_UINT32 tileno,
                                 opj_tcd_tile_t * tile,
                                 opj_tcp_t * tcp,
                                 opj_pi_iterator_t *pi,
@@ -793,7 +800,8 @@
                                     OPJ_BYTE *p_src,
                                     OPJ_UINT32 * p_data_read,
                                     OPJ_UINT32 p_max_length,
-                                    opj_packet_info_t *p_pack_info)
+                                    opj_packet_info_t *p_pack_info,
+                                    opj_event_mgr_t *p_manager)
 {
         OPJ_BOOL l_read_data;
         OPJ_UINT32 l_nb_bytes_read = 0;
@@ -801,7 +809,7 @@
 
         *p_data_read = 0;
 
-        if (! opj_t2_read_packet_header(p_t2,p_tile,p_tcp,p_pi,&l_read_data,p_src,&l_nb_bytes_read,p_max_length,p_pack_info)) {
+        if (! opj_t2_read_packet_header(p_t2,p_tile,p_tcp,p_pi,&l_read_data,p_src,&l_nb_bytes_read,p_max_length,p_pack_info, p_manager)) {
                 return OPJ_FALSE;
         }
 
@@ -813,7 +821,7 @@
         if (l_read_data) {
                 l_nb_bytes_read = 0;
 
-                if (! opj_t2_skip_packet_data(p_t2,p_tile,p_pi,&l_nb_bytes_read,p_max_length,p_pack_info)) {
+                if (! opj_t2_skip_packet_data(p_t2,p_tile,p_pi,&l_nb_bytes_read,p_max_length,p_pack_info, p_manager)) {
                         return OPJ_FALSE;
                 }
 
@@ -825,7 +833,7 @@
 }
 
 
-OPJ_BOOL opj_t2_read_packet_header( opj_t2_t* p_t2,
+static OPJ_BOOL opj_t2_read_packet_header( opj_t2_t* p_t2,
                                     opj_tcd_tile_t *p_tile,
                                     opj_tcp_t *p_tcp,
                                     opj_pi_iterator_t *p_pi,
@@ -833,7 +841,8 @@
                                     OPJ_BYTE *p_src_data,
                                     OPJ_UINT32 * p_data_read,
                                     OPJ_UINT32 p_max_length,
-                                    opj_packet_info_t *p_pack_info)
+                                    opj_packet_info_t *p_pack_info,
+                                    opj_event_mgr_t *p_manager)
 
 {
         /* loop */
@@ -882,11 +891,9 @@
 
         if (p_tcp->csty & J2K_CP_CSTY_SOP) {
                 if (p_max_length < 6) {
-                        /* TODO opj_event_msg(p_t2->cinfo->event_mgr, EVT_WARNING, "Not enough space for expected SOP marker\n"); */
-                        fprintf(stderr, "Not enough space for expected SOP marker\n");
+												opj_event_msg(p_manager, EVT_WARNING, "Not enough space for expected SOP marker\n");
                 } else if ((*l_current_data) != 0xff || (*(l_current_data + 1) != 0x91)) {
-                        /* TODO opj_event_msg(p_t2->cinfo->event_mgr, EVT_WARNING, "Expected SOP marker\n"); */
-                        fprintf(stderr, "Warning: expected SOP marker\n");
+                        opj_event_msg(p_manager, EVT_WARNING, "Expected SOP marker\n");
                 } else {
                         l_current_data += 6;
                 }
@@ -937,9 +944,9 @@
                 /* EPH markers */
                 if (p_tcp->csty & J2K_CP_CSTY_EPH) {
                         if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data - *l_header_data_start)) < 2U) {
-                                fprintf(stderr, "Not enough space for expected EPH marker\n");
+                                opj_event_msg(p_manager, EVT_WARNING, "Not enough space for expected EPH marker\n");
                         } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) {
-                                fprintf(stderr, "Error : expected EPH marker\n");
+                                opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n");
                         } else {
                                 l_header_data += 2;
                         }
@@ -990,7 +997,7 @@
                         if (!l_included) {
                                 l_cblk->numnewpasses = 0;
                                 ++l_cblk;
-        JAS_FPRINTF(stderr, "included=%d \n", l_included);
+                                JAS_FPRINTF(stderr, "included=%d \n", l_included);
                                 continue;
                         }
 
@@ -1065,10 +1072,9 @@
         /* EPH markers */
         if (p_tcp->csty & J2K_CP_CSTY_EPH) {
                 if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data - *l_header_data_start)) < 2U) {
-                        fprintf(stderr, "Not enough space for expected EPH marker\n");
+                        opj_event_msg(p_manager, EVT_WARNING, "Not enough space for expected EPH marker\n");
                 } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) {
-                        /* TODO opj_event_msg(t2->cinfo->event_mgr, EVT_ERROR, "Expected EPH marker\n"); */
-                        fprintf(stderr, "Error : expected EPH marker\n");
+                        opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n");
                 } else {
                         l_header_data += 2;
                 }
@@ -1094,13 +1100,14 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_t2_read_packet_data(   opj_t2_t* p_t2,
+static OPJ_BOOL opj_t2_read_packet_data(   opj_t2_t* p_t2,
                                     opj_tcd_tile_t *p_tile,
                                     opj_pi_iterator_t *p_pi,
                                     OPJ_BYTE *p_src_data,
                                     OPJ_UINT32 * p_data_read,
                                     OPJ_UINT32 p_max_length,
-                                    opj_packet_info_t *pack_info)
+                                    opj_packet_info_t *pack_info,
+                                    opj_event_mgr_t* p_manager)
 {
         OPJ_UINT32 bandno, cblkno;
         OPJ_UINT32 l_nb_code_blocks;
@@ -1150,8 +1157,8 @@
                         do {
                                 /* Check possible overflow (on l_current_data only, assumes input args already checked) then size */
                                 if ((((OPJ_SIZE_T)l_current_data + (OPJ_SIZE_T)l_seg->newlen) < (OPJ_SIZE_T)l_current_data) || (l_current_data + l_seg->newlen > p_src_data + p_max_length)) {
-                                        fprintf(stderr, "read: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
-                                                l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno);
+                                        opj_event_msg(p_manager, EVT_ERROR, "read: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
+																								l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno);
                                         return OPJ_FALSE;
                                 }
 
@@ -1161,22 +1168,22 @@
 
                                 /* let's check that we are not exceeding */
                                 if ((l_cblk->len + l_seg->newlen) > 8192) {
-                                        opj_event_msg(p_t2->cinfo, EVT_WARNING,
+                                        opj_event_msg(p_manager, EVT_WARNING,
                                                 "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
                                                 l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno);
                                         if (!JPWL_ASSUME) {
-                                                opj_event_msg(p_t2->cinfo, EVT_ERROR, "JPWL: giving up\n");
+                                                opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n");
                                                 return OPJ_FALSE;
                                         }
                                         l_seg->newlen = 8192 - l_cblk->len;
-                                        opj_event_msg(p_t2->cinfo, EVT_WARNING, "      - truncating segment to %d\n", l_seg->newlen);
+                                        opj_event_msg(p_manager, EVT_WARNING, "      - truncating segment to %d\n", l_seg->newlen);
                                         break;
                                 };
 
 #endif /* USE_JPWL */
                                 /* Check possible overflow on size */
                                 if ((l_cblk->data_current_size + l_seg->newlen) < l_cblk->data_current_size) {
-                                        fprintf(stderr, "read: segment too long (%d) with current size (%d > %d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
+                                        opj_event_msg(p_manager, EVT_ERROR, "read: segment too long (%d) with current size (%d > %d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
                                                 l_seg->newlen, l_cblk->data_current_size, 0xFFFFFFFF - l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno);
                                         return OPJ_FALSE;
                                 }
@@ -1228,12 +1235,13 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_t2_skip_packet_data(   opj_t2_t* p_t2,
+static OPJ_BOOL opj_t2_skip_packet_data(   opj_t2_t* p_t2,
                                     opj_tcd_tile_t *p_tile,
                                     opj_pi_iterator_t *p_pi,
                                     OPJ_UINT32 * p_data_read,
                                     OPJ_UINT32 p_max_length,
-                                    opj_packet_info_t *pack_info)
+                                    opj_packet_info_t *pack_info,
+                                    opj_event_mgr_t *p_manager)
 {
         OPJ_UINT32 bandno, cblkno;
         OPJ_UINT32 l_nb_code_blocks;
@@ -1284,7 +1292,7 @@
                         do {
                                 /* Check possible overflow then size */
                                 if (((*p_data_read + l_seg->newlen) < (*p_data_read)) || ((*p_data_read + l_seg->newlen) > p_max_length)) {
-                                        fprintf(stderr, "skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
+                                        opj_event_msg(p_manager, EVT_ERROR, "skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
                                                 l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno);
                                         return OPJ_FALSE;
                                 }
@@ -1295,15 +1303,15 @@
 
                                 /* let's check that we are not exceeding */
                                 if ((l_cblk->len + l_seg->newlen) > 8192) {
-                                        opj_event_msg(p_t2->cinfo, EVT_WARNING,
+                                        opj_event_msg(p_manager, EVT_WARNING,
                                                 "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
                                                 l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno);
                                         if (!JPWL_ASSUME) {
-                                                opj_event_msg(p_t2->cinfo, EVT_ERROR, "JPWL: giving up\n");
+                                                opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n");
                                                 return -999;
                                         }
                                         l_seg->newlen = 8192 - l_cblk->len;
-                                        opj_event_msg(p_t2->cinfo, EVT_WARNING, "      - truncating segment to %d\n", l_seg->newlen);
+                                        opj_event_msg(p_manager, EVT_WARNING, "      - truncating segment to %d\n", l_seg->newlen);
                                         break;
                                 };
 
diff --git a/third_party/libopenjpeg20/t2.h b/third_party/libopenjpeg20/t2.h
index 931141e..3b652ee 100644
--- a/third_party/libopenjpeg20/t2.h
+++ b/third_party/libopenjpeg20/t2.h
@@ -108,7 +108,8 @@
                                 OPJ_BYTE *src,
                                 OPJ_UINT32 * p_data_read,
                                 OPJ_UINT32 len,
-                                opj_codestream_index_t *cstr_info);
+                                opj_codestream_index_t *cstr_info,
+                                opj_event_mgr_t *p_manager);
 
 /**
  * Creates a Tier 2 handle
diff --git a/third_party/libopenjpeg20/tcd.c b/third_party/libopenjpeg20/tcd.c
index f623120..2fccff1 100644
--- a/third_party/libopenjpeg20/tcd.c
+++ b/third_party/libopenjpeg20/tcd.c
@@ -107,7 +107,7 @@
 /**
  * Initializes tile coding/decoding
  */
-static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block);
+static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block, opj_event_mgr_t* manager);
 
 /**
 * Allocates memory for a decoding code block.
@@ -146,13 +146,14 @@
                                     OPJ_BYTE * p_src_data,
                                     OPJ_UINT32 * p_data_read,
                                     OPJ_UINT32 p_max_src_size,
-                                    opj_codestream_index_t *p_cstr_index );
+                                    opj_codestream_index_t *p_cstr_index,
+                                    opj_event_mgr_t *p_manager);
 
 static OPJ_BOOL opj_tcd_t1_decode (opj_tcd_t *p_tcd);
 
 static OPJ_BOOL opj_tcd_dwt_decode (opj_tcd_t *p_tcd);
 
-static OPJ_BOOL opj_tcd_mct_decode (opj_tcd_t *p_tcd);
+static OPJ_BOOL opj_tcd_mct_decode (opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager);
 
 static OPJ_BOOL opj_tcd_dc_level_shift_decode (opj_tcd_t *p_tcd);
 
@@ -267,7 +268,7 @@
                                                                         n = passno + 1;
                                                                 continue;
                                                         }
-                                                        if (dd / dr >= thresh)
+                                                        if (thresh - (dd / dr) < DBL_EPSILON) /* do not rely on float equality, check with DBL_EPSILON margin */
                                                                 n = passno + 1;
                                                 }
 
@@ -655,7 +656,7 @@
 
 /* ----------------------------------------------------------------------- */
 
-static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block)
+static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block, opj_event_mgr_t* manager)
 {
 	OPJ_UINT32 (*l_gain_ptr)(OPJ_UINT32) = 00;
 	OPJ_UINT32 compno, resno, bandno, precno, cblkno;
@@ -711,7 +712,7 @@
 
 	/* testcase 1888.pdf.asan.35.988 */
 	if (l_tccp->numresolutions == 0) {
-		fprintf(stderr, "tiles require at least one resolution\n");
+		opj_event_msg(manager, EVT_ERROR, "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);*/
@@ -730,13 +731,13 @@
 		/* 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)) {
-			/* TODO event */
+			opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
 			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 */
+			opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
 			return OPJ_FALSE;
 		}
 		l_data_size = l_data_size * (OPJ_UINT32)sizeof(OPJ_UINT32);
@@ -750,6 +751,7 @@
 		
 		l_tilec->data_size_needed = l_data_size;
 		if (p_tcd->m_is_decoder && !opj_alloc_tile_component_data(l_tilec)) {
+			opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
 			return OPJ_FALSE;
 		}
 		
@@ -767,8 +769,7 @@
 		else if (l_data_size > l_tilec->resolutions_size) {
 			opj_tcd_resolution_t* new_resolutions = (opj_tcd_resolution_t *) opj_realloc(l_tilec->resolutions, l_data_size);
 			if (! new_resolutions) {
-				/* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to tile resolutions\n");                                                                                         */
-				fprintf(stderr, "Not enough memory to tile resolutions\n");
+				opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile resolutions\n");
 				opj_free(l_tilec->resolutions);
 				l_tilec->resolutions = NULL;
 				l_tilec->resolutions_size = 0;
@@ -861,10 +862,10 @@
 					/* y0b = 1 if bandno = 2 or 3 */
 					l_y0b = (OPJ_INT32)((l_band->bandno)>>1);
 					/* l_band border (global) */
-					l_band->x0 = opj_int_ceildivpow2(l_tilec->x0 - (1 << l_level_no) * l_x0b, (OPJ_INT32)(l_level_no + 1));
-					l_band->y0 = opj_int_ceildivpow2(l_tilec->y0 - (1 << l_level_no) * l_y0b, (OPJ_INT32)(l_level_no + 1));
-					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));
+					l_band->x0 = opj_int64_ceildivpow2(l_tilec->x0 - ((OPJ_INT64)l_x0b << l_level_no), (OPJ_INT32)(l_level_no + 1));
+					l_band->y0 = opj_int64_ceildivpow2(l_tilec->y0 - ((OPJ_INT64)l_y0b << l_level_no), (OPJ_INT32)(l_level_no + 1));
+					l_band->x1 = opj_int64_ceildivpow2(l_tilec->x1 - ((OPJ_INT64)l_x0b << l_level_no), (OPJ_INT32)(l_level_no + 1));
+					l_band->y1 = opj_int64_ceildivpow2(l_tilec->y1 - ((OPJ_INT64)l_y0b << l_level_no), (OPJ_INT32)(l_level_no + 1));
 				}
 				
 				/** avoid an if with storing function pointer */
@@ -886,8 +887,7 @@
 					
 					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");                                                                    */
-						fprintf(stderr, "Not enough memory to handle band precints\n");
+						opj_event_msg(manager, EVT_ERROR, "Not enough memory to handle band precints\n");
 						opj_free(l_band->precincts);
 						l_band->precincts = NULL;
 						l_band->precincts_data_size = 0;
@@ -950,8 +950,7 @@
 							opj_free(l_current_precinct->cblks.blocks);
 							l_current_precinct->cblks.blocks = NULL;
 							l_current_precinct->block_size = 0;
-							/* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory for current precinct codeblock element\n");                                              */
-							fprintf(stderr, "Not enough memory for current precinct codeblock element\n");
+							opj_event_msg(manager, EVT_ERROR, "Not enough memory for current precinct codeblock element\n");
 							return OPJ_FALSE;
 						}
 						l_current_precinct->cblks.blocks = new_blocks;
@@ -965,34 +964,26 @@
 					}
 					
 					if (! l_current_precinct->incltree) {
-						l_current_precinct->incltree = opj_tgt_create(l_current_precinct->cw,
-																													l_current_precinct->ch);
+						l_current_precinct->incltree = opj_tgt_create(l_current_precinct->cw, l_current_precinct->ch, manager);
 					}
 					else{
-						l_current_precinct->incltree = opj_tgt_init(l_current_precinct->incltree,
-																												l_current_precinct->cw,
-																												l_current_precinct->ch);
+						l_current_precinct->incltree = opj_tgt_init(l_current_precinct->incltree, l_current_precinct->cw, l_current_precinct->ch, manager);
 					}
 
 					if (! l_current_precinct->incltree)     {
-						fprintf(stderr, "WARNING: No incltree created.\n");
+						opj_event_msg(manager, EVT_WARNING, "No incltree created.\n");
 						/*return OPJ_FALSE;*/
 					}
 
 					if (! l_current_precinct->imsbtree) {
-						l_current_precinct->imsbtree = opj_tgt_create(
-																													l_current_precinct->cw,
-																													l_current_precinct->ch);
+						l_current_precinct->imsbtree = opj_tgt_create(l_current_precinct->cw, l_current_precinct->ch, manager);
 					}
 					else {
-						l_current_precinct->imsbtree = opj_tgt_init(
-																												l_current_precinct->imsbtree,
-																												l_current_precinct->cw,
-																												l_current_precinct->ch);
+						l_current_precinct->imsbtree = opj_tgt_init(l_current_precinct->imsbtree, l_current_precinct->cw, l_current_precinct->ch, manager);
 					}
 
 					if (! l_current_precinct->imsbtree) {
-						fprintf(stderr, "WARNING: No imsbtree created.\n");
+						opj_event_msg(manager, EVT_WARNING, "No imsbtree created.\n");
 						/*return OPJ_FALSE;*/
 					}
 
@@ -1045,14 +1036,14 @@
 	return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_tcd_init_encode_tile (opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no)
+OPJ_BOOL opj_tcd_init_encode_tile (opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager)
 {
-	return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_TRUE, 1.0F, sizeof(opj_tcd_cblk_enc_t));
+	return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_TRUE, 1.0F, sizeof(opj_tcd_cblk_enc_t), p_manager);
 }
 
-OPJ_BOOL opj_tcd_init_decode_tile (opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no)
+OPJ_BOOL opj_tcd_init_decode_tile (opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager)
 {
-	return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_FALSE, 0.5F, sizeof(opj_tcd_cblk_dec_t));
+	return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_FALSE, 0.5F, sizeof(opj_tcd_cblk_dec_t), p_manager);
 }
 
 /**
@@ -1089,7 +1080,7 @@
 		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);
+		p_code_block->data = (OPJ_BYTE*) opj_malloc(l_data_size+1);
 		if(! p_code_block->data) {
 			p_code_block->data_size = 0U;
 			return OPJ_FALSE;
@@ -1266,7 +1257,8 @@
                                 OPJ_BYTE *p_src,
                                 OPJ_UINT32 p_max_length,
                                 OPJ_UINT32 p_tile_no,
-                                opj_codestream_index_t *p_cstr_index
+                                opj_codestream_index_t *p_cstr_index,
+                                opj_event_mgr_t *p_manager
                                 )
 {
         OPJ_UINT32 l_data_read;
@@ -1299,7 +1291,7 @@
         /*--------------TIER2------------------*/
         /* FIXME _ProfStart(PGROUP_T2); */
         l_data_read = 0;
-        if (! opj_tcd_t2_decode(p_tcd, p_src, &l_data_read, p_max_length, p_cstr_index))
+        if (! opj_tcd_t2_decode(p_tcd, p_src, &l_data_read, p_max_length, p_cstr_index, p_manager))
         {
                 return OPJ_FALSE;
         }
@@ -1328,7 +1320,7 @@
         /*----------------MCT-------------------*/
         /* FIXME _ProfStart(PGROUP_MCT); */
         if
-                (! opj_tcd_mct_decode(p_tcd))
+                (! opj_tcd_mct_decode(p_tcd, p_manager))
         {
                 return OPJ_FALSE;
         }
@@ -1462,7 +1454,7 @@
 
 
 
-void opj_tcd_free_tile(opj_tcd_t *p_tcd)
+static void opj_tcd_free_tile(opj_tcd_t *p_tcd)
 {
         OPJ_UINT32 compno, resno, bandno, precno;
         opj_tcd_tile_t *l_tile = 00;
@@ -1545,11 +1537,12 @@
 }
 
 
-OPJ_BOOL opj_tcd_t2_decode (opj_tcd_t *p_tcd,
+static OPJ_BOOL opj_tcd_t2_decode (opj_tcd_t *p_tcd,
                             OPJ_BYTE * p_src_data,
                             OPJ_UINT32 * p_data_read,
                             OPJ_UINT32 p_max_src_size,
-                            opj_codestream_index_t *p_cstr_index
+                            opj_codestream_index_t *p_cstr_index,
+                            opj_event_mgr_t *p_manager
                             )
 {
         opj_t2_t * l_t2;
@@ -1566,7 +1559,8 @@
                                         p_src_data,
                                         p_data_read,
                                         p_max_src_size,
-                                        p_cstr_index)) {
+                                        p_cstr_index,
+                                        p_manager)) {
                 opj_t2_destroy(l_t2);
                 return OPJ_FALSE;
         }
@@ -1577,7 +1571,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_tcd_t1_decode ( opj_tcd_t *p_tcd )
+static OPJ_BOOL opj_tcd_t1_decode ( opj_tcd_t *p_tcd )
 {
         OPJ_UINT32 compno;
         opj_t1_t * l_t1;
@@ -1607,7 +1601,7 @@
 }
 
 
-OPJ_BOOL opj_tcd_dwt_decode ( opj_tcd_t *p_tcd )
+static OPJ_BOOL opj_tcd_dwt_decode ( opj_tcd_t *p_tcd )
 {
         OPJ_UINT32 compno;
         opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles;
@@ -1647,7 +1641,7 @@
 
         return OPJ_TRUE;
 }
-OPJ_BOOL opj_tcd_mct_decode ( opj_tcd_t *p_tcd )
+static OPJ_BOOL opj_tcd_mct_decode ( opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager)
 {
         opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles;
         opj_tcp_t * l_tcp = p_tcd->tcp;
@@ -1665,7 +1659,7 @@
                 if ((l_tile->comps[0].x1 - l_tile->comps[0].x0) * (l_tile->comps[0].y1 - l_tile->comps[0].y0) < (OPJ_INT32)l_samples ||
                     (l_tile->comps[1].x1 - l_tile->comps[1].x0) * (l_tile->comps[1].y1 - l_tile->comps[1].y0) < (OPJ_INT32)l_samples ||
                     (l_tile->comps[2].x1 - l_tile->comps[2].x0) * (l_tile->comps[2].y1 - l_tile->comps[2].y0) < (OPJ_INT32)l_samples) {
-                        fprintf(stderr, "Tiles don't all have the same dimension. Skip the MCT step.\n");
+                        opj_event_msg(p_manager, EVT_ERROR, "Tiles don't all have the same dimension. Skip the MCT step.\n");
                         return OPJ_FALSE;
                 }
                 else if (l_tcp->mct == 2) {
@@ -1717,15 +1711,14 @@
                 }
         }
         else {
-                /* FIXME need to use opj_event_msg function */
-                fprintf(stderr,"Number of components (%d) is inconsistent with a MCT. Skip the MCT step.\n",l_tile->numcomps);
+                opj_event_msg(p_manager, EVT_ERROR, "Number of components (%d) is inconsistent with a MCT. Skip the MCT step.\n",l_tile->numcomps);
         }
 
         return OPJ_TRUE;
 }
 
 
-OPJ_BOOL opj_tcd_dc_level_shift_decode ( opj_tcd_t *p_tcd )
+static OPJ_BOOL opj_tcd_dc_level_shift_decode ( opj_tcd_t *p_tcd )
 {
         OPJ_UINT32 compno;
         opj_tcd_tilecomp_t * l_tile_comp = 00;
@@ -1775,7 +1768,7 @@
                         for (j=0;j<l_height;++j) {
                                 for (i = 0; i < l_width; ++i) {
                                         OPJ_FLOAT32 l_value = *((OPJ_FLOAT32 *) l_current_ptr);
-                                        *l_current_ptr = opj_int_clamp((OPJ_INT32)lrintf(l_value) + l_tccp->m_dc_level_shift, l_min, l_max); ;
+                                        *l_current_ptr = opj_int_clamp((OPJ_INT32)opj_lrintf(l_value) + l_tccp->m_dc_level_shift, l_min, l_max); ;
                                         ++l_current_ptr;
                                 }
                                 l_current_ptr += l_stride;
@@ -1795,7 +1788,7 @@
 /**
  * Deallocates the encoding data of the given precinct.
  */
-void opj_tcd_code_block_dec_deallocate (opj_tcd_precinct_t * p_precinct)
+static void opj_tcd_code_block_dec_deallocate (opj_tcd_precinct_t * p_precinct)
 {
         OPJ_UINT32 cblkno , l_nb_code_blocks;
 
@@ -1833,7 +1826,7 @@
 /**
  * Deallocates the encoding data of the given precinct.
  */
-void opj_tcd_code_block_enc_deallocate (opj_tcd_precinct_t * p_precinct)
+static void opj_tcd_code_block_enc_deallocate (opj_tcd_precinct_t * p_precinct)
 {       
         OPJ_UINT32 cblkno , l_nb_code_blocks;
 
@@ -1894,7 +1887,7 @@
         return l_data_size;
 }
                 
-OPJ_BOOL opj_tcd_dc_level_shift_encode ( opj_tcd_t *p_tcd )
+static OPJ_BOOL opj_tcd_dc_level_shift_encode ( opj_tcd_t *p_tcd )
 {
         OPJ_UINT32 compno;
         opj_tcd_tilecomp_t * l_tile_comp = 00;
@@ -1934,7 +1927,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_tcd_mct_encode ( opj_tcd_t *p_tcd )
+static OPJ_BOOL opj_tcd_mct_encode ( opj_tcd_t *p_tcd )
 {
         opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles;
         opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps;
@@ -1989,7 +1982,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_tcd_dwt_encode ( opj_tcd_t *p_tcd )
+static OPJ_BOOL opj_tcd_dwt_encode ( opj_tcd_t *p_tcd )
 {
         opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles;
         opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps;
@@ -2015,7 +2008,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_tcd_t1_encode ( opj_tcd_t *p_tcd )
+static OPJ_BOOL opj_tcd_t1_encode ( opj_tcd_t *p_tcd )
 {
         opj_t1_t * l_t1;
         const OPJ_FLOAT64 * l_mct_norms;
@@ -2052,7 +2045,7 @@
         return OPJ_TRUE;
 }
 
-OPJ_BOOL opj_tcd_t2_encode (opj_tcd_t *p_tcd,
+static OPJ_BOOL opj_tcd_t2_encode (opj_tcd_t *p_tcd,
                                                 OPJ_BYTE * p_dest_data,
                                                 OPJ_UINT32 * p_data_written,
                                                 OPJ_UINT32 p_max_dest_size,
@@ -2090,7 +2083,7 @@
 }
 
 
-OPJ_BOOL opj_tcd_rate_allocate_encode(  opj_tcd_t *p_tcd,
+static OPJ_BOOL opj_tcd_rate_allocate_encode(  opj_tcd_t *p_tcd,
                                                                             OPJ_BYTE * p_dest_data,
                                                                             OPJ_UINT32 p_max_dest_size,
                                                                             opj_codestream_info_t *p_cstr_info )
diff --git a/third_party/libopenjpeg20/tcd.h b/third_party/libopenjpeg20/tcd.h
index 9bef0fe..07f8379 100644
--- a/third_party/libopenjpeg20/tcd.h
+++ b/third_party/libopenjpeg20/tcd.h
@@ -262,10 +262,11 @@
  * @param	p_tcd		the tile decoder.
  * @param	p_tile_no	the index of the tile received in sequence. This not necessarily lead to the
  * tile at index p_tile_no.
+ * @param p_manager the event manager.
  *
  * @return	true if the remaining data is sufficient.
  */
-OPJ_BOOL opj_tcd_init_decode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no);
+OPJ_BOOL opj_tcd_init_decode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager);
 
 void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, OPJ_UINT32 final);
 
@@ -295,7 +296,7 @@
  * @param	p_data_written	pointer to an int that is incremented by the number of bytes really written on p_dest
  * @param	p_len			Maximum length of the destination buffer
  * @param	p_cstr_info		Codestream information structure
- * @return  true if the coding is successfull.
+ * @return  true if the coding is successful.
 */
 OPJ_BOOL opj_tcd_encode_tile(   opj_tcd_t *p_tcd,
 							    OPJ_UINT32 p_tile_no,
@@ -312,12 +313,14 @@
 @param len Length of source buffer
 @param tileno Number that identifies one of the tiles to be decoded
 @param cstr_info  FIXME DOC
+@param manager the event manager.
 */
 OPJ_BOOL opj_tcd_decode_tile(   opj_tcd_t *tcd,
 							    OPJ_BYTE *src,
 							    OPJ_UINT32 len,
 							    OPJ_UINT32 tileno,
-							    opj_codestream_index_t *cstr_info);
+							    opj_codestream_index_t *cstr_info,
+							    opj_event_mgr_t *manager);
 
 
 /**
@@ -337,11 +340,12 @@
  *
  * @param	p_tcd		TCD handle.
  * @param	p_tile_no	current tile index to encode.
+ * @param p_manager the event manager.
  *
  * @return true if the encoding values could be set (false otherwise).
 */
 OPJ_BOOL opj_tcd_init_encode_tile (	opj_tcd_t *p_tcd,
-								    OPJ_UINT32 p_tile_no );
+								    OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager );
 
 /**
  * Copies tile data from the given memory block onto the system.
diff --git a/third_party/libopenjpeg20/tgt.c b/third_party/libopenjpeg20/tgt.c
index 6143c08..5e34aa9 100644
--- a/third_party/libopenjpeg20/tgt.c
+++ b/third_party/libopenjpeg20/tgt.c
@@ -45,7 +45,7 @@
 ==========================================================
 */
 
-opj_tgt_tree_t *opj_tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv) {
+opj_tgt_tree_t *opj_tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv, opj_event_mgr_t *manager) {
         OPJ_INT32 nplh[32];
         OPJ_INT32 nplv[32];
         opj_tgt_node_t *node = 00;
@@ -59,7 +59,7 @@
 
         tree = (opj_tgt_tree_t *) opj_calloc(1,sizeof(opj_tgt_tree_t));
         if(!tree) {
-                fprintf(stderr, "ERROR in tgt_create while allocating tree\n");
+                opj_event_msg(manager, EVT_ERROR, "Not enough memory to create Tag-tree\n");
                 return 00;
         }
 
@@ -81,13 +81,13 @@
         /* ADD */
         if (tree->numnodes == 0) {
                 opj_free(tree);
-                fprintf(stderr, "WARNING in tgt_create tree->numnodes == 0, no tree created.\n");
+                opj_event_msg(manager, EVT_WARNING, "tgt_create tree->numnodes == 0, no tree created.\n");
                 return 00;
         }
 
         tree->nodes = (opj_tgt_node_t*) opj_calloc(tree->numnodes, sizeof(opj_tgt_node_t));
         if(!tree->nodes) {
-                fprintf(stderr, "ERROR in tgt_create while allocating node of the tree\n");
+                opj_event_msg(manager, EVT_ERROR, "Not enough memory to create Tag-tree nodes\n");
                 opj_free(tree);
                 return 00;
         }
@@ -130,7 +130,7 @@
  * @param       p_num_leafs_v           the height of the array of leafs of the tree
  * @return      a new tag-tree if successful, NULL otherwise
 */
-opj_tgt_tree_t *opj_tgt_init(opj_tgt_tree_t * p_tree,OPJ_UINT32 p_num_leafs_h, OPJ_UINT32 p_num_leafs_v)
+opj_tgt_tree_t *opj_tgt_init(opj_tgt_tree_t * p_tree,OPJ_UINT32 p_num_leafs_h, OPJ_UINT32 p_num_leafs_v, opj_event_mgr_t *p_manager)
 {
         OPJ_INT32 l_nplh[32];
         OPJ_INT32 l_nplv[32];
@@ -175,7 +175,7 @@
                 if (l_node_size > p_tree->nodes_size) {
                         opj_tgt_node_t* new_nodes = (opj_tgt_node_t*) opj_realloc(p_tree->nodes, l_node_size);
                         if (! new_nodes) {
-                                fprintf(stderr, "ERROR Not enough memory to reinitialize the tag tree\n");
+                                opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to reinitialize the tag tree\n");
                                 opj_tgt_destroy(p_tree);
                                 return 00;
                         }
diff --git a/third_party/libopenjpeg20/tgt.h b/third_party/libopenjpeg20/tgt.h
index 3d152f8..1022380 100644
--- a/third_party/libopenjpeg20/tgt.h
+++ b/third_party/libopenjpeg20/tgt.h
@@ -83,7 +83,7 @@
 @param numleafsv Height of the array of leafs of the tree
 @return Returns a new tag-tree if successful, returns NULL otherwise
 */
-opj_tgt_tree_t *opj_tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv);
+opj_tgt_tree_t *opj_tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv, opj_event_mgr_t *manager);
 
 /**
  * Reinitialises a tag-tree from an exixting one.
@@ -91,11 +91,12 @@
  * @param	p_tree				the tree to reinitialize.
  * @param	p_num_leafs_h		the width of the array of leafs of the tree
  * @param	p_num_leafs_v		the height of the array of leafs of the tree
+ * @param p_manager       the event manager
  * @return	a new tag-tree if successful, NULL otherwise
 */
 opj_tgt_tree_t *opj_tgt_init(opj_tgt_tree_t * p_tree, 
                              OPJ_UINT32  p_num_leafs_h, 
-                             OPJ_UINT32  p_num_leafs_v);
+                             OPJ_UINT32  p_num_leafs_v, opj_event_mgr_t *p_manager);
 /**
 Destroy a tag-tree, liberating memory
 @param tree Tag-tree to destroy