Coverage Report

Created: 2026-09-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/sjpx_openjpeg.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
18
/* opj filter implementation using OpenJPeg library */
19
20
#include "memory_.h"
21
#include "gserrors.h"
22
#include "gdebug.h"
23
#include "strimpl.h"
24
#include "sjpx_openjpeg.h"
25
#include "gxsync.h"
26
#include "assert_.h"
27
#if !defined(SHARE_JPX) || (SHARE_JPX == 0)
28
#include "opj_malloc.h"
29
#endif
30
/* Some locking to get around the criminal lack of context
31
 * in the openjpeg library. */
32
#if !defined(SHARE_JPX) || (SHARE_JPX == 0)
33
static gs_memory_t *opj_memory;
34
#endif
35
36
int sjpxd_create(gs_memory_t *mem)
37
158k
{
38
158k
#if !defined(SHARE_JPX) || (SHARE_JPX == 0)
39
158k
    gs_lib_ctx_t *ctx = mem->gs_lib_ctx;
40
41
158k
    ctx->sjpxd_private = gx_monitor_label(gx_monitor_alloc(mem), "sjpxd_monitor");
42
158k
    if (ctx->sjpxd_private == NULL)
43
0
        return gs_error_VMerror;
44
158k
#endif
45
158k
    return 0;
46
158k
}
47
48
void sjpxd_destroy(gs_memory_t *mem)
49
158k
{
50
158k
#if !defined(SHARE_JPX) || (SHARE_JPX == 0)
51
158k
    gs_lib_ctx_t *ctx = mem->gs_lib_ctx;
52
53
158k
    gx_monitor_free((gx_monitor_t *)ctx->sjpxd_private);
54
158k
    ctx->sjpxd_private = NULL;
55
158k
#endif
56
158k
}
57
58
static int opj_lock(gs_memory_t *mem)
59
461k
{
60
461k
#if !defined(SHARE_JPX) || (SHARE_JPX == 0)
61
461k
    int ret;
62
63
461k
    gs_lib_ctx_t *ctx = mem->gs_lib_ctx;
64
65
461k
    ret = gx_monitor_enter((gx_monitor_t *)ctx->sjpxd_private);
66
461k
    assert(opj_memory == NULL);
67
461k
    opj_memory = mem->non_gc_memory;
68
461k
    return ret;
69
#else
70
    return 0;
71
#endif
72
461k
}
73
74
static int opj_unlock(gs_memory_t *mem)
75
461k
{
76
461k
#if !defined(SHARE_JPX) || (SHARE_JPX == 0)
77
461k
    gs_lib_ctx_t *ctx = mem->gs_lib_ctx;
78
79
461k
    assert(opj_memory != NULL);
80
461k
    opj_memory = NULL;
81
461k
    return gx_monitor_leave((gx_monitor_t *)ctx->sjpxd_private);
82
#else
83
    return 0;
84
#endif
85
461k
}
86
87
#if !defined(SHARE_JPX) || (SHARE_JPX == 0)
88
/* Allocation routines that use the memory pointer given above */
89
void *opj_malloc(size_t size)
90
6.30M
{
91
6.30M
    if (size == 0)
92
0
        return NULL;
93
94
6.30M
    assert(opj_memory != NULL);
95
96
6.30M
    if (size > (size_t) ARCH_MAX_UINT)
97
0
      return NULL;
98
99
6.30M
    return (void *)gs_alloc_bytes(opj_memory, size, "opj_malloc");
100
6.30M
}
101
102
void *opj_calloc(size_t n, size_t size)
103
3.79M
{
104
3.79M
    void *ptr;
105
106
    /* FIXME: Check for overflow? */
107
3.79M
    size *= n;
108
109
3.79M
    ptr = opj_malloc(size);
110
3.79M
    if (ptr)
111
3.79M
        memset(ptr, 0, size);
112
3.79M
    return ptr;
113
3.79M
}
114
115
void *opj_realloc(void *ptr, size_t size)
116
765k
{
117
765k
    if (ptr == NULL)
118
356k
        return opj_malloc(size);
119
120
409k
    if (size == 0)
121
0
    {
122
0
        opj_free(ptr);
123
0
        return NULL;
124
0
    }
125
126
409k
    return gs_resize_object(opj_memory, ptr, size, "opj_malloc");
127
409k
}
128
129
void opj_free(void *ptr)
130
6.38M
{
131
6.38M
    gs_free_object(opj_memory, ptr, "opj_malloc");
132
6.38M
}
133
134
static inline void * opj_aligned_malloc_n(size_t size, size_t align)
135
315k
{
136
315k
    uint8_t *ptr;
137
315k
    int off;
138
139
315k
    if (size == 0)
140
0
        return NULL;
141
142
315k
    size += align + sizeof(uint8_t);
143
315k
    ptr = opj_malloc(size);
144
315k
    if (ptr == NULL)
145
0
        return NULL;
146
315k
    off = align - (((int)(intptr_t)ptr) & (align - 1));
147
315k
    ptr[off-1] = off;
148
315k
    return ptr + off;
149
315k
}
150
151
void * opj_aligned_malloc(size_t size)
152
313k
{
153
313k
    return opj_aligned_malloc_n(size, 16);
154
313k
}
155
156
void *opj_aligned_32_malloc(size_t size)
157
1.88k
{
158
1.88k
    return opj_aligned_malloc_n(size, 32);
159
1.88k
}
160
161
void opj_aligned_free(void* ptr_)
162
2.00M
{
163
2.00M
    uint8_t *ptr = (uint8_t *)ptr_;
164
2.00M
    uint8_t off;
165
2.00M
    if (ptr == NULL)
166
1.69M
        return;
167
168
315k
    off = ptr[-1];
169
315k
    opj_free((void *)(((unsigned char *)ptr) - off));
170
315k
}
171
172
#if 0
173
/* UNUSED currently, and moderately tricky, so deferred until required */
174
void * opj_aligned_realloc(void *ptr, size_t size)
175
{
176
  return opj_realloc(ptr, size);
177
}
178
#endif
179
#endif
180
181
gs_private_st_simple(st_jpxd_state, stream_jpxd_state,
182
    "JPXDecode filter state"); /* creates a gc object for our state,
183
                            defined in sjpx.h */
