From c73e2713b5671464c941c827783345a30d95dbed Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Thu, 18 Nov 2010 23:53:34 +0100 Subject: [PATCH] Borrowed j2c bridge from Impru. THANKIES <3 --- indra/llimagej2coj/llimagej2coj.cpp | 77 +++++++++++++++++------------ indra/llimagej2coj/llimagej2coj.h | 3 ++ 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index a9dda75a8..fd923703d 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -99,6 +99,7 @@ void info_callback(const char* msg, void*) LLImageJ2COJ::LLImageJ2COJ() : LLImageJ2CImpl() { + mRawImagep=NULL; } @@ -112,10 +113,6 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod // // FIXME: Get the comment field out of the texture // - if (!base.getData()) return FALSE; - if (!base.getDataSize()) return FALSE; - if (!raw_image.getData()) return FALSE; - if (!raw_image.getDataSize()) return FALSE; LLTimer decode_timer; @@ -155,11 +152,13 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize()); - /* decode the stream and fill the image structure */ - if (!cio) return FALSE; - if (cio->bp == NULL) return FALSE; - if (!dinfo) return FALSE; - image = opj_decode(dinfo, cio); + /* decode the stream and fill the image structure, also fill in an additional + structure to get the decoding result. This structure is a bit unusual in that + it is not received through opj, but still has some dynamically allocated fields + that need to be cleared up at the end by calling a destroy function. */ + opj_codestream_info_t cinfo; + memset(&cinfo, 0, sizeof(opj_codestream_info_t)); + image = opj_decode_with_info(dinfo, cio, &cinfo); /* close the byte stream */ opj_cio_close(cio); @@ -173,19 +172,20 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod // The image decode failed if the return was NULL or the component // count was zero. The latter is just a sanity check before we // dereference the array. - if(!image) + if(!image) { - LL_DEBUGS("Openjpeg") << "ERROR -> decodeImpl: failed to decode image - no image" << LL_ENDL; - return TRUE; // done - } + LL_DEBUGS("Openjpeg") << "ERROR -> decodeImpl: failed to decode image - no image" << LL_ENDL; + return TRUE; // done + } - S32 img_components = image->numcomps; + S32 img_components = image->numcomps; - if( !img_components ) // < 1 ||img_components > 4 ) - { - LL_DEBUGS("Openjpeg") << "ERROR -> decodeImpl: failed to decode image wrong number of components: " << img_components << LL_ENDL; + if( !img_components ) // < 1 ||img_components > 4 ) + { + LL_DEBUGS("Openjpeg") << "ERROR -> decodeImpl: failed to decode image wrong number of components: " << img_components << LL_ENDL; if (image) { + opj_destroy_cstr_info(&cinfo); opj_image_destroy(image); } @@ -193,23 +193,40 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod } // sometimes we get bad data out of the cache - check to see if the decode succeeded - for (S32 i = 0; i < img_components; i++) + int decompdifference = 0; + if (cinfo.numdecompos) // sanity { - if (image->comps[i].factor != base.getRawDiscardLevel()) + for (int comp = 0; comp < image->numcomps; comp++) + { /* get maximum decomposition level difference, first field is from the COD header and the second + is what is actually met in the codestream, NB: if everything was ok, this calculation will + return what was set in the cp_reduce value! */ + decompdifference = llmax(decompdifference, cinfo.numdecompos[comp] - image->comps[comp].resno_decoded); + } + if (decompdifference < 0) // sanity { - // if we didn't get the discard level we're expecting, fail - if (image) //anyway somthing odd with the image, better check than crash - opj_image_destroy(image); - base.mDecoding = FALSE; - return TRUE; + decompdifference = 0; } } + + /* if OpenJPEG failed to decode all requested decomposition levels + the difference will be greater than this level */ + if (decompdifference > base.getRawDiscardLevel()) + { + llwarns << "not enough data for requested discard level, setting mDecoding to FALSE, difference: " << (decompdifference - base.getRawDiscardLevel()) << llendl; + opj_destroy_cstr_info(&cinfo); + opj_image_destroy(image); + base.mDecoding = FALSE; + return TRUE; + } + if(img_components <= first_channel) { + // sanity LL_DEBUGS("Openjpeg") << "trying to decode more channels than are present in image: numcomps: " << img_components << " first_channel: " << first_channel << LL_ENDL; if (image) { + opj_destroy_cstr_info(&cinfo); opj_image_destroy(image); } @@ -218,6 +235,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod // Copy image data into our raw image format (instead of the separate channel format + S32 channels = img_components - first_channel; if( channels > max_channel_count ) channels = max_channel_count; @@ -257,15 +275,17 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod else // Some rare OpenJPEG versions have this bug. { llwarns << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << llendl; + opj_destroy_cstr_info(&cinfo); opj_image_destroy(image); return TRUE; // done } } - /* free image data structure */ + /* free opj data structures */ if (image) { + opj_destroy_cstr_info(&cinfo); opj_image_destroy(image); } @@ -330,7 +350,7 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con OPJ_COLOR_SPACE color_space = CLRSPC_SRGB; opj_image_cmptparm_t cmptparm[MAX_COMPS]; opj_image_t * image = NULL; - S32 numcomps = llmin((S32)raw_image.getComponents(),(S32)MAX_COMPS); //Clamp avoid overrunning buffer -Shyotl + S32 numcomps = raw_image.getComponents(); S32 width = raw_image.getWidth(); S32 height = raw_image.getHeight(); @@ -421,8 +441,6 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base) // // FIXME: We get metadata by decoding the ENTIRE image. // - if (!base.getData()) return FALSE; - if (!base.getDataSize()) return FALSE; // Update the raw discard level base.updateRawDiscardLevel(); @@ -467,9 +485,6 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base) cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize()); /* decode the stream and fill the image structure */ - if (!cio) return FALSE; - if (cio->bp == NULL) return FALSE; - if (!dinfo) return FALSE; image = opj_decode(dinfo, cio); /* close the byte stream */ diff --git a/indra/llimagej2coj/llimagej2coj.h b/indra/llimagej2coj/llimagej2coj.h index 8255d5225..73cb074f1 100644 --- a/indra/llimagej2coj/llimagej2coj.h +++ b/indra/llimagej2coj/llimagej2coj.h @@ -51,6 +51,9 @@ protected: // Divide a by b to the power of 2 and round upwards. return (a + (1 << b) - 1) >> b; } + + // Temporary variables for in-progress decodes... + LLImageRaw *mRawImagep; }; #endif