summaryrefslogtreecommitdiff
path: root/indra/llimagej2coj/llimagej2coj.cpp
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2024-08-13 15:32:47 -0400
committerNat Goodspeed <nat@lindenlab.com>2024-08-13 15:32:47 -0400
commit23f2631d598b6e07450a96ed1ec00670c8867cdd (patch)
tree20195c1688ad8cb7e8631c97fa5920624f10972c /indra/llimagej2coj/llimagej2coj.cpp
parent54334ff6e377e35c97df3a0fe2a859795ec07b21 (diff)
parent8ce3323269d95f54e2b768c4c5aa154d4afbbb6b (diff)
Merge branch 'develop' into nat/edu-channel
Diffstat (limited to 'indra/llimagej2coj/llimagej2coj.cpp')
-rw-r--r--indra/llimagej2coj/llimagej2coj.cpp73
1 files changed, 61 insertions, 12 deletions
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index f5f151e27b..f4bcb97a5d 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -172,7 +172,7 @@ static OPJ_OFF_T opj_skip(OPJ_OFF_T bytes, void* user_data)
JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
jpeg_codec->offset += bytes;
- if (jpeg_codec->offset > jpeg_codec->size)
+ if (jpeg_codec->offset > (OPJ_OFF_T)jpeg_codec->size)
{
jpeg_codec->offset = jpeg_codec->size;
// Indicate end of stream
@@ -431,23 +431,20 @@ public:
opj_set_default_encoder_parameters(&parameters);
parameters.cod_format = OPJ_CODEC_J2K;
parameters.cp_disto_alloc = 1;
- parameters.max_cs_size = (1 << 15);
if (reversible)
{
+ parameters.max_cs_size = 0; // do not limit size for reversible compression
+ parameters.irreversible = 0; // should be the default, but, just in case
parameters.tcp_numlayers = 1;
- parameters.tcp_rates[0] = 1.0f;
+ /* documentation seems to be wrong, should be 0.0f for lossless, not 1.0f
+ see https://github.com/uclouvain/openjpeg/blob/39e8c50a2f9bdcf36810ee3d41bcbf1cc78968ae/src/lib/openjp2/j2k.c#L7755
+ */
+ parameters.tcp_rates[0] = 0.0f;
}
else
{
- parameters.tcp_numlayers = 5;
- parameters.tcp_rates[0] = 1920.0f;
- parameters.tcp_rates[1] = 960.0f;
- parameters.tcp_rates[2] = 480.0f;
- parameters.tcp_rates[3] = 120.0f;
- parameters.tcp_rates[4] = 30.0f;
parameters.irreversible = 1;
- parameters.tcp_mct = 1;
}
if (comment_text)
@@ -489,6 +486,9 @@ public:
bool encode(const LLImageRaw& rawImageIn, LLImageJ2C &compressedImageOut)
{
+ LLImageDataSharedLock lockIn(&rawImageIn);
+ LLImageDataLock lockOut(&compressedImageOut);
+
setImage(rawImageIn);
encoder = opj_create_compress(OPJ_CODEC_J2K);
@@ -498,6 +498,50 @@ public:
parameters.prog_order = OPJ_RLCP;
parameters.cp_disto_alloc = 1;
+ // if not lossless compression, computes tcp_numlayers and max_cs_size depending on the image dimensions
+ if( parameters.irreversible ) {
+
+ // computes a number of layers
+ U32 surface = rawImageIn.getWidth() * rawImageIn.getHeight();
+ U32 nb_layers = 1;
+ U32 s = 64*64;
+ while (surface > s)
+ {
+ nb_layers++;
+ s *= 4;
+ }
+ nb_layers = llclamp(nb_layers, 1, 6);
+
+ parameters.tcp_numlayers = nb_layers;
+ parameters.tcp_rates[nb_layers - 1] = (U32)(1.f / DEFAULT_COMPRESSION_RATE); // 1:8 by default
+
+ // for each subsequent layer, computes its rate and adds surface * numcomps * 1/rate to the max_cs_size
+ U32 max_cs_size = (U32)(surface * image->numcomps * DEFAULT_COMPRESSION_RATE);
+ U32 multiplier;
+ for (int i = nb_layers - 2; i >= 0; i--)
+ {
+ if( i == nb_layers - 2 )
+ {
+ multiplier = 15;
+ }
+ else if( i == nb_layers - 3 )
+ {
+ multiplier = 4;
+ }
+ else
+ {
+ multiplier = 2;
+ }
+ parameters.tcp_rates[i] = parameters.tcp_rates[i + 1] * multiplier;
+ max_cs_size += (U32)(surface * image->numcomps * (1 / parameters.tcp_rates[i]));
+ }
+
+ //ensure that we have at least a minimal size
+ max_cs_size = llmax(max_cs_size, (U32)FIRST_PACKET_SIZE);
+
+ parameters.max_cs_size = max_cs_size;
+ }
+
if (!opj_setup_encoder(encoder, &parameters, image))
{
return false;
@@ -554,7 +598,7 @@ public:
{
// "append" (set) the data we "streamed" (memcopied) for writing to the formatted image
// with side-effect of setting the actually encoded size to same
- compressedImageOut.allocateData(offset);
+ compressedImageOut.allocateData((S32)offset);
memcpy(compressedImageOut.getData(), buffer, offset);
compressedImageOut.updateData(); // update width, height etc from header
}
@@ -733,6 +777,9 @@ bool LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int block
bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
{
+ LLImageDataLock lockIn(&base);
+ LLImageDataLock lockOut(&raw_image);
+
JPEG2KDecode decoder(0);
U32 image_channels = 0;
@@ -787,7 +834,7 @@ bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
S32 offset = dest;
for (S32 y = (height - 1); y >= 0; y--)
{
- for (S32 x = 0; x < width; x++)
+ for (U32 x = 0; x < width; x++)
{
rawp[offset] = image->comps[comp].data[y*comp_width + x];
offset += channels;
@@ -820,6 +867,8 @@ bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con
bool LLImageJ2COJ::getMetadata(LLImageJ2C &base)
{
+ LLImageDataLock lock(&base);
+
JPEG2KDecode decode(0);
S32 width = 0;