summaryrefslogtreecommitdiff
path: root/indra/llimage/llimagej2c.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llimage/llimagej2c.cpp')
-rw-r--r--indra/llimage/llimagej2c.cpp54
1 files changed, 28 insertions, 26 deletions
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 5a941dc958..512b370bae 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -265,40 +265,42 @@ S32 LLImageJ2C::calcHeaderSizeJ2C()
return FIRST_PACKET_SIZE; // Hack. just needs to be >= actual header size...
}
-//static
-S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate)
+// Lean pyramid-walk byte estimator suited to packet-by-packet decoders (KDU).
+// Starts at one max-block, walks resolutions by doubling area, sums each
+// layer's compressed-bytes contribution.
+// Reference: https://wiki.lindenlab.com/wiki/THX1138_KDU_Improvements#Byte_Range_Study
+S32 LLImageJ2CImpl::estimateDataSize(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate) const
{
- // Note: This provides an estimation for the first to last quality layer of a given discard level
- // This is however an efficient approximation, as the true discard level boundary would be
- // in general too big for fast fetching.
- // For details about the equation used here, see https://wiki.lindenlab.com/wiki/THX1138_KDU_Improvements#Byte_Range_Study
-
- // Estimate the number of layers. This is consistent with what's done for j2c encoding in LLImageJ2CKDU::encodeImpl().
- constexpr S32 precision = 8; // assumed bitrate per component channel, might change in future for HDR support
- constexpr S32 max_components = 4; // assumed the file has four components; three color and alpha
- // Use MAX_IMAGE_SIZE_DEFAULT (currently 2048) if either dimension is unknown (zero)
+ constexpr S32 precision = 8;
+ constexpr S32 max_components = 4;
S32 width = (w > 0) ? w : 2048;
S32 height = (h > 0) ? h : 2048;
- S32 max_dimension = llmax(width, height); // Find largest dimension
- S32 block_area = MAX_BLOCK_SIZE * MAX_BLOCK_SIZE; // Calculated initial block area from established max block size (currently 64)
- S32 max_layers = (S32)llmax(llround(log2f((float)max_dimension) - log2f((float)MAX_BLOCK_SIZE)), 4); // Find number of powers of two between extents and block size to a minimum of 4
- block_area *= llmax(max_layers, 1); // Adjust initial block area by max number of layers
- S32 totalbytes = (S32) (MIN_LAYER_SIZE * max_components * precision); // Start estimation with a minimum reasonable size
- S32 block_layers = 0;
- while (block_layers <= max_layers) // Walk the layers
+ const S32 surface = width * height;
+ S32 nb_layers = 1;
+ S32 s = MAX_BLOCK_SIZE * MAX_BLOCK_SIZE;
+ S32 totalbytes = (S32)(s * max_components * precision * rate);
+ while (surface > s)
{
- if (block_layers <= (5 - discard_level)) // Walk backwards from discard 5 to required discard layer.
- totalbytes += (S32) (block_area * max_components * precision * rate); // Add each block layer reduced by assumed compression rate
- block_layers++; // Move to next layer
- block_area *= 4; // Increase block area by power of four
+ if (nb_layers <= (5 - discard_level))
+ totalbytes += (S32)(s * max_components * precision * rate);
+ nb_layers++;
+ s *= 4;
}
-
- totalbytes /= 8; // to bytes
- totalbytes += calcHeaderSizeJ2C(); // header
-
+ totalbytes /= 8;
+ totalbytes += LLImageJ2C::calcHeaderSizeJ2C();
return totalbytes;
}
+//static
+S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate)
+{
+ // Dispatch to the linked impl so OpenJPEG (block-aligned, needs
+ // over-allocation) and KDU (packet-aligned, lean) each return what
+ // their decoder actually needs.
+ static std::unique_ptr<LLImageJ2CImpl> s_estimator(fallbackCreateLLImageJ2CImpl());
+ return s_estimator->estimateDataSize(w, h, comp, discard_level, rate);
+}
+
S32 LLImageJ2C::calcHeaderSize()
{
return calcHeaderSizeJ2C();