diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2024-08-13 15:32:47 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2024-08-13 15:32:47 -0400 |
commit | 23f2631d598b6e07450a96ed1ec00670c8867cdd (patch) | |
tree | 20195c1688ad8cb7e8631c97fa5920624f10972c /indra/llimagej2coj/llimagej2coj.cpp | |
parent | 54334ff6e377e35c97df3a0fe2a859795ec07b21 (diff) | |
parent | 8ce3323269d95f54e2b768c4c5aa154d4afbbb6b (diff) |
Merge branch 'develop' into nat/edu-channel
Diffstat (limited to 'indra/llimagej2coj/llimagej2coj.cpp')
-rw-r--r-- | indra/llimagej2coj/llimagej2coj.cpp | 73 |
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(¶meters); 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, ¶meters, 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; |