Coverage Report

Created: 2026-07-24 07:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/xps/xpstiff.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
/* XPS interpreter - TIFF image support */
18
19
#include "ghostxps.h"
20
21
#include "stream.h"
22
#include "strimpl.h"
23
#include "gsstate.h"
24
#include "jpeglib_.h"
25
#include "sdct.h"
26
#include "sjpeg.h"
27
#include "srlx.h"
28
#include "slzwx.h"
29
#include "szlibx.h"
30
#include "scfx.h"
31
#include "memory_.h"
32
#include "gxdevice.h"
33
34
/*
35
 * TIFF image loader. Should be enough to support TIFF files in XPS.
36
 * Baseline TIFF 6.0 plus CMYK, LZW, Flate and JPEG support.
37
 * Limited bit depths (1,2,4,8).
38
 * Limited planar configurations (1=chunky).
39
 * No tiles (easy fix if necessary).
40
 * TODO: RGBPal images
41
 */
42
43
typedef struct xps_tiff_s xps_tiff_t;
44
45
struct xps_tiff_s
46
{
47
    /* "file" */
48
    byte *bp, *rp, *ep;
49
50
    /* byte order */
51
    unsigned order;
52
53
    /* where we can find the strips of image data */
54
    unsigned rowsperstrip;
55
    unsigned stripcount;
56
    unsigned *stripoffsets;
57
    unsigned *stripbytecounts;
58
59
    /* colormap */
60
    unsigned *colormap;
61
    int colormap_max;
62
63
    /* assorted tags */
64
    unsigned subfiletype;
65
    unsigned photometric;
66
    unsigned compression;
67
    unsigned imagewidth;
68
    unsigned imagelength;
69
    unsigned samplesperpixel;
70
    unsigned bitspersample;
71
    unsigned planar;
72
    unsigned extrasamples;
73
    unsigned xresolution;
74
    unsigned yresolution;
75
    unsigned resolutionunit;
76
    unsigned fillorder;
77
    unsigned g3opts;
78
    unsigned g4opts;
79
    unsigned predictor;
80
81
    unsigned ycbcrsubsamp[2];
82
83
    byte *jpegtables;       /* point into "file" buffer */
84
    unsigned jpegtableslen;
85
86
    byte *profile;
87
    int profilesize;
88
};
89
90
enum
91
{
92
    TII = 0x4949, /* 'II' */
93
    TMM = 0x4d4d, /* 'MM' */
94
    TBYTE = 1,
95
    TASCII = 2,
96
    TSHORT = 3,
97
    TLONG = 4,
98
    TRATIONAL = 5
99
};
100
101
0
#define NewSubfileType                          254
102
4
#define ImageWidth                              256
103
4
#define ImageLength                             257
104
4
#define BitsPerSample                           258
105
4
#define Compression                             259
106
4
#define PhotometricInterpretation               262
107
0
#define FillOrder                               266
108
4
#define StripOffsets                            273
109
4
#define SamplesPerPixel                         277
110
4
#define RowsPerStrip                            278
111
4
#define StripByteCounts                         279
112
0
#define XResolution                             282
113
0
#define YResolution                             283
114
4
#define PlanarConfiguration                     284
115
0
#define T4Options                               292
116
0
#define T6Options                               293
117
0
#define ResolutionUnit                          296
118
0
#define Predictor                               317
119
0
#define ColorMap                                320
120
0
#define TileWidth                               322
121
0
#define TileLength                              323
122
0
#define TileOffsets                             324
123
0
#define TileByteCounts                          325
124
0
#define ExtraSamples                            338
125
0
#define JPEGTables                              347
126
0
#define YCbCrSubSampling                        520
127
0
#define ICCProfile                              34675
128
129
static const byte bitrev[256] =
130
{
131
    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
132
    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
133
    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
134
    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
135
    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
136
    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
137
    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
138
    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
139
    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
140
    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
141
    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
142
    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
143
    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
144
    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
145
    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
146
    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
147
    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
148
    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
149
    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
150
    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
151
    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
152
    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
153
    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
154
    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
155
    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
156
    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
157
    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
158
    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
159
    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
160
    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
161
    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
162
    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
163
};
164
165
static int
166
xps_report_error(stream_state * st, const char *str)
167
0
{
168
0
    (void) gs_throw1(-1, "%s", str);
169
0
    return 0;
170
0
}
171
172
static inline int
173
readbyte(xps_tiff_t *tiff, unsigned int *v)
174
504
{
175
504
    if (tiff->rp < tiff->ep) {
176
504
        *v = *tiff->rp++;
177
504
        return 0;
178
504
    }
179
0
    return EOF;
180
504
}
181
182
static inline int
183
readshort(xps_tiff_t *tiff, unsigned int *v)
184
132
{
185
132
    int code;
186
132
    unsigned a;
187
132
    unsigned b;
188
189
132
    code = readbyte(tiff, &a);
190
132
    if (code < 0)
191
0
        return code;
192
132
    code = readbyte(tiff, &b);
193
132
    if (code < 0)
194
0
        return code;
195
196
132
    if (tiff->order == TII)
197
132
        *v = (b << 8) | a;
198
0
    else
199
0
        *v = (a << 8) | b;
200
201
132
    return 0;
202
132
}
203
204
static inline unsigned
205
readlong(xps_tiff_t *tiff, unsigned int *v)
206
60
{
207
60
    int code;
208
60
    unsigned a;
209
60
    unsigned b;
210
60
    unsigned c;
211
60
    unsigned d;
212
213
60
    code = readbyte(tiff, &a);
214
60
    if (code < 0)
215
0
        return code;
216
60
    code = readbyte(tiff, &b);
217
60
    if (code < 0)
218
0
        return code;
219
60
    code = readbyte(tiff, &c);
220
60
    if (code < 0)
221
0
        return code;
222
60
    code = readbyte(tiff, &d);
223
60
    if (code < 0)
224
0
        return code;
225
226
60
    if (tiff->order == TII)
227
60
        *v = (d << 24) | (c << 16) | (b << 8) | a;
228
0
    else
229
0
        *v = (a << 24) | (b << 16) | (c << 8) | d;
230
231
60
    return 0;
232
60
}
233
234
static int
235
xps_decode_tiff_uncompressed(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *rl, byte *wp, byte *wl)
236
2
{
237
2
    if (rl - rp != wl - wp)
238
0
        return gs_throw(-1, "mismatch in data sizes");
239
2
    memcpy(wp, rp, wl - wp);
240
2
    return gs_okay;
241
2
}
242
243
static int
244
xps_decode_tiff_packbits(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *rl, byte *wp, byte *wl)
245
0
{
246
0
    stream_RLD_state state;
247
0
    stream_cursor_read scr;
248
0
    stream_cursor_write scw;
249
0
    int code;
250
251
0
    s_init_state((stream_state*)&state, &s_RLD_template, ctx->memory);
252
0
    state.report_error = xps_report_error;
253
254
0
    s_RLD_template.set_defaults((stream_state*)&state);
255
0
    s_RLD_template.init((stream_state*)&state);
256
257
0
    scr.ptr = rp - 1;
258
0
    scr.limit = rl - 1;
259
0
    scw.ptr = wp - 1;
260
0
    scw.limit = wl - 1;
261
262
0
    code = s_RLD_template.process((stream_state*)&state, &scr, &scw, true);
263
0
    if (code == ERRC)
264
0
        return gs_throw1(-1, "error in packbits data (code = %d)", code);
265
266
0
    return gs_okay;
267
0
}
268
269
static int
270
xps_decode_tiff_lzw(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *rl, byte *wp, byte *wl)
271
0
{
272
0
    stream_LZW_state state;
273
0
    stream_cursor_read scr;
274
0
    stream_cursor_write scw;
275
0
    int code;
276
277
0
    s_init_state((stream_state*)&state, &s_LZWD_template, ctx->memory);
278
0
    state.report_error = xps_report_error;
279
280
0
    s_LZWD_template.set_defaults((stream_state*)&state);
281
282
    /* old-style TIFF 5.0 reversed bit order, late change */
283
0
    if (rp[0] == 0 && rp[1] & 0x01)
284
0
    {
285
0
        state.EarlyChange = 0;
286
0
        state.FirstBitLowOrder = 1;
287
0
        state.OldTiff = 1;
288
0
    }
289
290
    /* new-style TIFF 6.0 normal bit order, early change */
291
0
    else
292
0
    {
293
0
        state.EarlyChange = 1;
294
0
        state.FirstBitLowOrder = 0;
295
0
        state.OldTiff = 0;
296
0
    }
297
298
0
    s_LZWD_template.init((stream_state*)&state);
299
300
0
    scr.ptr = rp - 1;
301
0
    scr.limit = rl - 1;
302
0
    scw.ptr = wp - 1;
303
0
    scw.limit = wl - 1;
304
305
0
    code = s_LZWD_template.process((stream_state*)&state, &scr, &scw, true);
306
0
    if (code == ERRC)
307
0
    {
308
0
        s_LZWD_template.release((stream_state*)&state);
309
0
        return gs_throw1(-1, "error in lzw data (code = %d)", code);
310
0
    }
311
312
0
    s_LZWD_template.release((stream_state*)&state);
313
314
0
    return gs_okay;
315
0
}
316
317
static int
318
xps_decode_tiff_flate(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *rl, byte *wp, byte *wl)
319
0
{
320
0
    stream_zlib_state state;
321
0
    stream_cursor_read scr;
322
0
    stream_cursor_write scw;
323
0
    int code;
324
325
0
    s_init_state((stream_state*)&state, &s_zlibD_template, ctx->memory);
326
0
    state.report_error = xps_report_error;
327
328
0
    s_zlibD_template.set_defaults((stream_state*)&state);
329
330
0
    s_zlibD_template.init((stream_state*)&state);
331
332
0
    scr.ptr = rp - 1;
333
0
    scr.limit = rl - 1;
334
0
    scw.ptr = wp - 1;
335
0
    scw.limit = wl - 1;
336
337
0
    code = s_zlibD_template.process((stream_state*)&state, &scr, &scw, true);
338
0
    if (code == ERRC)
339
0
    {
340
0
        s_zlibD_template.release((stream_state*)&state);
341
0
        return gs_throw1(-1, "error in flate data (code = %d)", code);
342
0
    }
343
344
0
    s_zlibD_template.release((stream_state*)&state);
345
0
    return gs_okay;
346
0
}
347
348
static int
349
xps_decode_tiff_fax(xps_context_t *ctx, xps_tiff_t *tiff, int comp, byte *rp, byte *rl, byte *wp, byte *wl)
350
0
{
351
0
    stream_CFD_state state;
352
0
    stream_cursor_read scr;
353
0
    stream_cursor_write scw;
354
0
    int code;
355
356
0
    s_init_state((stream_state*)&state, &s_CFD_template, ctx->memory);
357
0
    state.report_error = xps_report_error;
358
359
0
    s_CFD_template.set_defaults((stream_state*)&state);
360
361
0
    state.EndOfLine = false;
362
0
    state.EndOfBlock = false;
363
0
    state.Columns = tiff->imagewidth;
364
0
    state.Rows = tiff->imagelength;
365
0
    state.BlackIs1 = tiff->photometric == 0;
366
367
0
    state.K = 0;
368
0
    if (comp == 4)
369
0
        state.K = -1;
370
0
    if (comp == 2)
371
0
        state.EncodedByteAlign = true;
372
373
0
    s_CFD_template.init((stream_state*)&state);
374
375
0
    scr.ptr = rp - 1;
376
0
    scr.limit = rl - 1;
377
0
    scw.ptr = wp - 1;
378
0
    scw.limit = wl - 1;
379
380
0
    code = s_CFD_template.process((stream_state*)&state, &scr, &scw, true);
381
0
    if (code == ERRC)
382
0
    {
383
0
        s_CFD_template.release((stream_state*)&state);
384
0
        return gs_throw1(-1, "error in fax data (code = %d)", code);
385
0
    }
386
387
0
    s_CFD_template.release((stream_state*)&state);
388
0
    return gs_okay;
389
0
}
390
391
/*
392
 * We need more find control over JPEG decoding parameters than
393
 * the s_DCTD_template filter will give us. So we abuse the
394
 * filter, and take control after the filter setup (which sets up
395
 * the memory manager and error handling) and call the gs_jpeg
396
 * wrappers directly for doing the actual decoding.
397
 */
