32
32
#include " event.h"
33
33
#include " cio.h"
34
34
35
- #define MAX_ENCODED_DISCARD_LEVELS 5
36
-
37
35
// Factory function: see declaration in llimagej2c.cpp
38
36
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl ()
39
37
{
@@ -132,73 +130,96 @@ static void opj_error(const char* msg, void* user_data)
132
130
133
131
static OPJ_SIZE_T opj_read (void * buffer, OPJ_SIZE_T bytes, void * user_data)
134
132
{
135
- llassert (user_data);
133
+ llassert (user_data && buffer);
134
+
136
135
JPEG2KBase* jpeg_codec = static_cast <JPEG2KBase*>(user_data);
137
- OPJ_SIZE_T remainder = (jpeg_codec-> size - jpeg_codec-> offset );
138
- if (remainder <= 0 )
136
+
137
+ if (jpeg_codec-> offset < 0 || static_cast <OPJ_SIZE_T>(jpeg_codec-> offset ) >= jpeg_codec-> size )
139
138
{
140
139
jpeg_codec->offset = jpeg_codec->size ;
141
- // Indicate end of stream (hacky?)
142
- return (OPJ_OFF_T)-1 ;
140
+ return static_cast <OPJ_SIZE_T>(-1 ); // Indicate EOF
143
141
}
144
- OPJ_SIZE_T to_read = llclamp (U32 (bytes), U32 (0 ), U32 (remainder ));
142
+
143
+ OPJ_SIZE_T remainder = jpeg_codec->size - static_cast <OPJ_SIZE_T>(jpeg_codec->offset );
144
+ OPJ_SIZE_T to_read = (bytes < remainder ) ? bytes : remainder ;
145
+
145
146
memcpy (buffer, jpeg_codec->buffer + jpeg_codec->offset , to_read);
146
147
jpeg_codec->offset += to_read;
148
+
147
149
return to_read;
148
150
}
149
151
150
152
static OPJ_SIZE_T opj_write (void * buffer, OPJ_SIZE_T bytes, void * user_data)
151
153
{
152
- llassert (user_data);
154
+ llassert (user_data && buffer);
155
+
153
156
JPEG2KBase* jpeg_codec = static_cast <JPEG2KBase*>(user_data);
154
- OPJ_SIZE_T remainder = jpeg_codec->size - jpeg_codec->offset ;
155
- if (remainder < bytes)
157
+ OPJ_OFF_T required_offset = jpeg_codec->offset + static_cast <OPJ_OFF_T>(bytes);
158
+
159
+ // Overflow check
160
+ if (required_offset < jpeg_codec->offset )
161
+ return 0 ; // Overflow detected
162
+
163
+ // Resize if needed (exponential growth)
164
+ if (required_offset > static_cast <OPJ_OFF_T>(jpeg_codec->size ))
156
165
{
157
- OPJ_SIZE_T new_size = jpeg_codec->size + (bytes - remainder );
166
+ OPJ_SIZE_T new_size = jpeg_codec->size ? jpeg_codec->size : 1024 ;
167
+ while (required_offset > static_cast <OPJ_OFF_T>(new_size))
168
+ new_size *= 2 ;
169
+
170
+ const OPJ_SIZE_T MAX_BUFFER_SIZE = 512 * 1024 * 1024 ; // 512 MB, increase if needed
171
+ if (new_size > MAX_BUFFER_SIZE) return 0 ;
172
+
158
173
U8* new_buffer = (U8*)ll_aligned_malloc_16 (new_size);
159
- memcpy (new_buffer, jpeg_codec->buffer , jpeg_codec->offset );
160
- U8* old_buffer = jpeg_codec->buffer ;
174
+ if (!new_buffer) return 0 ; // Allocation failed
175
+
176
+ if (jpeg_codec->offset > 0 )
177
+ memcpy (new_buffer, jpeg_codec->buffer , static_cast <size_t >(jpeg_codec->offset ));
178
+
179
+ ll_aligned_free_16 (jpeg_codec->buffer );
161
180
jpeg_codec->buffer = new_buffer;
162
- ll_aligned_free_16 (old_buffer);
163
181
jpeg_codec->size = new_size;
164
182
}
165
- memcpy (jpeg_codec->buffer + jpeg_codec->offset , buffer, bytes);
166
- jpeg_codec->offset += bytes;
183
+
184
+ memcpy (jpeg_codec->buffer + jpeg_codec->offset , buffer, static_cast <size_t >(bytes));
185
+ jpeg_codec->offset = required_offset;
167
186
return bytes;
168
187
}
169
188
170
189
static OPJ_OFF_T opj_skip (OPJ_OFF_T bytes, void * user_data)
171
190
{
191
+ llassert (user_data);
172
192
JPEG2KBase* jpeg_codec = static_cast <JPEG2KBase*>(user_data);
173
- jpeg_codec->offset += bytes;
174
193
175
- if (jpeg_codec->offset > (OPJ_OFF_T)jpeg_codec->size )
176
- {
177
- jpeg_codec->offset = jpeg_codec->size ;
178
- // Indicate end of stream
179
- return (OPJ_OFF_T)-1 ;
180
- }
194
+ OPJ_OFF_T new_offset = jpeg_codec->offset + bytes;
181
195
182
- if (jpeg_codec-> offset < 0 )
196
+ if (new_offset < 0 || new_offset > static_cast <OPJ_OFF_T>(jpeg_codec-> size ) )
183
197
{
184
- // Shouldn't be possible?
185
- jpeg_codec->offset = 0 ;
198
+ // Clamp and indicate EOF or error
199
+ jpeg_codec->offset = llclamp<OPJ_OFF_T>(new_offset, 0 , static_cast <OPJ_OFF_T>(jpeg_codec-> size )) ;
186
200
return (OPJ_OFF_T)-1 ;
187
201
}
188
202
203
+ jpeg_codec->offset = new_offset;
189
204
return bytes;
190
205
}
191
206
192
- static OPJ_BOOL opj_seek (OPJ_OFF_T bytes , void * user_data)
207
+ static OPJ_BOOL opj_seek (OPJ_OFF_T offset , void * user_data)
193
208
{
209
+ llassert (user_data);
194
210
JPEG2KBase* jpeg_codec = static_cast <JPEG2KBase*>(user_data);
195
- jpeg_codec->offset = bytes;
196
- jpeg_codec->offset = llclamp (U32 (jpeg_codec->offset ), U32 (0 ), U32 (jpeg_codec->size ));
211
+
212
+ if (offset < 0 || offset > static_cast <OPJ_OFF_T>(jpeg_codec->size ))
213
+ return OPJ_FALSE;
214
+
215
+ jpeg_codec->offset = offset;
197
216
return OPJ_TRUE;
198
217
}
199
218
200
219
static void opj_free_user_data (void * user_data)
201
220
{
221
+ llassert (user_data);
222
+
202
223
JPEG2KBase* jpeg_codec = static_cast <JPEG2KBase*>(user_data);
203
224
// Don't free, data is managed externally
204
225
jpeg_codec->buffer = nullptr ;
@@ -208,14 +229,54 @@ static void opj_free_user_data(void * user_data)
208
229
209
230
static void opj_free_user_data_write (void * user_data)
210
231
{
232
+ llassert (user_data);
233
+
211
234
JPEG2KBase* jpeg_codec = static_cast <JPEG2KBase*>(user_data);
212
235
// Free, data was allocated here
213
- ll_aligned_free_16 (jpeg_codec->buffer );
214
- jpeg_codec->buffer = nullptr ;
236
+ if (jpeg_codec->buffer )
237
+ {
238
+ ll_aligned_free_16 (jpeg_codec->buffer );
239
+ jpeg_codec->buffer = nullptr ;
240
+ }
215
241
jpeg_codec->size = 0 ;
216
242
jpeg_codec->offset = 0 ;
217
243
}
218
244
245
+ /* *
246
+ * Estimates the number of layers necessary depending on the image surface (w x h)
247
+ */
248
+ static U32 estimate_num_layers (U32 surface)
249
+ {
250
+ if (surface <= 1024 ) return 2 ; // Tiny (≤32×32)
251
+ else if (surface <= 16384 ) return 3 ; // Small (≤128×128)
252
+ else if (surface <= 262144 ) return 4 ; // Medium (≤512×512)
253
+ else if (surface <= 1048576 ) return 5 ; // Up to ~1MP
254
+ else return 6 ; // Up to ~1.5–2MP
255
+ }
256
+
257
+ /* *
258
+ * Sets the parameters.tcp_rates according to the number of layers and a last tcp_rate value (which equals to the final compression ratio).
259
+ *
260
+ * Example for 6 layers:
261
+ *
262
+ * i = 5, parameters.tcp_rates[6 - 1 - 5] = 8.0f * (1 << (5 << 1)) = 8192 // Layer 5 (lowest quality)
263
+ * i = 4, parameters.tcp_rates[6 - 1 - 4] = 8.0f * (1 << (4 << 1)) = 2048 // Layer 4
264
+ * i = 3, parameters.tcp_rates[6 - 1 - 3] = 8.0f * (1 << (3 << 1)) = 512 // Layer 3
265
+ * i = 2, parameters.tcp_rates[6 - 1 - 2] = 8.0f * (1 << (2 << 1)) = 128 // Layer 2
266
+ * i = 1, parameters.tcp_rates[6 - 1 - 1] = 8.0f * (1 << (1 << 1)) = 32 // Layer 1
267
+ * i = 0, parameters.tcp_rates[6 - 1 - 0] = 8.0f * (1 << (0 << 1)) = 8 // Layer 0 (highest quality)
268
+ *
269
+ */
270
+ static void set_tcp_rates (opj_cparameters_t * parameters, U32 num_layers = 1 , F32 last_tcp_rate = LAST_TCP_RATE)
271
+ {
272
+ parameters->tcp_numlayers = num_layers;
273
+
274
+ for (int i = num_layers - 1 ; i >= 0 ; i--)
275
+ {
276
+ parameters->tcp_rates [num_layers - 1 - i] = last_tcp_rate * static_cast <F32>(1 << (i << 1 ));
277
+ }
278
+ }
279
+
219
280
class JPEG2KDecode : public JPEG2KBase
220
281
{
221
282
public:
@@ -430,15 +491,16 @@ class JPEG2KEncode : public JPEG2KBase
430
491
431
492
opj_set_default_encoder_parameters (¶meters);
432
493
parameters.cod_format = OPJ_CODEC_J2K;
433
- parameters.cp_disto_alloc = 1 ;
494
+ parameters.prog_order = OPJ_RLCP; // should be the default, but, just in case
495
+ parameters.cp_disto_alloc = 1 ; // enable rate allocation by distortion
496
+ parameters.max_cs_size = 0 ; // do not cap max size because we're using tcp_rates and also irrelevant with lossless.
434
497
435
498
if (reversible)
436
499
{
437
- parameters.max_cs_size = 0 ; // do not limit size for reversible compression
438
500
parameters.irreversible = 0 ; // should be the default, but, just in case
439
501
parameters.tcp_numlayers = 1 ;
440
502
/* documentation seems to be wrong, should be 0.0f for lossless, not 1.0f
441
- see https://github.com/uclouvain/openjpeg/blob/39e8c50a2f9bdcf36810ee3d41bcbf1cc78968ae /src/lib/openjp2/j2k.c#L7755
503
+ see https://github.com/uclouvain/openjpeg/blob/e7453e398b110891778d8da19209792c69ca7169 /src/lib/openjp2/j2k.c#L7817
442
504
*/
443
505
parameters.tcp_rates [0 ] = 0 .0f ;
444
506
}
@@ -493,53 +555,22 @@ class JPEG2KEncode : public JPEG2KBase
493
555
494
556
encoder = opj_create_compress (OPJ_CODEC_J2K);
495
557
496
- parameters.tcp_mct = (image->numcomps >= 3 ) ? 1 : 0 ;
497
- parameters.cod_format = OPJ_CODEC_J2K;
498
- parameters.prog_order = OPJ_RLCP;
499
- parameters.cp_disto_alloc = 1 ;
558
+ parameters.tcp_mct = (image->numcomps >= 3 ) ? 1 : 0 ; // no color transform for RGBA images
559
+
500
560
501
561
// if not lossless compression, computes tcp_numlayers and max_cs_size depending on the image dimensions
502
- if ( parameters.irreversible ) {
562
+ if ( parameters.irreversible )
563
+ {
503
564
504
565
// computes a number of layers
505
566
U32 surface = rawImageIn.getWidth () * rawImageIn.getHeight ();
506
- U32 nb_layers = 1 ;
507
- U32 s = 64 *64 ;
508
- while (surface > s)
509
- {
510
- nb_layers++;
511
- s *= 4 ;
512
- }
513
- nb_layers = llclamp (nb_layers, 1 , 6 );
514
-
515
- parameters.tcp_numlayers = nb_layers;
516
- parameters.tcp_rates [nb_layers - 1 ] = (U32)(1 .f / DEFAULT_COMPRESSION_RATE); // 1:8 by default
517
567
518
- // for each subsequent layer, computes its rate and adds surface * numcomps * 1/rate to the max_cs_size
519
- U32 max_cs_size = (U32)(surface * image->numcomps * DEFAULT_COMPRESSION_RATE);
520
- U32 multiplier;
521
- for (int i = nb_layers - 2 ; i >= 0 ; i--)
522
- {
523
- if ( i == nb_layers - 2 )
524
- {
525
- multiplier = 15 ;
526
- }
527
- else if ( i == nb_layers - 3 )
528
- {
529
- multiplier = 4 ;
530
- }
531
- else
532
- {
533
- multiplier = 2 ;
534
- }
535
- parameters.tcp_rates [i] = parameters.tcp_rates [i + 1 ] * multiplier;
536
- max_cs_size += (U32)(surface * image->numcomps * (1 / parameters.tcp_rates [i]));
537
- }
568
+ // gets the necessary number of layers
569
+ U32 nb_layers = estimate_num_layers (surface);
538
570
539
- // ensure that we have at least a minimal size
540
- max_cs_size = llmax (max_cs_size, (U32)FIRST_PACKET_SIZE );
571
+ // fills parameters.tcp_rates and updates parameters.tcp_numlayers
572
+ set_tcp_rates (¶meters, nb_layers, LAST_TCP_RATE );
541
573
542
- parameters.max_cs_size = max_cs_size;
543
574
}
544
575
545
576
if (!opj_setup_encoder (encoder, ¶meters, image))
@@ -579,7 +610,7 @@ class JPEG2KEncode : public JPEG2KBase
579
610
opj_stream_destroy (stream);
580
611
}
581
612
582
- stream = opj_stream_create (data_size_guess, false );
613
+ stream = opj_stream_create (data_size_guess, OPJ_FALSE );
583
614
if (!stream)
584
615
{
585
616
return false ;
@@ -620,25 +651,23 @@ class JPEG2KEncode : public JPEG2KBase
620
651
621
652
void setImage (const LLImageRaw& raw)
622
653
{
623
- opj_image_cmptparm_t cmptparm[MAX_ENCODED_DISCARD_LEVELS];
624
- memset (&cmptparm[0 ], 0 , MAX_ENCODED_DISCARD_LEVELS * sizeof (opj_image_cmptparm_t ));
625
-
626
654
S32 numcomps = raw.getComponents ();
627
- S32 width = raw.getWidth ();
628
- S32 height = raw.getHeight ();
655
+ S32 width = raw.getWidth ();
656
+ S32 height = raw.getHeight ();
657
+
658
+ std::vector<opj_image_cmptparm_t > cmptparm (numcomps);
629
659
630
660
for (S32 c = 0 ; c < numcomps; c++)
631
661
{
632
- cmptparm[c].prec = 8 ;
633
- cmptparm[c].bpp = 8 ;
662
+ cmptparm[c].prec = 8 ; // replaces .bpp
634
663
cmptparm[c].sgnd = 0 ;
635
664
cmptparm[c].dx = parameters.subsampling_dx ;
636
665
cmptparm[c].dy = parameters.subsampling_dy ;
637
666
cmptparm[c].w = width;
638
667
cmptparm[c].h = height;
639
668
}
640
669
641
- image = opj_image_create (numcomps, & cmptparm[ 0 ] , OPJ_CLRSPC_SRGB);
670
+ image = opj_image_create (numcomps, cmptparm. data () , OPJ_CLRSPC_SRGB);
642
671
643
672
image->x1 = width;
644
673
image->y1 = height;
@@ -650,7 +679,7 @@ class JPEG2KEncode : public JPEG2KBase
650
679
{
651
680
for (S32 x = 0 ; x < width; x++)
652
681
{
653
- const U8 *pixel = src_datap + (y* width + x) * numcomps;
682
+ const U8 *pixel = src_datap + (y * width + x) * numcomps;
654
683
for (S32 c = 0 ; c < numcomps; c++)
655
684
{
656
685
image->comps [c].data [i] = *pixel;
0 commit comments