Export to GitHub

openjpeg - issue #426

issue414 revisited


Posted on Nov 9, 2014 by Grumpy Elephant

The specification ISO/IEC 15444-1:2002 (E) says

and in Table I.16 (page 143):

typ[i] == 0 : Colour typ[i] == 1 : Opacity typ[i] == 2 : Premultiplied opacity typ[i] == 3 ... 65534: Reserved for ISO use typ[i] == 65535 : The type of this channel is not specified

and in Table I.17 (page 143):

asoc[i] == 0 : This channel is associated as the image as a whole asoc[i] == 1 .. 65534: This channel is associated with a particular colour as indicated by this value. asoc[i] == 65535 : This channel is not associated with any particular colour.

"There shall not be more than one channel in a JP2 file with a the same Typ[i] and Asoc[i] value pair, with the exception of Typ[i] and Asoc[i] values of 2^(16)­ 1 (not specified)."(page 144)

NOTE: "2^(16)­ 1" is 65535.

This means:

  • typ[i] == 65535 and asoc[i] == 65535 must be skipped.

  • image->comps[cn].alpha = (info[i].typ == 1);

File '5C-cdef.jp2' has the following values:

n(6)
CDEF[0]cn(4) typ(0) asoc(1)
CDEF[1]cn(2) typ(0) asoc(2)
CDEF[2]cn(3) typ(0) asoc(3)
CDEF[3]cn(0) typ(1) asoc(1)
CDEF[4]cn(0) typ(1) asoc(2)
CDEF[5]cn(1) typ(1) asoc(3)

numcomps(5)
IMAGE[0]w(128) w(128) alpha(0)
IMAGE[1]w(128) w(128) alpha(0)
IMAGE[2]w(128) w(128) alpha(0)
IMAGE[3]w(128) w(128) alpha(1)
IMAGE[4]w(128) w(128) alpha(1)

But '18_1805_a4_2.jp2' of issue327 has the following values:

n(5)
CDEF[0]cn(0) typ(0) asoc(1)
CDEF[1]cn(1) typ(0) asoc(2)
CDEF[2]cn(2) typ(0) asoc(3)
CDEF[3]cn(3) typ(1) asoc(0)
CDEF[4]cn(4) typ(65535) asoc(5)

numcomps(5)
IMAGE[0]w(300) w(400) alpha(0)
IMAGE[1]w(300) w(400) alpha(0)
IMAGE[2]w(300) w(400) alpha(0)
IMAGE[3]w(300) w(400) alpha(1)
IMAGE[4]w(300) w(400) alpha(65535)

winfried

Comment #1

Posted on Nov 14, 2014 by Quick Lion

Winfried,

The resulting op_image_t is "wrong"/misleading in both cases.

5C-cdef.jp2 has per channel alpha ( 1 alpha channel for color 1 & 2 + 1 alpha channel for color 3). This information is lost in opj_image_t. The goal of issue 414 was to get at least color channels in the proper order. There's no way to get the information missing back. At least with image from issue 327, one can infer that alpha value of 65535 is an auxiliary channel that can be dismissed (or kept by specific applications).

What you're asking, if I understand correctly, is to get alpha = 0 for type 65535 / asoc 65535 ?

Comment #2

Posted on Nov 15, 2014 by Grumpy Elephant

Here is my proposal:

void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color) { opj_jp2_cdef_info_t *info; OPJ_UINT16 i, j, n, cn, asoc, acn, last, typ;

info = color->jp2_cdef->info;
n = color->jp2_cdef->n;

for(i = 0; i < n; ++i)

{ if(info[i].asoc != 65535 && info[i].typ != 65535) continue;

opj_free(image->comps[i].data);
image->comps[i].data = NULL;

last = n - 1;

for(j = i; j < last; ++j)

{ image->comps[j] = image->comps[j+1]; info[j] = info[j+1]; } --n; --color->jp2_cdef->n; --image->numcomps; }

for(i = 0; i < n; ++i)

{ /* WATCH: acn = asoc - 1 ! */ asoc = info[i].asoc; typ = info[i].typ;

image->comps[i].alpha = (typ == 1);

if(typ == 1) continue;
if(asoc == 0) continue;

cn = info[i].cn;
acn = (OPJ_UINT16)(asoc - 1);

if( cn >= image->numcomps || acn >= image->numcomps )

{ fprintf(stderr, "\tINFO[%d]cn=%d, acn=%d, numcomps=%d: SKIP.\n", i,cn, acn, image->numcomps); continue; }

if(cn != acn && typ == 0)

{ opj_image_comp_t saved;

memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t));
memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t));
memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t));

info[i].asoc = (OPJ_UINT16)(cn + 1);
info[acn].asoc = (OPJ_UINT16)(info[acn].cn + 1);

} } //MARK1 if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info);

opj_free(color->jp2_cdef); color->jp2_cdef = NULL;

}/* jp2_apply_cdef() */

In the line marked with '//MARK1' one could add e.g.: for(i = 4; i < n; ++i) { opj_free(image->comps[i].data); image->comps[i].data = NULL;

last = n - 1;

for(j = i; j < last; ++j)

{ image->comps[j] = image->comps[j+1]; info[j] = info[j+1]; } --n; --color->jp2_cdef->n; --image->numcomps; }

So the resulting 'image->numcomps' can never be larger than 4. Otherwise the code for applications using ALPHA (e.g. 'imagetopng()') must be changed, e.g.

numcomps = image->numcomps; if(numcomps > 4) numcomps = 4;

winfried

Comment #3

Posted on Nov 18, 2014 by Grumpy Elephant

Here is the patch for changing the numcomps value in the binaries.

winfried

Attachments

Status: Accepted

Labels:
Type-Defect Priority-Medium