summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llimage/llimagej2c.h10
-rw-r--r--indra/llimagej2coj/llimagej2coj.cpp78
-rw-r--r--indra/llimagej2coj/llimagej2coj.h5
3 files changed, 64 insertions, 29 deletions
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(&parameters);
+ // 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;