398
399
static int
400
xps_decode_tiff_jpeg(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *rl, byte *wp, byte *wl)
401
0
{
402
0
    stream_DCT_state state; /* used by gs_jpeg_* wrappers */
403
0
    jpeg_decompress_data jddp;
404
0
    struct jpeg_source_mgr *srcmgr;
405
0
    JSAMPROW scanlines[1];
406
0
    int stride;
407
0
    int code;
408
409
    /*
410
     * Set up the JPEG and DCT filter voodoo.
411
     */
412
413
0
    s_init_state((stream_state*)&state, &s_DCTD_template, ctx->memory);
414
0
    state.report_error = xps_report_error;
415
0
    s_DCTD_template.set_defaults((stream_state*)&state);
416
417
0
    state.jpeg_memory = ctx->memory;
418
0
    state.data.decompress = &jddp;
419
420
0
    jddp.templat = s_DCTD_template;
421
0
    jddp.memory = ctx->memory;
422
0
    jddp.scanline_buffer = NULL;
423
0
    jddp.PassThrough = 0;
424
0
    jddp.PassThroughfn = 0;
425
0
    jddp.device = (void *)0;
426
427
0
    if ((code = gs_jpeg_create_decompress(&state)) < 0)
428
0
        return gs_throw(-1, "error in gs_jpeg_create_decompress");
429
430
0
    s_DCTD_template.init((stream_state*)&state);
431
432
0
    srcmgr = jddp.dinfo.src;
433
434
    /*
435
     * Read the abbreviated table file.
436
     */
437
438
0
    if (tiff->jpegtables)
439
0
    {
440
0
        srcmgr->next_input_byte = tiff->jpegtables;
441
0
        srcmgr->bytes_in_buffer = tiff->jpegtableslen;
442
443
0
        code = gs_jpeg_read_header(&state, FALSE);
444
0
        if (code != JPEG_HEADER_TABLES_ONLY)
445
0
            return gs_throw(-1, "error in jpeg table data");
446
0
    }
447
448
    /*
449
     * Read the image jpeg header.
450
     */
451
452
0
    srcmgr->next_input_byte = rp;
453
0
    srcmgr->bytes_in_buffer = rl - rp;
454
455
0
    if ((code = gs_jpeg_read_header(&state, TRUE)) < 0)
456
0
        return gs_throw(-1, "error in jpeg_read_header");
457
458
    /* when TIFF says RGB and libjpeg says YCbCr, libjpeg is wrong */
459
0
    if (tiff->photometric == 2 && jddp.dinfo.jpeg_color_space == JCS_YCbCr)
460
0
    {
461
0
        jddp.dinfo.jpeg_color_space = JCS_RGB;
462
0
    }
463
464
    /*
465
     * Decode the strip image data.
466
     */
467
468
0
    if ((code = gs_jpeg_start_decompress(&state)) < 0)
469
0
        return gs_throw(-1, "error in jpeg_start_decompress");
470
471
0
    stride = jddp.dinfo.output_width * jddp.dinfo.output_components;
472
473
0
    while (wp + stride <= wl && jddp.dinfo.output_scanline < jddp.dinfo.output_height)
474
0
    {
475
0
        scanlines[0] = wp;
476
0
        code = gs_jpeg_read_scanlines(&state, scanlines, 1);
477
0
        if (code < 0)
478
0
            return gs_throw(01, "error in jpeg_read_scanlines");
479
0
        wp += stride;
480
0
    }
481
482
    /*
483
     * Clean up.
484
     */
485
486
0
    if ((code = gs_jpeg_finish_decompress(&state)) < 0)
487
0
        return gs_throw(-1, "error in jpeg_finish_decompress");
488
489
0
    gs_jpeg_destroy(&state);
490
491
0
    return gs_okay;
492
0
}
493
494
static inline int
495
getcomp(byte *line, size_t x, int bpc)
496
0
{
497
0
    switch (bpc)
498
0
    {
499
0
    case 1: return line[x / 8] >> (7 - (x % 8)) & 0x01;
500
0
    case 2: return line[x / 4] >> ((3 - (x % 4)) * 2) & 0x03;
501
0
    case 4: return line[x / 2] >> ((1 - (x % 2)) * 4) & 0x0f;
502
0
    case 8: return line[x];
503
0
    case 16: return ((line[x * 2 + 0]) << 8) | (line[x * 2 + 1]);
504
0
    }
505
0
    return 0;
506
0
}
507
508
static inline void
509
putcomp(byte *line, size_t x, int bpc, int value)
510
0
{
511
0
    int maxval = (1 << bpc) - 1;
512
513
    /* clear bits first  */
514
0
    switch (bpc)
515
0
    {
516
0
    case 1: line[x / 8] &= ~(maxval << (7 - (x % 8))); break;
517
0
    case 2: line[x / 4] &= ~(maxval << ((3 - (x % 4)) * 2)); break;
518
0
    case 4: line[x / 2] &= ~(maxval << ((1 - (x % 2)) * 4)); break;
519
0
    }
520
521
0
    switch (bpc)
522
0
    {
523
0
    case 1: line[x / 8] |= value << (7 - (x % 8)); break;
524
0
    case 2: line[x / 4] |= value << ((3 - (x % 4)) * 2); break;
525
0
    case 4: line[x / 2] |= value << ((1 - (x % 2)) * 4); break;
526
0
    case 8: line[x] = value; break;
527
0
    case 16: line[x * 2 + 0] = value >> 8; line[x * 2 + 1] = value & 0xFF; break;
528
0
    }
529
0
}
530
531
static void
532
xps_unpredict_tiff(byte *line, int width, int comps, int bits)
533
0
{
534
0
    byte left[32];
535
0
    int i, k, v;
536
537
0
    for (k = 0; k < comps; k++)
538
0
        left[k] = 0;
539
540
0
    for (i = 0; i < width; i++)
541
0
    {
542
0
        for (k = 0; k < comps; k++)
543
0
        {
544
0
            v = getcomp(line, (size_t)i * comps + k, bits);
545
0
            v = v + left[k];
546
0
            v = v % (1 << bits);
547
0
            putcomp(line, (size_t)i * comps + k, bits, v);
548
0
            left[k] = v;
549
0
        }
550
0
    }
551
0
}
552
553
static void
554
xps_unassocalpha_tiff(byte *line, int width, int comps, int bits)
555
0
{
556
0
    int i, k, v, a;
557
0
    int m = (1 << bits) - 1;
558
559
0
    for (i = 0; i < width; i++)
560
0
    {
561
0
        a = getcomp(line, (size_t)i * comps + (comps - 1), bits);
562
0
        for (k = 0; k < (comps - 1); k++)
563
0
        {
564
0
            if (a > 0)
565
0
            {
566
0
                v = getcomp(line, (size_t)i * comps + k, bits);
567
0
                v = (v * m) / a;
568
0
                putcomp(line, (size_t)i * comps + k, bits, v);
569
0
            }
570
0
        }
571
0
    }
572
0
}
573
574
static void
575
xps_invert_tiff(byte *line, int width, int comps, int bits, int alpha)
576
0
{
577
0
    int i, k, v;
578
0
    int m = (1 << bits) - 1;
579
580
0
    for (i = 0; i < width; i++)
581
0
    {
582
0
        for (k = 0; k < comps; k++)
583
0
        {
584
0
            v = getcomp(line, (size_t)i * comps + k, bits);
585
0
            if (!alpha || k < comps - 1)
586
0
                v = m - v;
587
0
            putcomp(line, (size_t)i * comps + k, bits, v);
588
0
        }
589
0
    }
590
0
}
591
592
static int
593
xps_expand_colormap(xps_context_t *ctx, xps_tiff_t *tiff, xps_image_t *image)
594
0
{
595
0
    int maxval = 1 << image->bits;
596
0
    byte *samples;
597
0
    byte *src, *dst;
598
0
    int x, y;
599
0
    uint32_t stride, size;
600
601
    /* colormap has first all red, then all green, then all blue values */
602
    /* colormap values are 0..65535, bits is 4 or 8 */
603
    /* image can be with or without extrasamples: comps is 1 or 2 */
604
605
0
    if (image->comps != 1 && image->comps != 2)
606
0
        return gs_throw(-1, "invalid number of samples for RGBPal");
607
608
0
    if (image->bits != 1 && image->bits != 4 && image->bits != 8)
609
0
        return gs_throw(-1, "invalid number of bits for RGBPal");
610
611
0
    if (check_uint32_multiply((uint32_t)image->width, ((uint32_t)image->comps + 2), &stride) != 0)
612
0
        return gs_throw(gs_error_limitcheck, "image is too large");
613
614
0
    if (check_uint32_multiply((uint32_t)image->height, stride, &size) != 0)
615
0
        return gs_throw(gs_error_limitcheck, "image is too large");
616
617
0
    samples = xps_alloc(ctx, (size_t)stride * image->height);
618
0
    if (!samples)
619
0
        return gs_throw(gs_error_VMerror, "out of memory: samples");
620
621
0
    for (y = 0; y < image->height; y++)
622
0
    {
623
0
        src = image->samples + ((size_t)image->stride * y);
624
0
        dst = samples + ((size_t)stride * y);
625
626
0
        for (x = 0; x < image->width; x++)
627
0
        {
628
0
            if (tiff->extrasamples)
629
0
            {
630
0
                int c = getcomp(src, (size_t)x * 2, image->bits);
631
0
                int a = getcomp(src, (size_t)x * 2 + 1, image->bits);
632
0
                *dst++ = tiff->colormap[c + 0] >> 8;
633
0
                *dst++ = tiff->colormap[c + maxval] >> 8;
634
0
                *dst++ = tiff->colormap[c + maxval * 2] >> 8;
635
0
                *dst++ = a << (8 - image->bits);
636
0
            }
637
0
            else
638
0
            {
639
0
                int c = getcomp(src, (size_t)x, image->bits);
640
0
                *dst++ = tiff->colormap[c + 0] >> 8;
641
0
                *dst++ = tiff->colormap[c + maxval] >> 8;
642
0
                *dst++ = tiff->colormap[c + maxval * 2] >> 8;
643
0
            }
644
0
        }
645
0
    }
646
647
0
    image->bits = 8;
648
0
    image->stride = stride;
649
0
    image->samples = samples;
650
651
0
    return gs_okay;
652
0
}
653
654
static int
655
xps_decode_tiff_strips(xps_context_t *ctx, xps_tiff_t *tiff, xps_image_t *image)
656
2
{
657
2
    int error;
658
659
    /* switch on compression to create a filter */
660
    /* feed each strip to the filter */
661
    /* read out the data and pack the samples into an xps_image */
662
663
    /* type 32773 / packbits -- nothing special (same row-padding as PDF) */
664
    /* type 2 / ccitt rle -- no EOL, no RTC, rows are byte-aligned */
665
    /* type 3 and 4 / g3 and g4 -- each strip starts new section */
666
    /* type 5 / lzw -- each strip is handled separately */
667
668
2
    byte *wp;
669
2
    uint32_t row;
670
2
    unsigned strip;
671
2
    unsigned i;
672
2
    int64_t stride_bits;
673
2
    gs_color_space *old_cs;
674
675
2
    if (!tiff->rowsperstrip || !tiff->stripoffsets || !tiff->rowsperstrip)
676
0
        return gs_throw(-1, "no image data in tiff; maybe it is tiled");
677
678
2
    if (tiff->planar != 1)
679
0
        return gs_throw(-1, "image data is not in chunky format");
680
681
2
    if (tiff->imagewidth > (unsigned int)INT_MAX || tiff->imagelength > (unsigned int)INT_MAX)
682
0
        return gs_throw(-1, "image is too large");
683
684
2
    image->width = tiff->imagewidth;
685
2
    image->height = tiff->imagelength;
686
2
    image->comps = tiff->samplesperpixel;
687
2
    image->bits = tiff->bitspersample;
688
2
    if (image->width <= 0 || image->height <= 0 || image->comps <= 0 || image->bits <= 0)
689
0
        return gs_throw(-1, "bad image dimension");
690
691
2
    if (check_64bit_multiply(image->width, image->comps, &stride_bits) ||
692
2
        check_64bit_multiply(stride_bits, image->bits, &stride_bits))
693
0
        return gs_throw(-1, "image is too large");
694
2
    stride_bits = (stride_bits + 7) / 8;
695
2
    if (stride_bits > (int64_t)INT_MAX)
696
0
        return gs_throw(-1, "image is too large");
697
2
    image->stride = (int)stride_bits;
698
2
    image->invert_decode = false;
699
700
2
    old_cs = image->colorspace;
701
2
    switch (tiff->photometric)
702
2
    {
703
0
    case 0: /* WhiteIsZero -- inverted */
704
0
        image->colorspace = ctx->gray;
705
0
        break;
706
0
    case 1: /* BlackIsZero */
707
0
        image->colorspace = ctx->gray;
708
0
        break;
709
2
    case 2: /* RGB */
710
2
        image->colorspace = ctx->srgb;
711
2
        break;
712
0
    case 3: /* RGBPal */
713
0
        image->colorspace = ctx->srgb;
714
0
        break;
715
0
    case 5: /* CMYK */
716
0
        image->colorspace = ctx->cmyk;
717
0
        break;
718
0
    case 6: /* YCbCr */
719
        /* it's probably a jpeg ... we let jpeg convert to rgb */
720
0
        image->colorspace = ctx->srgb;
721
0
        break;
722
0
    default:
723
0
        return gs_throw1(-1, "unknown photometric: %d", tiff->photometric);
724
2
    }
725
2
    rc_increment(image->colorspace);
726
2
    rc_decrement(old_cs, "xps_decode_tiff_strips");
727
728
2
    switch (tiff->resolutionunit)
729
2
    {
730
2
    case 2:
731
2
        image->xres = tiff->xresolution;
732
2
        image->yres = tiff->yresolution;
733
2
        break;
734
0
    case 3:
735
0
        image->xres = (int)(tiff->xresolution * 2.54 + 0.5);
736
0
        image->yres = (int)(tiff->yresolution * 2.54 + 0.5);
737
738
0
        break;
739
0
    default:
740
0
        image->xres = 96;
741
0
        image->yres = 96;
742
0
        break;
743
2
    }
744
745
    /* Note xres and yres could be 0 even if unit was set. If so default to 96dpi */
746
2
    if (image->xres == 0 || image->yres == 0)
747
2
    {
748
2
        image->xres = 96;
749
2
        image->yres = 96;
750
2
    }
751
752
2
    if (check_uint32_multiply((uint32_t)image->stride, (uint32_t)image->height, &row) != 0)
753
0
        return gs_throw(-1, "image row is too large");
754
755
2
    image->samples = xps_alloc(ctx, (size_t)row);
756
2
    if (!image->samples)
757
0
        return gs_throw(gs_error_VMerror, "could not allocate image samples");
758
759
2
    memset(image->samples, 0x55, (size_t)row);
760
761
2
    wp = image->samples;
762
763
2
    strip = 0;
764
4
    for (row = 0; row < tiff->imagelength; row += tiff->rowsperstrip)
765
2
    {
766
2
        unsigned offset, rlen, wlen;
767
2
        byte *rp;
768
769
2
        if (strip >= tiff->stripcount)
770
0
            return gs_throw(-1, "strip index exceeds strip offsets array size");
771
772
2
        offset = tiff->stripoffsets[strip];
773
2
        rlen = tiff->stripbytecounts[strip];
774
2
        wlen = image->stride * tiff->rowsperstrip;
775
2
        rp = tiff->bp + offset;
776
777
2
        if (wp + wlen > image->samples + (size_t)image->stride * image->height)
778
0
            wlen = image->samples + (size_t)image->stride * image->height - wp;
779
780
2
        if (rp + rlen > tiff->ep)
781
0
            return gs_throw(-1, "strip extends beyond the end of the file");
782
783
        /* the bits are in un-natural order */
784
2
        if (tiff->fillorder == 2)
785
0
            for (i = 0; i < rlen; i++)
786
0
                rp[i] = bitrev[rp[i]];
787
788
2
        switch (tiff->compression)
789
2
        {
790
2
        case 1:
791
2
            error = xps_decode_tiff_uncompressed(ctx, tiff, rp, rp + rlen, wp, wp + wlen);
792
2
            break;
793
0
        case 2:
794
0
            error = xps_decode_tiff_fax(ctx, tiff, 2, rp, rp + rlen, wp, wp + wlen);
795
0
            break;
796
0
        case 3:
797
0
            error = xps_decode_tiff_fax(ctx, tiff, 3, rp, rp + rlen, wp, wp + wlen);
798
0
            break;
799
0
        case 4:
800
0
            error = xps_decode_tiff_fax(ctx, tiff, 4, rp, rp + rlen, wp, wp + wlen);
801
0
            break;
802
0
        case 5:
803
0
            error = xps_decode_tiff_lzw(ctx, tiff, rp, rp + rlen, wp, wp + wlen);
804
0
            break;
805
0
        case 6:
806
0
            error = gs_throw(-1, "deprecated JPEG in TIFF compression not supported");
807
0
            break;
808
0
        case 7:
809
0
            error = xps_decode_tiff_jpeg(ctx, tiff, rp, rp + rlen, wp, wp + wlen);
810
0
            break;
811
0
        case 8:
812
0
            error = xps_decode_tiff_flate(ctx, tiff, rp, rp + rlen, wp, wp + wlen);
813
0
            break;
814
0
        case 32773:
815
0
            error = xps_decode_tiff_packbits(ctx, tiff, rp, rp + rlen, wp, wp + wlen);
816
0
            break;
817
0
        default:
818
0
            error = gs_throw1(-1, "unknown TIFF compression: %d", tiff->compression);
819
2
        }
820
821
2
        if (error)
822
0
            return gs_rethrow1(error, "could not decode strip %d", row / tiff->rowsperstrip);
823
824
        /* scramble the bits back into original order */
825
2
        if (tiff->fillorder == 2)
826
0
            for (i = 0; i < rlen; i++)
827
0
                rp[i] = bitrev[rp[i]];
828
829
2
        wp += (size_t)image->stride * tiff->rowsperstrip;
830
2
        strip ++;
831
2
    }
832
833
    /* Predictor (only for LZW and Flate) */
834
2
    if ((tiff->compression == 5 || tiff->compression == 8) && tiff->predictor == 2)
835
0
    {
836
0
        byte *p = image->samples;
837
0
        for (i = 0; i < image->height; i++)
838
0
        {
839
0
            xps_unpredict_tiff(p, image->width, tiff->samplesperpixel, image->bits);
840
0
            p += image->stride;
841
0
        }
842
0
    }
843
844
    /* RGBPal */
845
2
    if (tiff->photometric == 3 && tiff->colormap)
846
0
    {
847
0
        if (tiff->colormap_max != (3<<tiff->bitspersample))
848
0
            return gs_rethrow(-1, "colormap too short for image");
849
850
0
        error = xps_expand_colormap(ctx, tiff, image);
851
0
        if (error)
852
0
            return gs_rethrow(error, "could not expand colormap");
853
0
    }
854
855
    /* B&W with palette */
856
2
    if (tiff->photometric == 1 && tiff->colormap)
857
0
    {
858
0
        if (tiff->colormap_max != (3<<tiff->bitspersample))
859
0
            return gs_rethrow(-1, "colormap too short for image");
860
861
0
        error = xps_expand_colormap(ctx, tiff, image);
862
0
        if (error)
863
0
            return gs_rethrow(error, "could not expand colormap");
864
0
    }
865
866
    /* WhiteIsZero .. invert */
867
2
    if (tiff->photometric == 0)
868
0
    {
869
0
        byte *p = image->samples;
870
0
        for (i = 0; i < image->height; i++)
871
0
        {
872
0
            xps_invert_tiff(p, image->width, image->comps, image->bits, tiff->extrasamples);
873
0
            p += image->stride;
874
0
        }
875
0
    }
876
877
    /* Premultiplied transparency */
878
2
    if (tiff->extrasamples == 1)
879
0
    {
880
        /* We have to unassociate the alpha with the image data in this case */
881
        /* otherwise it is applied twice */
882
0
        byte *p = image->samples;
883
0
        for (i = 0; i < image->height; i++)
884
0
        {
885
0
            xps_unassocalpha_tiff(p, image->width, image->comps, image->bits);
886
0
            p += image->stride;
887
0
        }
888
0
        image->hasalpha = 1;
889
0
    }
890
891
    /* Non-pre-multiplied transparency */
892
2
    if (tiff->extrasamples == 2)
893
0
    {
894
0
        image->hasalpha = 1;
895
0
    }
896
897
2
    return gs_okay;
898
2
}
899
900
static int
901
xps_read_tiff_bytes(unsigned char *p, xps_tiff_t *tiff, unsigned ofs, unsigned n)
902
0
{
903
0
    int code;
904
0
    tiff->rp = tiff->bp + ofs;
905
0
    if (tiff->rp > tiff->ep)
906
0
        tiff->rp = tiff->bp;
907
908
0
    while (n--)
909
0
    {
910
0
        unsigned int v;
911
0
        code = readbyte(tiff, &v);
912
0
        if (code < 0)
913
0
            return code;
914
0
        *p++ = v;
915
0
    }
916
0
    return 0;
917
0
}
918
919
static int
920
xps_read_tiff_tag_value(unsigned *p, xps_tiff_t *tiff, unsigned type, unsigned ofs, unsigned n)
921
40
{
922
40
    int code;
923
40
    unsigned int v, u;
924
40
    tiff->rp = tiff->bp + ofs;
925
40
    if (tiff->rp > tiff->ep)
926
0
        tiff->rp = tiff->bp;
927
928
80
    while (n--)
929
40
    {
930
40
        switch (type)
931
40
        {
932
0
        case TRATIONAL:
933
0
            code = readlong(tiff, &v);
934
0
            if (code < 0)
935
0
                return code;
936
0
            code = readlong(tiff, &u);
937
0
            if (code < 0)
938
0
                return code;
939
0
            *p = v / u;
940
0
            p++;
941
0
            break;
942
0
        case TBYTE:
943
0
            code = readbyte(tiff, p++);
944
0
            if (code < 0)
945
0
                return code;
946
0
            break;
947
32
        case TSHORT:
948
32
            code = readshort(tiff, p++);
949
32
            if (code < 0)
950
0
                return code;
951
32
            break;
952
32
        case TLONG:
953
8
            code = readlong(tiff, p++);
954
8
            if (code < 0)
955
0
                return code;
956
8
            break;
957
8
        default:
958
0
            *p++ = 0;
959
0
            break;
960
40
        }
961
40
    }
962
40
    return 0;
963
40
}
964
965
966
static void *
967
xps_alloc_table(void **table, xps_context_t *ctx, size_t size)
968
8
{
969
8
    if (*table)
970
8
        xps_free(ctx, *table);
971
8
    *table = NULL;
972
8
    *table = xps_alloc(ctx, size);
973
974
8
    return *table;
975
8
}
976
977
static int
978
xps_read_tiff_tag(xps_context_t *ctx, xps_tiff_t *tiff, unsigned offset)
979
44
{
980
44
    int code = 0;
981
44
    unsigned tag;
982
44
    unsigned type;
983
44
    unsigned count;
984
44
    unsigned value;
985
986
44
    tiff->rp = tiff->bp + offset;
987
988
44
    code = readshort(tiff, &tag);
989
44
    if (code < 0)
990
0
        return code;
991
44
    code = readshort(tiff, &type);
992
44
    if (code < 0)
993
0
        return code;
994
44
    code = readlong(tiff, &count);
995
44
    if (code < 0)
996
0
        return code;
997
998
44
    if ((type == TBYTE && count <= 4) ||
999
44
            (type == TSHORT && count <= 2) ||
1000
12
            (type == TLONG && count <= 1))
1001
40
        value = tiff->rp - tiff->bp;
1002
4
    else {
1003
4
        code = readlong(tiff, &value);
1004
4
        if (code < 0)
1005
0
            return code;
1006
4
    }
1007
1008
44
    switch (tag)
1009
44
    {
1010
0
    case NewSubfileType:
1011
0
        code = xps_read_tiff_tag_value(&tiff->subfiletype, tiff, type, value, 1);
1012
0
        break;
1013
4
    case ImageWidth:
1014
4
        code = xps_read_tiff_tag_value(&tiff->imagewidth, tiff, type, value, 1);
1015
4
        break;
1016
4
    case ImageLength:
1017
4
        code = xps_read_tiff_tag_value(&tiff->imagelength, tiff, type, value, 1);
1018
4
        break;
1019
4
    case BitsPerSample:
1020
4
        code = xps_read_tiff_tag_value(&tiff->bitspersample, tiff, type, value, 1);
1021
4
        break;
1022
4
    case Compression:
1023
4
        code = xps_read_tiff_tag_value(&tiff->compression, tiff, type, value, 1);
1024
4
        break;
1025
4
    case PhotometricInterpretation:
1026
4
        code = xps_read_tiff_tag_value(&tiff->photometric, tiff, type, value, 1);
1027
4
        break;
1028
0
    case FillOrder:
1029
0
        code = xps_read_tiff_tag_value(&tiff->fillorder, tiff, type, value, 1);
1030
0
        break;
1031
4
    case SamplesPerPixel:
1032
4
        code = xps_read_tiff_tag_value(&tiff->samplesperpixel, tiff, type, value, 1);
1033
4
        break;
1034
4
    case RowsPerStrip:
1035
4
        code = xps_read_tiff_tag_value(&tiff->rowsperstrip, tiff, type, value, 1);
1036
4
        break;
1037
0
    case XResolution:
1038
0
        code = xps_read_tiff_tag_value(&tiff->xresolution, tiff, type, value, 1);
1039
0
        break;
1040
0
    case YResolution:
1041
0
        code = xps_read_tiff_tag_value(&tiff->yresolution, tiff, type, value, 1);
1042
0
        break;
1043
4
    case PlanarConfiguration:
1044
4
        code = xps_read_tiff_tag_value(&tiff->planar, tiff, type, value, 1);
1045
4
        break;
1046
0
    case T4Options:
1047
0
        code = xps_read_tiff_tag_value(&tiff->g3opts, tiff, type, value, 1);
1048
0
        break;
1049
0
    case T6Options:
1050
0
        code = xps_read_tiff_tag_value(&tiff->g4opts, tiff, type, value, 1);
1051
0
        break;
1052
0
    case Predictor:
1053
0
        code = xps_read_tiff_tag_value(&tiff->predictor, tiff, type, value, 1);
1054
0
        break;
1055
0
    case ResolutionUnit:
1056
0
        code = xps_read_tiff_tag_value(&tiff->resolutionunit, tiff, type, value, 1);
1057
0
        break;
1058
0
    case YCbCrSubSampling:
1059
0
        code = xps_read_tiff_tag_value(tiff->ycbcrsubsamp, tiff, type, value, 2);
1060
0
        break;
1061
0
    case ExtraSamples:
1062
0
        code = xps_read_tiff_tag_value(&tiff->extrasamples, tiff, type, value, 1);
1063
0
        break;
1064
0
    case ICCProfile:
1065
0
        if (!xps_alloc_table((void **)&tiff->profile, ctx, count))
1066
0
            return gs_throw(gs_error_VMerror, "could not allocate embedded icc profile");
1067
        /* ICC profile data type is set to UNDEFINED.
1068
         * TBYTE reading not correct in xps_read_tiff_tag_value */
1069
0
        code = xps_read_tiff_bytes(tiff->profile, tiff, value, count);
1070
0
        if (code < 0)
1071
0
            return code;
1072
0
        tiff->profilesize = count;
1073
0
        break;
1074
1075
0
    case JPEGTables:
1076
0
        if (tiff->bp + value < tiff->bp || tiff->bp + value + count > tiff->ep)
1077
0
            return gs_throw(gs_error_unknownerror, "JPEGTables out of bounds");
1078
0
        tiff->jpegtables = tiff->bp + value;
1079
0
        tiff->jpegtableslen = count;
1080
0
        break;
1081
1082
4
    case StripOffsets:
1083
4
        if (count > INT_MAX / sizeof(unsigned))
1084
0
            return gs_throw(gs_error_limitcheck, "could not allocate strip offsets");
1085
4
        if (!xps_alloc_table((void **)&tiff->stripoffsets, ctx, (size_t)count * sizeof(unsigned)))
1086
0
            return gs_throw(gs_error_VMerror, "could not allocate strip offsets");
1087
4
        code = xps_read_tiff_tag_value(tiff->stripoffsets, tiff, type, value, count);
1088
4
        tiff->stripcount = count;
1089
4
        break;
1090
1091
4
    case StripByteCounts:
1092
4
        if (count > INT_MAX / sizeof(unsigned))
1093
0
            return gs_throw(gs_error_limitcheck, "could not allocate strip offsets");
1094
4
        if (!xps_alloc_table((void **)&tiff->stripbytecounts, ctx, (size_t)count * sizeof(unsigned)))
1095
0
            return gs_throw(gs_error_VMerror, "could not allocate strip byte counts");
1096
4
        code = xps_read_tiff_tag_value(tiff->stripbytecounts, tiff, type, value, count);
1097
4
        break;
1098
1099
0
    case ColorMap:
1100
0
        if (count > INT_MAX / sizeof(unsigned))
1101
0
            return gs_throw(gs_error_limitcheck, "could not allocate strip offsets");
1102
0
        if (!xps_alloc_table((void **)&tiff->colormap, ctx, (size_t)count * sizeof(unsigned)))
1103
0
            return gs_throw(gs_error_VMerror, "could not allocate color map");
1104
0
        tiff->colormap_max = count;
1105
0
        code = xps_read_tiff_tag_value(tiff->colormap, tiff, type, value, count);
1106
0
        break;
1107
1108
0
    case TileWidth:
1109
0
    case TileLength:
1110
0
    case TileOffsets:
1111
0
    case TileByteCounts:
1112
0
        return gs_throw(-1, "tiled tiffs not supported");
1113
1114
4
    default:
1115
        /* printf("unknown tag: %d t=%d n=%d\n", tag, type, count); */
1116
4
        break;
1117
44
    }
1118
1119
44
    return code;
1120
44
}
1121
1122
static void
1123
xps_swap_byte_order(byte *buf, int n)
1124
0
{
1125
0
    int i, t;
1126
0
    for (i = 0; i < n; i++)
1127
0
    {
1128
0
        t = buf[i * 2 + 0];
1129
0
        buf[i * 2 + 0] = buf[i * 2 + 1];
1130
0
        buf[i * 2 + 1] = t;
1131
0
    }
1132
0
}
1133
1134
static int
1135
xps_decode_tiff_header(xps_context_t *ctx, xps_tiff_t *tiff, byte *buf, int len)
1136
4
{
1137
4
    int code;
1138
4
    unsigned version;
1139
4
    unsigned offset;
1140
4
    unsigned count;
1141
4
    unsigned i;
1142
4
    int error;
1143
1144
4
    memset(tiff, 0, sizeof(xps_tiff_t));
1145
1146
4
    tiff->bp = buf;
1147
4
    tiff->rp = buf;
1148
4
    tiff->ep = buf + len;
1149
1150
    /* tag defaults, where applicable */
1151
4
    tiff->bitspersample = 1;
1152
4
    tiff->compression = 1;
1153
4
    tiff->samplesperpixel = 1;
1154
4
    tiff->resolutionunit = 2;
1155
4
    tiff->rowsperstrip = 0xFFFFFFFF;
1156
4
    tiff->fillorder = 1;
1157
4
    tiff->planar = 1;
1158
4
    tiff->subfiletype = 0;
1159
4
    tiff->predictor = 1;
1160
4
    tiff->ycbcrsubsamp[0] = 2;
1161
4
    tiff->ycbcrsubsamp[1] = 2;
1162
1163
    /*
1164
     * Read IFH
1165
     */
1166
1167
    /* get byte order marker */
1168
4
    tiff->order = TII;
1169
4
    code = readshort(tiff, &tiff->order);
1170
4
    if (code < 0 || (tiff->order != TII && tiff->order != TMM))
1171
0
        return gs_throw(-1, "not a TIFF file, wrong magic marker");
1172
1173
    /* check version */
1174
4
    code = readshort(tiff, &version);
1175
4
    if (code < 0 || version != 42)
1176
0
        return gs_throw(-1, "not a TIFF file, wrong version marker");
1177
1178
    /* get offset of IFD */
1179
1180
4
    code = readlong(tiff, &offset);
1181
4
    if (code < 0 || offset > len - 2)
1182
0
        return gs_throw(-1, "TIFF IFD offset incorrect");
1183
1184
    /*
1185
     * Read IFD
1186
     */
1187
1188
4
    tiff->rp = tiff->bp + offset;
1189
1190
4
    code = readshort(tiff, &count);
1191
1192
4
    if (code < 0 || (offset > (len - 2 - (count * 12))))
1193
0
        return gs_throw(-1, "TIFF IFD offset incorrect");
1194
1195
4
    offset += 2;
1196
48
    for (i = 0; i < count; i++)
1197
44
    {
1198
44
        error = xps_read_tiff_tag(ctx, tiff, offset);
1199
44
        if (error)
1200
0
            return gs_rethrow(error, "could not read TIFF header tag");
1201
44
        offset += 12;
1202
44
    }
1203
1204
4
    return gs_okay;
1205
4
}
1206
1207
int
1208
xps_decode_tiff(xps_context_t *ctx, byte *buf, int len, xps_image_t *image)
1209
2
{
1210
2
    int error = gs_okay;
1211
2
    xps_tiff_t tiffst;
1212
2
    xps_tiff_t *tiff = &tiffst;
1213
1214
2
    error = xps_decode_tiff_header(ctx, tiff, buf, len);
1215
2
    if (error)
1216
0
    {
1217
0
        gs_rethrow(error, "cannot decode tiff header");
1218
0
        goto cleanup;
1219
0
    }
1220
1221
2
    if (!tiff->stripbytecounts)
1222
0
    {
1223
0
        error = gs_error_unknownerror;
1224
0
        gs_throw(error, "stripbytecounts is NULL");
1225
0
        goto cleanup;
1226
0
    }
1227
1228
    /*
1229
     * Decode the image strips
1230
     */
1231
1232
2
    if (tiff->rowsperstrip > tiff->imagelength)
1233
0
        tiff->rowsperstrip = tiff->imagelength;
1234
1235
2
    if (tiff->bitspersample != 1 && tiff->bitspersample != 4 && tiff->bitspersample != 8 && tiff->bitspersample != 16) {
1236
0
        gs_rethrow(error, "Illegal BitsPerSample in TIFF header");
1237
0
        goto cleanup;
1238
0
    }
1239
1240
2
    if (tiff->samplesperpixel != 1 && tiff->samplesperpixel != 3 && tiff->samplesperpixel != 4 && tiff->samplesperpixel != 5) {
1241
0
        gs_rethrow(error, "Illegal SamplesPerPixel in TIFF header");
1242
0
        goto cleanup;
1243
0
    }
1244
1245
2
    if (tiff->compression < 1 || (tiff->compression > 5 && (tiff->compression != 7 && tiff->compression != 32773))) {
1246
0
        gs_rethrow(error, "Illegal Compression in TIFF header");
1247
0
        goto cleanup;
1248
0
    }
1249
1250
2
    error = xps_decode_tiff_strips(ctx, tiff, image);
1251
2
    if (error) {
1252
0
        gs_rethrow(error, "could not decode image data");
1253
0
        goto cleanup;
1254
0
    }
1255
1256
    /*
1257
     * Byte swap 16-bit images to big endian if necessary.
1258
     */
1259
2
    if (image->bits == 16)
1260
0
    {
1261
0
        if (tiff->order == TII)
1262
0
            xps_swap_byte_order(image->samples, image->width * image->height * image->comps);
1263
0
    }
1264
1265
    /*
1266
     * Save ICC profile data
1267
     */
1268
2
    image->profile = tiff->profile;
1269
2
    image->profilesize = tiff->profilesize;
1270
1271
    /*
1272
     * Clean up scratch memory
1273
     */
1274
2
cleanup:
1275
2
    if (tiff->colormap) xps_free(ctx, tiff->colormap);
1276
2
    if (tiff->stripoffsets) xps_free(ctx, tiff->stripoffsets);
1277
2
    if (tiff->stripbytecounts) xps_free(ctx, tiff->stripbytecounts);
1278
1279
2
    return error;
1280
2
}
1281
1282
int
1283
xps_tiff_has_alpha(xps_context_t *ctx, byte *buf, int len)
1284
2
{
1285
2
    int error;
1286
2
    xps_tiff_t tiffst;
1287
2
    xps_tiff_t *tiff = &tiffst;
1288
1289
2
    error = xps_decode_tiff_header(ctx, tiff, buf, len);
1290
1291
2
    if (tiff->profile) xps_free(ctx, tiff->profile);
1292
2
    if (tiff->colormap) xps_free(ctx, tiff->colormap);
1293
2
    if (tiff->stripoffsets) xps_free(ctx, tiff->stripoffsets);
1294
2
    if (tiff->stripbytecounts) xps_free(ctx, tiff->stripbytecounts);
1295
1296
2
    if (error)
1297
0
    {
1298
0
        gs_catch(error, "cannot decode tiff header");
1299
0
        return 0;
1300
0
    }
1301
1302
2
    return tiff->extrasamples == 2 || tiff->extrasamples == 1;
1303
2
}