184
185
static int s_opjd_accumulate_input(stream_jpxd_state *state, stream_cursor_read * pr);
186
187
static OPJ_SIZE_T sjpx_stream_read(void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data)
188
13.7k
{
189
13.7k
  stream_block *sb = (stream_block *)p_user_data;
190
13.7k
  OPJ_SIZE_T len;
191
192
13.7k
  len = sb->fill - sb->pos;
193
13.7k
        if (sb->fill < sb->pos)
194
0
    len = 0;
195
13.7k
  if (len == 0)
196
1.44k
    return (OPJ_SIZE_T)-1;  /* End of file! */
197
12.3k
  if ((OPJ_SIZE_T)len > p_nb_bytes)
198
0
    len = p_nb_bytes;
199
12.3k
  memcpy(p_buffer, sb->data + sb->pos, len);
200
12.3k
  sb->pos += len;
201
12.3k
  return len;
202
13.7k
}
203
204
static OPJ_OFF_T sjpx_stream_skip(OPJ_OFF_T skip, void * p_user_data)
205
14
{
206
14
  stream_block *sb = (stream_block *)p_user_data;
207
208
14
  if (skip > sb->fill - sb->pos)
209
14
    skip = sb->fill - sb->pos;
210
14
  sb->pos += skip;
211
14
  return sb->pos;
212
14
}
213
214
static OPJ_BOOL sjpx_stream_seek(OPJ_OFF_T seek_pos, void * p_user_data)
215
2.82k
{
216
2.82k
  stream_block *sb = (stream_block *)p_user_data;
217
218
2.82k
  if (seek_pos > sb->fill)
219
73
    return OPJ_FALSE;
220
2.75k
  sb->pos = seek_pos;
221
2.75k
  return OPJ_TRUE;
222
2.82k
}
223
224
static void sjpx_error_callback(const char *msg, void *ptr)
225
19.1k
{
226
19.1k
  dlprintf1("openjpeg error: %s", msg);
227
19.1k
}
228
229
static void sjpx_info_callback(const char *msg, void *ptr)
230
54.4k
{
231
#ifdef DEBUG
232
  /* prevent too many messages during normal build */
233
  dlprintf1("openjpeg info: %s", msg);
234
#endif
235
54.4k
}
236
237
static void sjpx_warning_callback(const char *msg, void *ptr)
238
564
{
239
#ifdef DEBUG
240
  /* prevent too many messages during normal build */
241
  dlprintf1("openjpeg warning: %s", msg);
242
#endif
243
564
}
244
245
/* initialize the stream */
246
static int
247
s_opjd_init(stream_state * ss)
248
10.2k
{
249
10.2k
    stream_jpxd_state *const state = (stream_jpxd_state *) ss;
250
10.2k
    state->codec = NULL;
251
252
10.2k
    state->image = NULL;
253
10.2k
    state->sb.data= NULL;
254
10.2k
    state->sb.size = 0;
255
10.2k
    state->sb.pos = 0;
256
10.2k
    state->sb.fill = 0;
257
10.2k
    state->out_offset = 0;
258
10.2k
    state->pdata = NULL;
259
10.2k
    state->sign_comps = NULL;
260
10.2k
    state->stream = NULL;
261
10.2k
    state->row_data = NULL;
262
263
10.2k
    return 0;
264
10.2k
}
265
266
/* setting the codec format,
267
   allocating the stream and image structures, and
268
   initializing the decoder.
269
 */
