Re: [OpenJPEG] Re: opj_encode with tcp broken

Skip to first unread message


Aug 14, 2009, 5:14:57 PM8/14/09
to OpenJPEG
Trying to continue this thread,

but google will not let me. so heres a new one

I spent some time looking at this today, and got the following results
(v1.3 this is on)

Windows 32 bit does not have this problem
Linux 32 bit compiled with -O3 does have this problem
Linux 32 bit compiled with -O0 does not have this problem
Linux 64 bit has this problem

So its very arch/compiler specific, looking at the resulting files
between linux 32 bit -O3 and Linux 64 bit (by converting a 4 channel
tga to j2k and back) the results for the j2k stage were identical for
both fail situations. SO i brute forced it looking for differences in
the code at run time and hit a bunch of issues that all stemmed back
to mct.c, and in particular the arrays of size [3] being accessed by
mct_getnorm_real() and mct_getnorm()

This in turn is accessed by t1_getwmsedec(), now t1_getwmsedec() knows
which component we are on, so for a 4 channel image its calling the
mct_getnorm() with ordinals of 0,1,2,3 so its an array overrun. Now i
guess that windows and linux 32bit no opt are working because that
array overrun hits a non-zero memory location, on linux 64 bit and
optimised that location appears to be 0 which then cascades back
through the code multipling things by 0 and screwing the encode up.

So i quickly did this to test

--- openjpeg-1.3+dfsg.orig/libopenjpeg/mct.c
+++ openjpeg-1.3+dfsg/libopenjpeg/mct.c
@@ -34,12 +34,12 @@
/* <summary> */
/* This table contains the norms of the basis function of the
reversible MCT. */
/* </summary> */
-static const double mct_norms[3] = { 1.732, .8292, .8292 };
+static const double mct_norms[5] = { 1.732, .8292, .8292, .8292 , .
8292 };

/* <summary> */
/* This table contains the norms of the basis function of the
irreversible MCT. */
/* </summary> */
-static const double mct_norms_real[3] = { 1.732, 1.805, 1.573 };
+static const double mct_norms_real[5] = { 1.732, 1.805, 1.573 ,
1.573, 1.573};

/* <summary> */
/* Foward reversible MCT. */

and it works, i can encode and decode 4 channel images with out ending
up with a 50% alpha applied to the whole image.

Now the questions are, what is the *correct* implementation of a

Should the norms be defined for channels >0,1,2 should mct_getnorm_real
() just limit to a maximum ordinal of 2, or should t1_getwmsedec() or
further up the call stack know better and not actually expose
t1_getwmsedec() to this situation in the first place?




Aug 15, 2009, 7:23:04 PM8/15/09
to OpenJPEG

Ok so to save me looking like a _complete_ fool i did some further
research, and now i understand what the MCT is doing...

Turns out the MCT transform is only valid for 3 component images.
Openjpeg 1.3 blindly ignores this, v2.0 in the codecs check the number
of channels and use this to disable the MCT (although looks like the
lib itself supports more complex things via custom tables). So the fix
for 1.3 is to check the number of components and if !=3 i believe all
you need to do is to return 1.0 for w1 in t1_getwmsedec()


Antonin Descampe

Nov 6, 2009, 7:53:50 AM11/6/09

Hi Robin,

You're completely right. The MCT is only valid for 3 components
images. And even more, the transformation has been designed for RGB
components. There was a unstatisfying test in t1_getwmsedec as the
number of components was only checked in order to know if it was
greater than 1.

The mct_getnorm should actually be called only if the MCT has been
applied. I changed this with a double check : (i) tcp->mct should be
set to 1, (ii) the number of components should be exactly 3.

Could you check if it correctly solve the issue on your 4-components
images ?




Dec 24, 2009, 3:32:20 PM12/24/09
to OpenJPEG
I can confirm that 4-component images are working correctly
with the new check in 1_getwmsedec.

However, I was wondering if it would be possible to use MCT
(it's some sort of RGB -> YCC conversion right?)
on images with more than 3 components: for RGB components use MCT
and leave additional components alone?

Something like:
w1 = (mct && numcomps >=3 && compno < 3) ? mct_getnorm_real(compno) :
Or is it more complicated?


On Nov 6, 1:53 pm, Antonin Descampe <>

Reply all
Reply to author
0 new messages