diff --git a/poppler/JPEG2000Stream.cc b/poppler/JPEG2000Stream.cc index a6763e0..7daa23d 100644 --- a/poppler/JPEG2000Stream.cc +++ b/poppler/JPEG2000Stream.cc @@ -43,12 +43,13 @@ struct JPXStreamPrivate { int ncomps; GBool indexed; GBool inited; + int smaskInData; #ifdef USE_OPENJPEG1 opj_dinfo_t *dinfo; - void init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT format); + void init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT format, GBool indexed); #endif #ifdef USE_OPENJPEG2 - void init2(OPJ_CODEC_FORMAT format, unsigned char *data, int length); + void init2(OPJ_CODEC_FORMAT format, unsigned char *data, int length, GBool indexed); #endif }; @@ -159,9 +160,21 @@ void JPXStream::getImageParams(int *bitsPerComponent, StreamColorSpaceMode *csMo if (unlikely(priv->inited == gFalse)) { init(); } *bitsPerComponent = 8; - if (priv->image && priv->image->numcomps == 3) + int numComps = (priv->image) ? priv->image->numcomps : 1; + if (priv->image) { +#ifdef USE_OPENJPEG1 + if (priv->image->color_space == CLRSPC_SRGB && numComps == 4) { numComps = 3; } + else if (priv->image->color_space == CLRSPC_SYCC && numComps == 4) { numComps = 3; } +#else + if (priv->image->color_space == OPJ_CLRSPC_SRGB && numComps == 4) { numComps = 3; } + else if (priv->image->color_space == OPJ_CLRSPC_SYCC && numComps == 4) { numComps = 3; } +#endif + else if (numComps == 2) { numComps = 1; } + else if (numComps > 4) { numComps = 4; } + } + if (numComps == 3) *csMode = streamCSDeviceRGB; - else if (priv->image && priv->image->numcomps == 4) + else if (numComps == 4) *csMode = streamCSDeviceCMYK; else *csMode = streamCSDeviceGray; @@ -182,9 +195,10 @@ static void libopenjpeg_warning_callback(const char *msg, void * /*client_data*/ void JPXStream::init() { - Object oLen, cspace; + Object oLen, cspace, smaskInData; if (getDict()) getDict()->lookup("Length", &oLen); if (getDict()) getDict()->lookup("ColorSpace", &cspace); + if (getDict()) getDict()->lookup("SMaskInData", &smaskInData); int bufSize = BUFFER_INITIAL_SIZE; if (oLen.isInt()) bufSize = oLen.getInt(); @@ -198,14 +212,28 @@ void JPXStream::init() } cspace.free(); + priv->smaskInData = 0; + if (smaskInData.isInt()) priv->smaskInData = smaskInData.getInt(); + smaskInData.free(); + int length = 0; unsigned char *buf = str->toUnsignedChars(&length, bufSize); - priv->init2(buf, length, CODEC_JP2); + priv->init2(buf, length, CODEC_JP2, priv->indexed); free(buf); if (priv->image) { + int numComps = (priv->image) ? priv->image->numcomps : 1; + int alpha = 0; + if (priv->image) { + if (priv->image->color_space == CLRSPC_SRGB && numComps == 4) { numComps = 3; alpha = 1; } + else if (priv->image->color_space == CLRSPC_SYCC && numComps == 4) { numComps = 3; alpha = 1; } + else if (numComps == 2) { numComps = 1; alpha = 1; } + else if (numComps > 4) { numComps = 4; alpha = 1; } + else { alpha = 0; } + } priv->npixels = priv->image->comps[0].w * priv->image->comps[0].h; priv->ncomps = priv->image->numcomps; + if (alpha == 1 && priv->smaskInData == 0) priv->ncomps--; for (int component = 0; component < priv->ncomps; component++) { if (priv->image->comps[component].data == NULL) { close(); @@ -232,7 +260,7 @@ void JPXStream::init() priv->inited = gTrue; } -void JPXStreamPrivate::init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT format) +void JPXStreamPrivate::init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT format, GBool indexed) { opj_cio_t *cio = NULL; @@ -240,7 +268,8 @@ void JPXStreamPrivate::init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT fo opj_dparameters_t parameters; opj_set_default_decoder_parameters(¶meters); #ifdef WITH_OPENJPEG_IGNORE_PCLR_CMAP_CDEF_FLAG - parameters.flags = OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; + if (indexed) + parameters.flags = OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; #endif /* Configure the event manager to receive errors and warnings */ @@ -274,10 +303,10 @@ void JPXStreamPrivate::init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT fo error: if (format == CODEC_JP2) { error(errSyntaxWarning, -1, "Did not succeed opening JPX Stream as JP2, trying as J2K."); - init2(buf, bufLen, CODEC_J2K); + init2(buf, bufLen, CODEC_J2K, indexed); } else if (format == CODEC_J2K) { error(errSyntaxWarning, -1, "Did not succeed opening JPX Stream as J2K, trying as JPT."); - init2(buf, bufLen, CODEC_JPT); + init2(buf, bufLen, CODEC_JPT, indexed); } else { error(errSyntaxError, -1, "Did not succeed opening JPX Stream."); } @@ -333,9 +362,10 @@ static OPJ_BOOL jpxSeek_callback(OPJ_OFF_T seek_pos, void * p_user_data) void JPXStream::init() { - Object oLen, cspace; + Object oLen, cspace, smaskInData; if (getDict()) getDict()->lookup("Length", &oLen); if (getDict()) getDict()->lookup("ColorSpace", &cspace); + if (getDict()) getDict()->lookup("SMaskInData", &smaskInData); int bufSize = BUFFER_INITIAL_SIZE; if (oLen.isInt()) bufSize = oLen.getInt(); @@ -349,14 +379,28 @@ void JPXStream::init() } cspace.free(); + priv->smaskInData = 0; + if (smaskInData.isInt()) priv->smaskInData = smaskInData.getInt(); + smaskInData.free(); + int length = 0; unsigned char *buf = str->toUnsignedChars(&length, bufSize); - priv->init2(OPJ_CODEC_JP2, buf, length); + priv->init2(OPJ_CODEC_JP2, buf, length, priv->indexed); gfree(buf); if (priv->image) { + int numComps = (priv->image) ? priv->image->numcomps : 1; + int alpha = 0; + if (priv->image) { + if (priv->image->color_space == OPJ_CLRSPC_SRGB && numComps == 4) { numComps = 3; alpha = 1; } + else if (priv->image->color_space == OPJ_CLRSPC_SYCC && numComps == 4) { numComps = 3; alpha = 1; } + else if (numComps == 2) { numComps = 1; alpha = 1; } + else if (numComps > 4) { numComps = 4; alpha = 1; } + else { alpha = 0; } + } priv->npixels = priv->image->comps[0].w * priv->image->comps[0].h; priv->ncomps = priv->image->numcomps; + if (alpha == 1 && priv->smaskInData == 0) priv->ncomps--; for (int component = 0; component < priv->ncomps; component++) { if (priv->image->comps[component].data == NULL) { close(); @@ -384,7 +428,7 @@ void JPXStream::init() priv->inited = gTrue; } -void JPXStreamPrivate::init2(OPJ_CODEC_FORMAT format, unsigned char *buf, int length) +void JPXStreamPrivate::init2(OPJ_CODEC_FORMAT format, unsigned char *buf, int length, GBool indexed) { JPXData jpxData; @@ -413,7 +457,8 @@ void JPXStreamPrivate::init2(OPJ_CODEC_FORMAT format, unsigned char *buf, int le /* Use default decompression parameters */ opj_dparameters_t parameters; opj_set_default_decoder_parameters(¶meters); - parameters.flags |= OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; + if (indexed) + parameters.flags |= OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; /* Get the decoder handle of the format */ decoder = opj_create_decompress(format); @@ -462,10 +507,10 @@ error: opj_destroy_codec(decoder); if (format == OPJ_CODEC_JP2) { error(errSyntaxWarning, -1, "Did no succeed opening JPX Stream as JP2, trying as J2K."); - init2(OPJ_CODEC_J2K, buf, length); + init2(OPJ_CODEC_J2K, buf, length, indexed); } else if (format == OPJ_CODEC_J2K) { error(errSyntaxWarning, -1, "Did no succeed opening JPX Stream as J2K, trying as JPT."); - init2(OPJ_CODEC_JPT, buf, length); + init2(OPJ_CODEC_JPT, buf, length, indexed); } else { error(errSyntaxError, -1, "Did no succeed opening JPX Stream."); }