diff options
| -rw-r--r-- | doc/contributions.txt | 3 | ||||
| -rw-r--r-- | indra/llimage/llimagej2c.h | 10 | ||||
| -rw-r--r-- | indra/llimagej2coj/llimagej2coj.cpp | 78 | ||||
| -rw-r--r-- | indra/llimagej2coj/llimagej2coj.h | 5 | 
4 files changed, 66 insertions, 30 deletions
| diff --git a/doc/contributions.txt b/doc/contributions.txt index 59663640e3..494e3fe1d7 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -9,13 +9,14 @@ blino Nakamura - VWR-17  Drewan Keats - VWR-28  Dylan Haskell - VWR-72  Eddy Stryker - VWR-15, VWR-23 +Hiro Sommambulist - VWR-66  Joghert LeSabre - VWR-64  Kage Pixel - VWR-11  Kunnis Basiat - VWR-82  Paul Churchill - VWR-20  Paula Innis - VWR-30  Peekay Semyorka - VWR-7, VWR-19, VWR-49 -SpacedOut Frye - VWR-57 +SpacedOut Frye - VWR-57, VWR-123  Strife Onizuka - VWR-74, VWR-85, SVC-9  Zipherius Turas - VWR-76, VWR-77 diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h index 1181ae2bb8..8a832677a3 100644 --- a/indra/llimage/llimagej2c.h +++ b/indra/llimage/llimagej2c.h @@ -68,7 +68,17 @@ class LLImageJ2CImpl  public:  	virtual ~LLImageJ2CImpl();  protected: +	// Find out the image size and number of channels. +	// Return value: +	// true: image size and number of channels was determined +	// false: error on decode  	virtual BOOL getMetadata(LLImageJ2C &base) = 0; +	// Decode the raw image optionally aborting (to continue later) after +	// decode_time seconds.  Decode at most max_channel_count and start +	// decoding channel first_channel. +	// Return value: +	// true: decoding complete (even if it failed) +	// false: time expired while decoding  	virtual BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) = 0;  	virtual BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0) = 0; diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index a6c7c623f3..52549e5d11 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -9,6 +9,8 @@  #include "linden_common.h"  #include "llimagej2coj.h" +// this is defined so that we get static linking. +#define OPJ_STATIC  #include "openjpeg/openjpeg.h"  #include "lltimer.h" @@ -103,46 +105,61 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod  	/* decode the stream and fill the image structure */  	image = opj_decode(dinfo, cio); -	if(!image) -	{ -		fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); -		opj_destroy_decompress(dinfo); -		opj_cio_close(cio); -		return 1; -	}  	/* close the byte stream */  	opj_cio_close(cio); -  	/* free remaining structures */ -	if(dinfo) { +	if(dinfo) +	{  		opj_destroy_decompress(dinfo);  	} +	// 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 || !image->numcomps) +	{ +		fprintf(stderr, "ERROR -> decodeImpl: failed to decode image!\n"); +		if (image) +			opj_image_destroy(image); + +		return TRUE; // done +	} +  	// Copy image data into our raw image format (instead of the separate channel format -	S32 width = 0; -	S32 height = 0;  	S32 img_components = image->numcomps;  	S32 channels = img_components - first_channel;  	if( channels > max_channel_count ) -	{  		channels = max_channel_count; -	} -	width = image->x1 - image->x0; -	height = image->y1 - image->y0; + +	// Component buffers are allocated in an image width by height buffer. +	// The image placed in that buffer is ceil(width/2^factor) by +	// ceil(height/2^factor) and if the factor isn't zero it will be at the +	// top left of the buffer with black filled in the rest of the pixels. +	// It is integer math so the formula is written in ceildivpo2. +	// (Assuming all the components have the same width, height and +	// factor.) +	S32 comp_width = image->comps[0].w; +	S32 f=image->comps[0].factor; +	S32 width = ceildivpow2(image->x1 - image->x0, f); +	S32 height = ceildivpow2(image->y1 - image->y0, f);  	raw_image.resize(width, height, channels);  	U8 *rawp = raw_image.getData(); -	for (S32 comp = first_channel; comp < first_channel + channels; comp++) +	// first_channel is what channel to start copying from +	// dest is what channel to copy to.  first_channel comes from the +	// argument, dest always starts writing at channel zero. +	for (S32 comp = first_channel, dest=0; comp < first_channel + channels; +		comp++, dest++)  	{ -		S32 offset = comp; +		S32 offset = dest;  		for (S32 y = (height - 1); y >= 0; y--)  		{  			for (S32 x = 0; x < width; x++)  			{ -				rawp[offset] = image->comps[comp].data[y*width + x]; +				rawp[offset] = image->comps[comp].data[y*comp_width + x];  				offset += channels;  			}  		} @@ -151,7 +168,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod  	/* free image data structure */  	opj_image_destroy(image); -	return TRUE; +	return TRUE; // done  } @@ -304,6 +321,9 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)  	/* set decoding parameters to default values */  	opj_set_default_decoder_parameters(¶meters); +	// Only decode what's required to get the size data. +	parameters.cp_limit_decoding=LIMIT_TO_MAIN_HEADER; +  	//parameters.cp_reduce = mRawDiscardLevel;  	/* decode the code-stream */ @@ -325,23 +345,22 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)  	/* decode the stream and fill the image structure */  	image = opj_decode(dinfo, cio); -	if(!image) -	{ -		fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); -		opj_destroy_decompress(dinfo); -		opj_cio_close(cio); -		return 1; -	}  	/* close the byte stream */  	opj_cio_close(cio); -  	/* free remaining structures */ -	if(dinfo) { +	if(dinfo) +	{  		opj_destroy_decompress(dinfo);  	} +	if(!image) +	{ +		fprintf(stderr, "ERROR -> getMetadata: failed to decode image!\n"); +		return FALSE; +	} +  	// Copy image data into our raw image format (instead of the separate channel format  	S32 width = 0;  	S32 height = 0; @@ -352,5 +371,6 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)  	base.setSize(width, height, img_components);  	/* free image data structure */ -	opj_image_destroy(image);	return TRUE; +	opj_image_destroy(image); +	return TRUE;  } diff --git a/indra/llimagej2coj/llimagej2coj.h b/indra/llimagej2coj/llimagej2coj.h index 9391ab4f70..5c90144469 100644 --- a/indra/llimagej2coj/llimagej2coj.h +++ b/indra/llimagej2coj/llimagej2coj.h @@ -21,6 +21,11 @@ protected:  	/*virtual*/ BOOL getMetadata(LLImageJ2C &base);  	/*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count);  	/*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0); +	int ceildivpow2(int a, int b) +	{ +		// 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; | 