270
static int
271
s_opjd_set_codec_format(stream_state * ss, OPJ_CODEC_FORMAT format)
272
9.75k
{
273
9.75k
    stream_jpxd_state *const state = (stream_jpxd_state *) ss;
274
9.75k
    opj_dparameters_t parameters; /* decompression parameters */
275
276
    /* set decoding parameters to default values */
277
9.75k
    opj_set_default_decoder_parameters(&parameters);
278
279
    /* get a decoder handle */
280
9.75k
    state->codec = opj_create_decompress(format);
281
9.75k
    if (state->codec == NULL)
282
0
        return_error(gs_error_VMerror);
283
284
    /* catch events using our callbacks */
285
9.75k
    opj_set_error_handler(state->codec, sjpx_error_callback, stderr);
286
9.75k
    opj_set_info_handler(state->codec, sjpx_info_callback, stderr);
287
9.75k
    opj_set_warning_handler(state->codec, sjpx_warning_callback, stderr);
288
289
9.75k
    if (state->colorspace == gs_jpx_cs_indexed) {
290
55
        parameters.flags |= OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
291
55
    }
292
293
    /* setup the decoder decoding parameters using user parameters */
294
9.75k
    if (!opj_setup_decoder(state->codec, &parameters))
295
0
    {
296
0
        dlprintf("openjpeg: failed to setup the decoder!\n");
297
0
        return ERRC;
298
0
    }
299
300
    /* open a byte stream */
301
9.75k
    state->stream = opj_stream_default_create(OPJ_TRUE);
302
9.75k
    if (state->stream == NULL)
303
0
    {
304
0
        dlprintf("openjpeg: failed to open a byte stream!\n");
305
0
        return ERRC;
306
0
    }
307
308
9.75k
    opj_stream_set_read_function(state->stream, sjpx_stream_read);
309
9.75k
    opj_stream_set_skip_function(state->stream, sjpx_stream_skip);
310
9.75k
    opj_stream_set_seek_function(state->stream, sjpx_stream_seek);
311
312
9.75k
    return 0;
313
9.75k
}
314
315
static void
316
ycc_to_rgb_8(unsigned char *row, unsigned long row_size)
317
0
{
318
0
    unsigned char y;
319
0
    signed char u, v;
320
0
    int r,g,b;
321
322
    /* extra code for OSS-fuzz 414383025, the test file should not get here now
323
     * but as a belt and braces approach, check the width of the row is a
324
     * multiple of 3. If it isn't, reduce it until it is. This prevents
325
     * row_size being decreased *below* 0, failing to exit the loop and
326
     * reading from illegal memory locations
327
     */
328
0
    if (row_size < 3)
329
0
        return;
330
0
    row_size = row_size - row_size % 3;
331
332
0
    do
333
0
    {
334
0
        y = row[0];
335
0
        u = row[1] - 128;
336
0
        v = row[2] - 128;
337
0
        r = (int)((double)y + 1.402 * v);
338
0
        if (r < 0)
339
0
            r = 0;
340
0
        if (r > 255)
341
0
            r = 255;
342
0
        g = (int)((double)y - 0.34413 * u - 0.71414 * v);
343
0
        if (g < 0)
344
0
            g = 0;
345
0
        if (g > 255)
346
0
            g = 255;
347
0
        b = (int)((double)y + 1.772 * u);
348
0
        if (b < 0)
349
0
            b = 0;
350
0
        if (b > 255)
351
0
            b = 255;
352
0
        row[0] = r;
353
0
        row[1] = g;
354
0
        row[2] = b;
355
0
        row += 3;
356
0
        row_size -= 3;
357
0
    }
358
0
    while (row_size);
359
0
}
360
361
static void
362
ycc_to_rgb_16(unsigned char *row, unsigned long row_size)
363
0
{
364
0
    unsigned short y;
365
0
    signed short u, v;
366
0
    int r,g,b;
367
368
    /* As per the 8-bit case above, make sure that row-size is a mutiple of 6
369
     * so that we don't decrement it below 0 in the loop.
370
     */
371
0
    if (row_size < 6)
372
0
        return;
373
0
    row_size = row_size - row_size % 6;
374
375
0
    do
376
0
    {
377
0
        y = (row[0]<<8) | row[1];
378
0
        u = ((row[2]<<8) | row[3]) - 32768;
379
0
        v = ((row[4]<<8) | row[5]) - 32768;
380
0
        r = (int)((double)y + 1.402 * v);
381
0
        if (r < 0)
382
0
            r = 0;
383
0
        if (r > 65535)
384
0
            r = 65535;
385
0
        g = (int)((double)y - 0.34413 * u - 0.71414 * v);
386
0
        if (g < 0)
387
0
            g = 0;
388
0
        if (g > 65535)
389
0
            g = 65535;
390
0
        b = (int)((double)y + 1.772 * u);
391
0
        if (b < 0)
392
0
            b = 0;
393
0
        if (b > 65535)
394
0
            b = 65535;
395
0
        row[0] = r>>8;
396
0
        row[1] = r;
397
0
        row[2] = g>>8;
398
0
        row[3] = g;
399
0
        row[4] = b>>8;
400
0
        row[5] = b;
401
0
        row += 6;
402
0
        row_size -= 6;
403
0
    }
404
0
    while (row_size);
405
0
}
406
407
static int decode_image(stream_jpxd_state * const state)
408
9.75k
{
409
9.75k
    int numprimcomp = 0, alpha_comp = -1, compno, rowbytes, bps;
410
411
    /* read header */
412
9.75k
    if (!opj_read_header(state->stream, state->codec, &(state->image)))
413
1.20k
    {
414
1.20k
      dlprintf("openjpeg: failed to read header\n");
415
1.20k
      return ERRC;
416
1.20k
    }
417
418
    /* decode the stream and fill the image structure */
419
8.55k
    if (!opj_decode(state->codec, state->stream, state->image))
420
5.94k
    {
421
5.94k
        dlprintf("openjpeg: failed to decode image!\n");
422
5.94k
        return ERRC;
423
5.94k
    }
424
425
    /* check dimension and prec */
426
2.60k
    if (state->image->numcomps == 0)
427
0
        return ERRC;
428
429
2.60k
    state->width = state->image->comps[0].w;
430
2.60k
    state->height = state->image->comps[0].h;
431
2.60k
    state->bpp = state->image->comps[0].prec;
432
2.60k
    state->samescale = true;
433
5.63k
    for(compno = 1; compno < state->image->numcomps; compno++)
434
3.03k
    {
435
3.03k
        if (state->bpp != state->image->comps[compno].prec)
436
0
            return ERRC; /* Not supported. */
437
3.03k
        if (state->width < state->image->comps[compno].w)
438
0
            state->width = state->image->comps[compno].w;
439
3.03k
        if (state->height < state->image->comps[compno].h)
440
0
            state->height = state->image->comps[compno].h;
441
3.03k
        if (state->image->comps[compno].dx != state->image->comps[0].dx ||
442
3.03k
                state->image->comps[compno].dy != state->image->comps[0].dy)
443
0
            state->samescale = false;
444
3.03k
    }
445
446
    /* find alpha component and regular colour component by channel definition */
447
8.23k
    for (compno = 0; compno < state->image->numcomps; compno++)
448
5.63k
    {
449
5.63k
        if (state->image->comps[compno].alpha == 0x00)
450
5.61k
            numprimcomp++;
451
21
        else if (state->image->comps[compno].alpha == 0x01 || state->image->comps[compno].alpha == 0x02)
452
21
            alpha_comp = compno;
453
5.63k
    }
454
455
    /* color space and number of components */
456
2.60k
    switch(state->image->color_space)
457
2.60k
    {
458
1.07k
        case OPJ_CLRSPC_GRAY:
459
1.07k
            state->colorspace = gs_jpx_cs_gray;
460
1.07k
            if (numprimcomp > 1) {
461
0
                dmprintf1(state->memory, "openjpeg warning: Ignoring extra components for %d component Gray data.\n", numprimcomp);
462
0
                numprimcomp = 1;
463
0
            }
464
1.07k
            break;
465
1.51k
        case OPJ_CLRSPC_SRGB:
466
1.51k
        case OPJ_CLRSPC_SYCC:
467
1.52k
        case OPJ_CLRSPC_EYCC:
468
1.52k
            state->colorspace = gs_jpx_cs_rgb;
469
1.52k
            if (numprimcomp > 3) {
470
0
                dmprintf1(state->memory, "openjpeg warning: Ignoring extra components for %d component RGB data.\n", numprimcomp);
471
0
                numprimcomp = 3;
472
0
            }
473
1.52k
           break;
474
0
        case OPJ_CLRSPC_CMYK:
475
0
            state->colorspace = gs_jpx_cs_cmyk;
476
0
            if (numprimcomp > 4) {
477
0
                dmprintf1(state->memory, "openjpeg warning: Ignoring extra components for %d component CMYK data.\n", numprimcomp);
478
0
                numprimcomp = 4;
479
0
            }
480
0
            break;
481
0
        default:
482
3
        case OPJ_CLRSPC_UNSPECIFIED:
483
6
        case OPJ_CLRSPC_UNKNOWN:
484
6
            if (numprimcomp == 1) {
485
1
                dmprintf1(state->memory, "openjpeg warning: unspec CS. %d component so assuming gray.\n", numprimcomp);
486
1
                state->colorspace = gs_jpx_cs_gray;
487
5
            } else if (numprimcomp == 4) {
488
0
                dmprintf1(state->memory, "openjpeg warning: unspec CS. %d components so assuming CMYK.\n", numprimcomp);
489
0
                state->colorspace = gs_jpx_cs_cmyk;
490
5
            } else {
491
                /* Note, numprimcomp > 4 possible here. Bug 694909.
492
                   Trust that it is RGB though.  Do not set numprimcomp */
493
5
                dmprintf1(state->memory, "openjpeg warning: unspec CS. %d components. Assuming data RGB.\n", numprimcomp);
494
5
                state->colorspace = gs_jpx_cs_rgb;
495
5
            }
496
6
            break;
497
2.60k
    }
498
499
2.60k
    state->alpha_comp = -1;
500
2.60k
    if (state->alpha)
501
0
    {
502
0
        state->alpha_comp = alpha_comp;
503
0
        state->out_numcomps = 1;
504
0
    }
505
2.60k
    else
506
2.60k
        state->out_numcomps = numprimcomp;
507
508
    /* round up bpp 12->16 */
509
2.60k
    if (state->bpp == 12)
510
0
        state->bpp = 16;
511
512
2.60k
    if (state->bpp != 1 && state->bpp != 2 && state->bpp != 4 && state->bpp != 8 && state->bpp != 16)
513
0
        return ERRC;
514
515
    /* calculate  total data */
516
2.60k
    bps = state->bpp * state->out_numcomps;
517
518
    /* Overflow check, almost certainly superfluous, but let's be certain */
519
2.60k
    if (state->out_numcomps != 0 && bps / state->out_numcomps != state->bpp)
520
0
        return_error(gs_error_rangecheck);
521
522
2.60k
    rowbytes = state->width * bps;
523
    /* Overflow check */
524
2.60k
    if ((bps != 0 && rowbytes / bps != state->width) || rowbytes > max_int - 8)
525
0
        return_error(gs_error_rangecheck);
526
527
2.60k
    rowbytes = (rowbytes + 7) / 8;
528
529
2.60k
    state->totalbytes = (ulong)rowbytes*state->height;
530
    /* Overflow check */
531
2.60k
    if (rowbytes != 0 && state->totalbytes / rowbytes != state->height)
532
0
        return_error(gs_error_rangecheck);
533
534
2.60k
    state->pdata = (int **)gs_alloc_byte_array(state->memory->non_gc_memory, sizeof(int*)*(size_t)state->image->numcomps, 1, "decode_image(pdata)");
535
2.60k
    if (!state->pdata)
536
0
        return_error(gs_error_VMerror);
537
538
    /* compensate for signed data (signed => unsigned) */
539
2.60k
    state->sign_comps = (int *)gs_alloc_byte_array(state->memory->non_gc_memory, sizeof(int)*(size_t)state->image->numcomps, 1, "decode_image(sign_comps)");
540
2.60k
    if (!state->sign_comps)
541
0
        return_error(gs_error_VMerror);
542
543
8.23k
    for(compno = 0; compno < state->image->numcomps; compno++)
544
5.63k
    {
545
5.63k
        if (state->image->comps[compno].sgnd)
546
0
            state->sign_comps[compno] = ((state->bpp%8)==0) ? 0x80 : (1<<(state->bpp-1));
547
5.63k
        else
548
5.63k
            state->sign_comps[compno] = 0;
549
5.63k
    }
550
551
2.60k
    return 0;
552
2.60k
}
553
554
static int process_one_trunk(stream_jpxd_state * const state, stream_cursor_write * pw)
555
782k
{
556
    /* read data from image to pw */
557
782k
    unsigned long out_size = pw->limit - pw->ptr;
558
782k
    int bytepp1 = state->bpp/8; /* bytes / pixel for one output component */
559
782k
    int bytepp = state->out_numcomps*state->bpp/8; /* bytes / pixel all components */
560
782k
    unsigned long write_size = min(out_size-(bytepp?(out_size%bytepp):0), state->totalbytes-state->out_offset);
561
782k
    int shift_bit = state->bpp-state->image->comps[0].prec; /*difference between input and output bit-depth*/
562
782k
    int img_numcomps = min(state->out_numcomps, state->image->numcomps); /* the actual number of channel data used */
563
782k
    int compno;
564
782k
    unsigned long il;
565
782k
    int i;
566
782k
    int b;
567
782k
    byte *row;
568
782k
    unsigned int x_offset;
569
782k
    unsigned int y_offset;
570
782k
    unsigned int row_size = (state->width * state->out_numcomps * state->bpp + 7)>>3;
571
572
    /* If nothing to write, nothing to do */
573
782k
    if (write_size == 0)
574
0
        return 0;
575
576
782k
    if (state->row_data == NULL)
577
2.60k
    {
578
2.60k
        state->row_data = gs_alloc_byte_array(state->memory->non_gc_memory, row_size, 1, "jpxd_openjpeg(row_data)");
579
2.60k
        if (state->row_data == NULL)
580
0
            return gs_error_VMerror;
581
2.60k
    }
582
583
1.62M
    while (state->out_offset != state->totalbytes)
584
1.62M
    {
585
1.62M
        y_offset = state->out_offset / row_size;
586
1.62M
        x_offset = state->out_offset % row_size;
587
588
1.62M
        if (x_offset == 0)
589
1.01M
        {
590
            /* Decode another rows worth */
591
1.01M
            row = state->row_data;
592
1.01M
            if (state->alpha && state->alpha_comp == -1)
593
0
            {
594
                /* return 0xff for all */
595
0
                memset(row, 0xff, row_size);
596
0
            }
597
1.01M
            else if (state->samescale)
598
1.01M
            {
599
1.01M
                if (state->alpha)
600
0
                    state->pdata[0] = &(state->image->comps[state->alpha_comp].data[y_offset * state->width]);
601
1.01M
                else
602
1.01M
                {
603
3.20M
                    for (compno=0; compno<img_numcomps; compno++)
604
2.19M
                        state->pdata[compno] = &(state->image->comps[compno].data[y_offset * state->width]);
605
1.01M
                }
606
1.01M
                if (shift_bit == 0 && state->bpp == 8) /* optimized for the most common case */
607
1.00M
                {
608
372M
                    for (i = state->width; i > 0; i--)
609
1.17G
                        for (compno=0; compno<img_numcomps; compno++)
610
804M
                            *row++ = *(state->pdata[compno]++) + state->sign_comps[compno]; /* copy input buffer to output */
611
1.00M
                }
612
5.12k
                else if ((state->bpp%8)==0)
613
3.57k
                {
614
1.97M
                    for (i = state->width; i > 0; i--)
615
1.96M
                    {
616
3.93M
                        for (compno=0; compno<img_numcomps; compno++)
617
1.96M
                        {
618
5.90M
                            for (b=0; b<bytepp1; b++)
619
3.93M
                                *row++ = (((*(state->pdata[compno]) << shift_bit) >> (8*(bytepp1-b-1))))
620
3.93M
                                                        + (b==0 ? state->sign_comps[compno] : 0); /* split and shift input int to output bytes */
621
1.96M
                            state->pdata[compno]++;
622
1.96M
                        }
623
1.96M
                    }
624
3.57k
                }
625
1.55k
                else
626
1.55k
                {
627
                    /* shift_bit = 0, bpp < 8 */
628
1.55k
                    int bt=0;
629
1.55k
                    int bit_pos = 0;
630
818k
                    for (i = state->width; i > 0; i--)
631
816k
                    {
632
1.88M
                        for (compno=0; compno<img_numcomps; compno++)
633
1.06M
                        {
634
1.06M
                            bt <<= state->bpp;
635
1.06M
                            bt += *(state->pdata[compno]++) + state->sign_comps[compno];
636
1.06M
                            bit_pos += state->bpp;
637
1.06M
                            if (bit_pos >= 8)
638
534k
                            {
639
534k
                                *row++ = bt >> (bit_pos-8);
640
534k
                                bit_pos -= 8;
641
534k
                                bt &= (1<<bit_pos)-1;
642
534k
                            }
643
1.06M
                        }
644
816k
                    }
645
1.55k
                    if (bit_pos != 0)
646
148
                    {
647
                        /* row padding */
648
148
                        *row++ = bt << (8 - bit_pos);
649
148
                        bit_pos = 0;
650
148
                        bt = 0;
651
148
                    }
652
1.55k
                }
653
1.01M
            }
654
0
            else if ((state->bpp%8)==0)
655
0
            {
656
                /* sampling required */
657
0
                if (state->alpha)
658
0
                {
659
0
                    for (i = 0; i < state->width; i++)
660
0
                    {
661
0
                        int dx = state->image->comps[state->alpha_comp].dx;
662
0
                        int dy = state->image->comps[state->alpha_comp].dy;
663
0
                        int w = state->image->comps[state->alpha_comp].w;
664
0
                        int in_offset_scaled = (y_offset/dy * w) + i / dx;
665
0
                        for (b=0; b<bytepp1; b++)
666
0
                            *row++ = (((state->image->comps[state->alpha_comp].data[in_offset_scaled] << shift_bit) >> (8*(bytepp1-b-1))))
667
0
                                                                     + (b==0 ? state->sign_comps[state->alpha_comp] : 0);
668
0
                    }
669
0
                }
670
0
                else
671
0
                {
672
0
                    for (i = 0; i < state->width; i++)
673
0
                    {
674
0
                        for (compno=0; compno<img_numcomps; compno++)
675
0
                        {
676
0
                            int dx = state->image->comps[compno].dx;
677
0
                            int dy = state->image->comps[compno].dy;
678
0
                            int w = state->image->comps[compno].w;
679
0
                            int in_offset_scaled = (y_offset/dy * w) + i / dx;
680
0
                            for (b=0; b<bytepp1; b++)
681
0
                                *row++ = (((state->image->comps[compno].data[in_offset_scaled] << shift_bit) >> (8*(bytepp1-b-1))))
682
0
                                                                                + (b==0 ? state->sign_comps[compno] : 0);
683
0
                        }
684
0
                    }
685
0
                }
686
0
            }
687
0
            else
688
0
            {
689
0
                int compno = state->alpha ? state->alpha_comp : 0;
690
0
                int bt=0;
691
0
                int ppbyte1 = 8/state->bpp;
692
                /* sampling required */
693
                /* only grayscale can have such bit-depth, also shift_bit = 0, bpp < 8 */
694
0
                for (i = 0; i < state->width; )
695
0
                {
696
0
                    for (b=0; b<ppbyte1; b++, i++)
697
0
                    {
698
0
                        int dx = state->image->comps[compno].dx;
699
0
                        int dy = state->image->comps[compno].dy;
700
0
                        int w = state->image->comps[compno].w;
701
0
                        int in_offset_scaled = (y_offset/dy * w) + i / dx;
702
0
                        bt = bt<<state->bpp;
703
0
                        if (i < state->width)
704
0
                            bt += state->image->comps[compno].data[in_offset_scaled] + state->sign_comps[compno];
705
0
                    }
706
0
                    *row++ = bt;
707
0
                }
708
0
            }
709
710
            /* Check the number of components, if it's not 3 then we could be dealing with an indexed space and must not do this conversion */
711
1.01M
            if ((state->image->color_space == OPJ_CLRSPC_SYCC || state->image->color_space == OPJ_CLRSPC_EYCC) && state->image->numcomps == 3)
712
0
            {
713
                /* bpp >= 8 always, as bpp < 8 only for grayscale */
714
0
                if (state->bpp == 8)
715
0
                    ycc_to_rgb_8(state->row_data, row_size);
716
0
                else
717
0
                    ycc_to_rgb_16(state->row_data, row_size);
718
0
            }
719
1.01M
        }
720
721
1.62M
        pw->ptr++;
722
1.62M
        il = (write_size > (unsigned long)(row_size - x_offset)) ? (row_size - x_offset) : (unsigned int)write_size;
723
1.62M
        memcpy(pw->ptr, &state->row_data[x_offset], il);
724
1.62M
        pw->ptr += il;
725
1.62M
        pw->ptr--;
726
1.62M
        state->out_offset += il;
727
1.62M
        write_size -= il;
728
1.62M
        if (write_size == 0)
729
782k
            break;
730
1.62M
    }
731
732
782k
    if (state->out_offset == state->totalbytes)
733
2.57k
        return EOFC; /* all data returned */
734
779k
    else
735
779k
        return 1; /* need more calls */
736
782k
}
737
738
/* process a section of the input and return any decoded data.
739
   see strimpl.h for return codes.
740
 */
