Coverage Report

Created: 2026-04-09 07:06

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