741
static int
742
s_opjd_process(stream_state * ss, stream_cursor_read * pr,
743
                 stream_cursor_write * pw, bool last)
744
1.24M
{
745
1.24M
    stream_jpxd_state *const state = (stream_jpxd_state *) ss;
746
1.24M
    long in_size = pr->limit - pr->ptr;
747
1.24M
    int locked = 0;
748
1.24M
    int code;
749
750
1.24M
    if (in_size > 0)
751
452k
    {
752
452k
        if (state->PassThrough && state->PassThroughfn) {
753
110k
            if (state->PassThrough && state->PassThroughfn && !state->StartedPassThrough) {
754
1.83k
                state->StartedPassThrough = 1;
755
1.83k
                (state->PassThroughfn)(state->device, NULL, 1);
756
1.83k
            }
757
110k
            (state->PassThroughfn)(state->device, (byte *)pr->ptr + 1, (byte *)pr->limit - (byte *)pr->ptr);
758
110k
        }
759
760
        /* buffer available data */
761
452k
        code = opj_lock(ss->memory);
762
452k
        if (code < 0) return code;
763
452k
        locked = 1;
764
765
452k
        code = s_opjd_accumulate_input(state, pr);
766
452k
        if (code < 0) {
767
0
            (void)opj_unlock(ss->memory);
768
0
            return code;
769
0
        }
770
771
452k
        if (state->codec == NULL) {
772
            /* state->sb.size is non-zero after successful
773
               accumulate_input(); 1 is probably extremely rare */
774
9.75k
            if (state->sb.data[0] == 0xFF && ((state->sb.size == 1) || (state->sb.data[1] == 0x4F)))
775
60
                code = s_opjd_set_codec_format(ss, OPJ_CODEC_J2K);
776
9.69k
            else
777
9.69k
                code = s_opjd_set_codec_format(ss, OPJ_CODEC_JP2);
778
9.75k
            if (code < 0)
779
0
            {
780
0
                (void)opj_unlock(ss->memory);
781
0
                return code;
782
0
            }
783
9.75k
        }
784
452k
    }
785
786
1.24M
    if (last == 1)
787
789k
    {
788
789k
        if (state->image == NULL)
789
9.75k
        {
790
9.75k
            int ret;
791
792
9.75k
            if (locked == 0)
793
76
            {
794
76
                ret = opj_lock(ss->memory);
795
76
                if (ret < 0) return ret;
796
76
                locked = 1;
797
76
            }
798
799
9.75k
#if OPJ_VERSION_MAJOR >= 2 && OPJ_VERSION_MINOR >= 1
800
9.75k
            opj_stream_set_user_data(state->stream, &(state->sb), NULL);
801
#else
802
            opj_stream_set_user_data(state->stream, &(state->sb));
803
#endif
804
9.75k
            opj_stream_set_user_data_length(state->stream, state->sb.size);
805
9.75k
            ret = decode_image(state);
806
9.75k
            if (ret != 0)
807
7.15k
            {
808
7.15k
                (void)opj_unlock(ss->memory);
809
7.15k
                return ret;
810
7.15k
            }
811
9.75k
        }
812
813
782k
        if (locked)
814
2.60k
        {
815
2.60k
            code = opj_unlock(ss->memory);
816
2.60k
            if (code < 0) return code;
817
2.60k
        }
818
819
        /* copy out available data */
820
782k
        return process_one_trunk(state, pw);
821
822
782k
    }
823
824
451k
    if (locked)
825
442k
        return opj_unlock(ss->memory);
826
827
    /* ask for more data */
828
9.22k
    return 0;
829
451k
}
830
831
/* Set the defaults */
832
static void
833
20.3k
s_opjd_set_defaults(stream_state * ss) {
834
20.3k
    stream_jpxd_state *const state = (stream_jpxd_state *) ss;
835
836
20.3k
    state->alpha = false;
837
20.3k
    state->colorspace = gs_jpx_cs_rgb;
838
20.3k
    state->StartedPassThrough = 0;
839
20.3k
    state->PassThrough = 0;
840
20.3k
    state->PassThroughfn = NULL;
841
20.3k
    state->device = (void *)NULL;
842
20.3k
}
843
844
/* stream release.
845
   free all our decoder state.
846
 */
847
static void
848
s_opjd_release(stream_state *ss)
849
10.1k
{
850
10.1k
    stream_jpxd_state *const state = (stream_jpxd_state *) ss;
851
852
10.1k
    if (state->PassThrough && state->PassThroughfn) {
853
1.99k
        state->StartedPassThrough = 0;
854
1.99k
        (state->PassThroughfn)(state->device, NULL, 0);
855
1.99k
    }
856
    /* empty stream or failed to accumulate */
857
10.1k
    if (state->codec == NULL)
858
467
        return;
859
860
9.69k
    (void)opj_lock(ss->memory);
861
862
    /* free image data structure */
863
9.69k
    if (state->image)
864
8.54k
        opj_image_destroy(state->image);
865
866
    /* free stream */
867
9.69k
    if (state->stream)
868
9.69k
        opj_stream_destroy(state->stream);
869
870
    /* free decoder handle */
871
9.69k
    if (state->codec)
872
9.69k
  opj_destroy_codec(state->codec);
873
874
9.69k
    (void)opj_unlock(ss->memory);
875
876
    /* free input buffer */
877
9.69k
    if (state->sb.data)
878
9.69k
        gs_free_object(state->memory->non_gc_memory, state->sb.data, "s_opjd_release(sb.data)");
879
880
9.69k
    if (state->pdata)
881
2.60k
        gs_free_object(state->memory->non_gc_memory, state->pdata, "s_opjd_release(pdata)");
882
883
9.69k
    if (state->sign_comps)
884
2.60k
        gs_free_object(state->memory->non_gc_memory, state->sign_comps, "s_opjd_release(sign_comps)");
885
886
9.69k
    if (state->row_data)
887
2.60k
        gs_free_object(state->memory->non_gc_memory, state->row_data, "s_opjd_release(row_data)");
888
9.69k
}
889
890
891
static int
892
s_opjd_accumulate_input(stream_jpxd_state *state, stream_cursor_read * pr)
893
452k
{
894
452k
    long in_size = pr->limit - pr->ptr;
895
896
    /* grow the input buffer if needed */
897
452k
    if (state->sb.size < state->sb.fill + in_size)
898
51.0k
    {
899
51.0k
        unsigned char *new_buf;
900
51.0k
        unsigned long new_size = state->sb.size==0 ? in_size : state->sb.size;
901
902
93.1k
        while (new_size < state->sb.fill + in_size)
903
42.0k
            new_size = new_size << 1;
904
905
51.0k
        if_debug1('s', "[s]opj growing input buffer to %lu bytes\n",
906
51.0k
                new_size);
907
51.0k
        if (state->sb.data == NULL)
908
9.75k
            new_buf = (byte *) gs_alloc_byte_array(state->memory->non_gc_memory, new_size, 1, "s_opjd_accumulate_input(alloc)");
909
41.3k
        else
910
41.3k
            new_buf = (byte *) gs_resize_object(state->memory->non_gc_memory, state->sb.data, new_size, "s_opjd_accumulate_input(resize)");
911
51.0k
        if (new_buf == NULL) return_error( gs_error_VMerror);
912
913
51.0k
        state->sb.data = new_buf;
914
51.0k
        state->sb.size = new_size;
915
51.0k
    }
916
917
    /* copy the available input into our buffer */
918
    /* note that the gs stream library uses offset-by-one
919
        indexing of its buffers while we use zero indexing */
920
452k
    memcpy(state->sb.data + state->sb.fill, pr->ptr + 1, in_size);
921
452k
    state->sb.fill += in_size;
922
452k
    pr->ptr += in_size;
923
924
452k
    return 0;
925
452k
}
926
927
/* stream template */
928
const stream_template s_jpxd_template = {
929
    &st_jpxd_state,
930
    s_opjd_init,
931
    s_opjd_process,
932
    1024, 1024,   /* min in and out buffer sizes we can handle
933
                     should be ~32k,64k for efficiency? */
934
    s_opjd_release,
935
    s_opjd_set_defaults
936
};