Coverage Report

Created: 2026-04-01 07:17

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 stride;
598
0
    int x, y;
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
    stride = image->width * (image->comps + 2);
611
612
0
    samples = xps_alloc(ctx, (size_t)stride * image->height);
613
0
    if (!samples)
614
0
        return gs_throw(gs_error_VMerror, "out of memory: samples");
615
616
0
    for (y = 0; y < image->height; y++)
617
0
    {
618
0
        src = image->samples + ((size_t)image->stride * y);
619
0
        dst = samples + ((size_t)stride * y);
620
621
0
        for (x = 0; x < image->width; x++)
622
0
        {
623
0
            if (tiff->extrasamples)
624
0
            {
625
0
                int c = getcomp(src, (size_t)x * 2, image->bits);
626
0
                int a = getcomp(src, (size_t)x * 2 + 1, image->bits);
627
0
                *dst++ = tiff->colormap[c + 0] >> 8;
628
0
                *dst++ = tiff->colormap[c + maxval] >> 8;
629
0
                *dst++ = tiff->colormap[c + maxval * 2] >> 8;
630
0
                *dst++ = a << (8 - image->bits);
631
0
            }
632
0
            else
633
0
            {
634
0
                int c = getcomp(src, (size_t)x, image->bits);
635
0
                *dst++ = tiff->colormap[c + 0] >> 8;
636
0
                *dst++ = tiff->colormap[c + maxval] >> 8;
637
0
                *dst++ = tiff->colormap[c + maxval * 2] >> 8;
638
0
            }
639
0
        }
640
0
    }
641
642
0
    image->bits = 8;
643
0
    image->stride = stride;
644
0
    image->samples = samples;
645
646
0
    return gs_okay;
647
0
}
648
649
static int
650
xps_decode_tiff_strips(xps_context_t *ctx, xps_tiff_t *tiff, xps_image_t *image)
651
0
{
652
0
    int error;
653
654
    /* switch on compression to create a filter */
655
    /* feed each strip to the filter */
656
    /* read out the data and pack the samples into an xps_image */
657
658
    /* type 32773 / packbits -- nothing special (same row-padding as PDF) */
659
    /* type 2 / ccitt rle -- no EOL, no RTC, rows are byte-aligned */
660
    /* type 3 and 4 / g3 and g4 -- each strip starts new section */
661
    /* type 5 / lzw -- each strip is handled separately */
662
663
0
    byte *wp;
664
0
    uint32_t row;
665
0
    unsigned strip;
666
0
    unsigned i;
667
0
    int64_t stride_bits;
668
0
    gs_color_space *old_cs;
669
670
0
    if (!tiff->rowsperstrip || !tiff->stripoffsets || !tiff->rowsperstrip)
671
0
        return gs_throw(-1, "no image data in tiff; maybe it is tiled");
672
673
0
    if (tiff->planar != 1)
674
0
        return gs_throw(-1, "image data is not in chunky format");
675
676
0
    if (tiff->imagewidth > (unsigned int)INT_MAX || tiff->imagelength > (unsigned int)INT_MAX)
677
0
        return gs_throw(-1, "image is too large");
678
679
0
    image->width = tiff->imagewidth;
680
0
    image->height = tiff->imagelength;
681
0
    image->comps = tiff->samplesperpixel;
682
0
    image->bits = tiff->bitspersample;
683
0
    if (image->width <= 0 || image->height <= 0 || image->comps <= 0 || image->bits <= 0)
684
0
        return gs_throw(-1, "bad image dimension");
685
686
0
    if (check_64bit_multiply(image->width, image->comps, &stride_bits) ||
687
0
        check_64bit_multiply(stride_bits, image->bits, &stride_bits))
688
0
        return gs_throw(-1, "image is too large");
689
0
    stride_bits = (stride_bits + 7) / 8;
690
0
    if (stride_bits > (int64_t)INT_MAX)
691
0
        return gs_throw(-1, "image is too large");
692
0
    image->stride = (int)stride_bits;
693
0
    image->invert_decode = false;
694
695
0
    old_cs = image->colorspace;
696
0
    switch (tiff->photometric)
697
0
    {
698
0
    case 0: /* WhiteIsZero -- inverted */
699
0
        image->colorspace = ctx->gray;
700
0
        break;
701
0
    case 1: /* BlackIsZero */
702
0
        image->colorspace = ctx->gray;
703
0
        break;
704
0
    case 2: /* RGB */
705
0
        image->colorspace = ctx->srgb;
706
0
        break;
707
0
    case 3: /* RGBPal */
708
0
        image->colorspace = ctx->srgb;
709
0
        break;
710
0
    case 5: /* CMYK */
711
0
        image->colorspace = ctx->cmyk;
712
0
        break;
713
0
    case 6: /* YCbCr */
714
        /* it's probably a jpeg ... we let jpeg convert to rgb */
715
0
        image->colorspace = ctx->srgb;
716
0
        break;
717
0
    default:
718
0
        return gs_throw1(-1, "unknown photometric: %d", tiff->photometric);
719
0
    }
720
0
    rc_increment(image->colorspace);
721
0
    rc_decrement(old_cs, "xps_decode_tiff_strips");
722
723
0
    switch (tiff->resolutionunit)
724
0
    {
725
0
    case 2:
726
0
        image->xres = tiff->xresolution;
727
0
        image->yres = tiff->yresolution;
728
0
        break;
729
0
    case 3:
730
0
        image->xres = (int)(tiff->xresolution * 2.54 + 0.5);
731
0
        image->yres = (int)(tiff->yresolution * 2.54 + 0.5);
732
733
0
        break;
734
0
    default:
735
0
        image->xres = 96;
736
0
        image->yres = 96;
737
0
        break;
738
0
    }
739
740
    /* Note xres and yres could be 0 even if unit was set. If so default to 96dpi */
741
0
    if (image->xres == 0 || image->yres == 0)
742
0
    {
743
0
        image->xres = 96;
744
0
        image->yres = 96;
745
0
    }
746
747
0
    if (check_uint32_multiply((uint32_t)image->stride, (uint32_t)image->height, &row) != 0)
748
0
        return gs_throw(-1, "image row is too large");
749
750
0
    image->samples = xps_alloc(ctx, (size_t)row);
751
0
    if (!image->samples)
752
0
        return gs_throw(gs_error_VMerror, "could not allocate image samples");
753
754
0
    memset(image->samples, 0x55, (size_t)row);
755
756
0
    wp = image->samples;
757
758
0
    strip = 0;
759
0
    for (row = 0; row < tiff->imagelength; row += tiff->rowsperstrip)
760
0
    {
761
0
        unsigned offset = tiff->stripoffsets[strip];
762
0
        unsigned rlen = tiff->stripbytecounts[strip];
763
0
        unsigned wlen = image->stride * tiff->rowsperstrip;
764
0
        byte *rp = tiff->bp + offset;
765
766
0
        if (wp + wlen > image->samples + (size_t)image->stride * image->height)
767
0
            wlen = image->samples + (size_t)image->stride * image->height - wp;
768
769
0
        if (rp + rlen > tiff->ep)
770
0
            return gs_throw(-1, "strip extends beyond the end of the file");
771
772
        /* the bits are in un-natural order */
773
0
        if (tiff->fillorder == 2)
774
0
            for (i = 0; i < rlen; i++)
775
0
                rp[i] = bitrev[rp[i]];
776
777
0
        switch (tiff->compression)
778
0
        {
779
0
        case 1:
780
0
            error = xps_decode_tiff_uncompressed(ctx, tiff, rp, rp + rlen, wp, wp + wlen);
781
0
            break;
782
0
        case 2:
783
0
            error = xps_decode_tiff_fax(ctx, tiff, 2, rp, rp + rlen, wp, wp + wlen);
784
0
            break;
785
0
        case 3:
786
0
            error = xps_decode_tiff_fax(ctx, tiff, 3, rp, rp + rlen, wp, wp + wlen);
787
0
            break;
788
0
        case 4:
789
0
            error = xps_decode_tiff_fax(ctx, tiff, 4, rp, rp + rlen, wp, wp + wlen);
790
0
            break;
791
0
        case 5:
792
0
            error = xps_decode_tiff_lzw(ctx, tiff, rp, rp + rlen, wp, wp + wlen);
793
0
            break;
794
0
        case 6:
795
0
            error = gs_throw(-1, "deprecated JPEG in TIFF compression not supported");
796
0
            break;
797
0
        case 7:
798
0
            error = xps_decode_tiff_jpeg(ctx, tiff, rp, rp + rlen, wp, wp + wlen);
799
0
            break;
800
0
        case 8:
801
0
            error = xps_decode_tiff_flate(ctx, tiff, rp, rp + rlen, wp, wp + wlen);
802
0
            break;
803
0
        case 32773:
804
0
            error = xps_decode_tiff_packbits(ctx, tiff, rp, rp + rlen, wp, wp + wlen);
805
0
            break;
806
0
        default:
807
0
            error = gs_throw1(-1, "unknown TIFF compression: %d", tiff->compression);
808
0
        }
809
810
0
        if (error)
811
0
            return gs_rethrow1(error, "could not decode strip %d", row / tiff->rowsperstrip);
812
813
        /* scramble the bits back into original order */
814
0
        if (tiff->fillorder == 2)
815
0
            for (i = 0; i < rlen; i++)
816
0
                rp[i] = bitrev[rp[i]];
817
818
0
        wp += (size_t)image->stride * tiff->rowsperstrip;
819
0
        strip ++;
820
0
    }
821
822
    /* Predictor (only for LZW and Flate) */
823
0
    if ((tiff->compression == 5 || tiff->compression == 8) && tiff->predictor == 2)
824
0
    {
825
0
        byte *p = image->samples;
826
0
        for (i = 0; i < image->height; i++)
827
0
        {
828
0
            xps_unpredict_tiff(p, image->width, tiff->samplesperpixel, image->bits);
829
0
            p += image->stride;
830
0
        }
831
0
    }
832
833
    /* RGBPal */
834
0
    if (tiff->photometric == 3 && tiff->colormap)
835
0
    {
836
0
        if (tiff->colormap_max != (3<<tiff->bitspersample))
837
0
            return gs_rethrow(-1, "colormap too short for image");
838
839
0
        error = xps_expand_colormap(ctx, tiff, image);
840
0
        if (error)
841
0
            return gs_rethrow(error, "could not expand colormap");
842
0
    }
843
844
    /* B&W with palette */
845
0
    if (tiff->photometric == 1 && 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
    /* WhiteIsZero .. invert */
856
0
    if (tiff->photometric == 0)
857
0
    {
858
0
        byte *p = image->samples;
859
0
        for (i = 0; i < image->height; i++)
860
0
        {
861
0
            xps_invert_tiff(p, image->width, image->comps, image->bits, tiff->extrasamples);
862
0
            p += image->stride;
863
0
        }
864
0
    }
865
866
    /* Premultiplied transparency */
867
0
    if (tiff->extrasamples == 1)
868
0
    {
869
        /* We have to unassociate the alpha with the image data in this case */
870
        /* otherwise it is applied twice */
871
0
        byte *p = image->samples;
872
0
        for (i = 0; i < image->height; i++)
873
0
        {
874
0
            xps_unassocalpha_tiff(p, image->width, image->comps, image->bits);
875
0
            p += image->stride;
876
0
        }
877
0
        image->hasalpha = 1;
878
0
    }
879
880
    /* Non-pre-multiplied transparency */
881
0
    if (tiff->extrasamples == 2)
882
0
    {
883
0
        image->hasalpha = 1;
884
0
    }
885
886
0
    return gs_okay;
887
0
}
888
889
static int
890
xps_read_tiff_bytes(unsigned char *p, xps_tiff_t *tiff, unsigned ofs, unsigned n)
891
0
{
892
0
    int code;
893
0
    tiff->rp = tiff->bp + ofs;
894
0
    if (tiff->rp > tiff->ep)
895
0
        tiff->rp = tiff->bp;
896
897
0
    while (n--)
898
0
    {
899
0
        unsigned int v;
900
0
        code = readbyte(tiff, &v);
901
0
        if (code < 0)
902
0
            return code;
903
0
        *p++ = v;
904
0
    }
905
0
    return 0;
906
0
}
907
908
static int
909
xps_read_tiff_tag_value(unsigned *p, xps_tiff_t *tiff, unsigned type, unsigned ofs, unsigned n)
910
0
{
911
0
    int code;
912
0
    unsigned int v, u;
913
0
    tiff->rp = tiff->bp + ofs;
914
0
    if (tiff->rp > tiff->ep)
915
0
        tiff->rp = tiff->bp;
916
917
0
    while (n--)
918
0
    {
919
0
        switch (type)
920
0
        {
921
0
        case TRATIONAL:
922
0
            code = readlong(tiff, &v);
923
0
            if (code < 0)
924
0
                return code;
925
0
            code = readlong(tiff, &u);
926
0
            if (code < 0)
927
0
                return code;
928
0
            *p = v / u;
929
0
            p++;
930
0
            break;
931
0
        case TBYTE:
932
0
            code = readbyte(tiff, p++);
933
0
            if (code < 0)
934
0
                return code;
935
0
            break;
936
0
        case TSHORT:
937
0
            code = readshort(tiff, p++);
938
0
            if (code < 0)
939
0
                return code;
940
0
            break;
941
0
        case TLONG:
942
0
            code = readlong(tiff, p++);
943
0
            if (code < 0)
944
0
                return code;
945
0
            break;
946
0
        default:
947
0
            *p++ = 0;
948
0
            break;
949
0
        }
950
0
    }
951
0
    return 0;
952
0
}
953
954
955
static void *
956
xps_alloc_table(void **table, xps_context_t *ctx, size_t size)
957
0
{
958
0
    if (*table)
959
0
        xps_free(ctx, *table);
960
0
    *table = NULL;
961
0
    *table = xps_alloc(ctx, size);
962
963
0
    return *table;
964
0
}
965
966
static int
967
xps_read_tiff_tag(xps_context_t *ctx, xps_tiff_t *tiff, unsigned offset)
968
0
{
969
0
    int code = 0;
970
0
    unsigned tag;
971
0
    unsigned type;
972
0
    unsigned count;
973
0
    unsigned value;
974
975
0
    tiff->rp = tiff->bp + offset;
976
977
0
    code = readshort(tiff, &tag);
978
0
    if (code < 0)
979
0
        return code;
980
0
    code = readshort(tiff, &type);
981
0
    if (code < 0)
982
0
        return code;
983
0
    code = readlong(tiff, &count);
984
0
    if (code < 0)
985
0
        return code;
986
987
0
    if ((type == TBYTE && count <= 4) ||
988
0
            (type == TSHORT && count <= 2) ||
989
0
            (type == TLONG && count <= 1))
990
0
        value = tiff->rp - tiff->bp;
991
0
    else {
992
0
        code = readlong(tiff, &value);
993
0
        if (code < 0)
994
0
            return code;
995
0
    }
996
997
0
    switch (tag)
998
0
    {
999
0
    case NewSubfileType:
1000
0
        code = xps_read_tiff_tag_value(&tiff->subfiletype, tiff, type, value, 1);
1001
0
        break;
1002
0
    case ImageWidth:
1003
0
        code = xps_read_tiff_tag_value(&tiff->imagewidth, tiff, type, value, 1);
1004
0
        break;
1005
0
    case ImageLength:
1006
0
        code = xps_read_tiff_tag_value(&tiff->imagelength, tiff, type, value, 1);
1007
0
        break;
1008
0
    case BitsPerSample:
1009
0
        code = xps_read_tiff_tag_value(&tiff->bitspersample, tiff, type, value, 1);
1010
0
        break;
1011
0
    case Compression:
1012
0
        code = xps_read_tiff_tag_value(&tiff->compression, tiff, type, value, 1);
1013
0
        break;
1014
0
    case PhotometricInterpretation:
1015
0
        code = xps_read_tiff_tag_value(&tiff->photometric, tiff, type, value, 1);
1016
0
        break;
1017
0
    case FillOrder:
1018
0
        code = xps_read_tiff_tag_value(&tiff->fillorder, tiff, type, value, 1);
1019
0
        break;
1020
0
    case SamplesPerPixel:
1021
0
        code = xps_read_tiff_tag_value(&tiff->samplesperpixel, tiff, type, value, 1);
1022
0
        break;
1023
0
    case RowsPerStrip:
1024
0
        code = xps_read_tiff_tag_value(&tiff->rowsperstrip, tiff, type, value, 1);
1025
0
        break;
1026
0
    case XResolution:
1027
0
        code = xps_read_tiff_tag_value(&tiff->xresolution, tiff, type, value, 1);
1028
0
        break;
1029
0
    case YResolution:
1030
0
        code = xps_read_tiff_tag_value(&tiff->yresolution, tiff, type, value, 1);
1031
0
        break;
1032
0
    case PlanarConfiguration:
1033
0
        code = xps_read_tiff_tag_value(&tiff->planar, tiff, type, value, 1);
1034
0
        break;
1035
0
    case T4Options:
1036
0
        code = xps_read_tiff_tag_value(&tiff->g3opts, tiff, type, value, 1);
1037
0
        break;
1038
0
    case T6Options:
1039
0
        code = xps_read_tiff_tag_value(&tiff->g4opts, tiff, type, value, 1);
1040
0
        break;
1041
0
    case Predictor:
1042
0
        code = xps_read_tiff_tag_value(&tiff->predictor, tiff, type, value, 1);
1043
0
        break;
1044
0
    case ResolutionUnit:
1045
0
        code = xps_read_tiff_tag_value(&tiff->resolutionunit, tiff, type, value, 1);
1046
0
        break;
1047
0
    case YCbCrSubSampling:
1048
0
        code = xps_read_tiff_tag_value(tiff->ycbcrsubsamp, tiff, type, value, 2);
1049
0
        break;
1050
0
    case ExtraSamples:
1051
0
        code = xps_read_tiff_tag_value(&tiff->extrasamples, tiff, type, value, 1);
1052
0
        break;
1053
0
    case ICCProfile:
1054
0
        if (!xps_alloc_table((void **)&tiff->profile, ctx, count))
1055
0
            return gs_throw(gs_error_VMerror, "could not allocate embedded icc profile");
1056
        /* ICC profile data type is set to UNDEFINED.
1057
         * TBYTE reading not correct in xps_read_tiff_tag_value */
1058
0
        code = xps_read_tiff_bytes(tiff->profile, tiff, value, count);
1059
0
        if (code < 0)
1060
0
            return code;
1061
0
        tiff->profilesize = count;
1062
0
        break;
1063
1064
0
    case JPEGTables:
1065
0
        if (tiff->bp + value < tiff->bp || tiff->bp + value + count > tiff->ep)
1066
0
            return gs_throw(gs_error_unknownerror, "JPEGTables out of bounds");
1067
0
        tiff->jpegtables = tiff->bp + value;
1068
0
        tiff->jpegtableslen = count;
1069
0
        break;
1070
1071
0
    case StripOffsets:
1072
0
        if (!xps_alloc_table((void **)&tiff->stripoffsets, ctx, (size_t)count * sizeof(unsigned)))
1073
0
            return gs_throw(gs_error_VMerror, "could not allocate strip offsets");
1074
0
        code = xps_read_tiff_tag_value(tiff->stripoffsets, tiff, type, value, count);
1075
0
        break;
1076
1077
0
    case StripByteCounts:
1078
0
        if (!xps_alloc_table((void **)&tiff->stripbytecounts, ctx, (size_t)count * sizeof(unsigned)))
1079
0
            return gs_throw(gs_error_VMerror, "could not allocate strip byte counts");
1080
0
        code = xps_read_tiff_tag_value(tiff->stripbytecounts, tiff, type, value, count);
1081
0
        break;
1082
1083
0
    case ColorMap:
1084
0
        if (!xps_alloc_table((void **)&tiff->colormap, ctx, (size_t)count * sizeof(unsigned)))
1085
0
            return gs_throw(gs_error_VMerror, "could not allocate color map");
1086
0
        tiff->colormap_max = count;
1087
0
        code = xps_read_tiff_tag_value(tiff->colormap, tiff, type, value, count);
1088
0
        break;
1089
1090
0
    case TileWidth:
1091
0
    case TileLength:
1092
0
    case TileOffsets:
1093
0
    case TileByteCounts:
1094
0
        return gs_throw(-1, "tiled tiffs not supported");
1095
1096
0
    default:
1097
        /* printf("unknown tag: %d t=%d n=%d\n", tag, type, count); */
1098
0
        break;
1099
0
    }
1100
1101
0
    return code;
1102
0
}
1103
1104
static void
1105
xps_swap_byte_order(byte *buf, int n)
1106
0
{
1107
0
    int i, t;
1108
0
    for (i = 0; i < n; i++)
1109
0
    {
1110
0
        t = buf[i * 2 + 0];
1111
0
        buf[i * 2 + 0] = buf[i * 2 + 1];
1112
0
        buf[i * 2 + 1] = t;
1113
0
    }
1114
0
}
1115
1116
static int
1117
xps_decode_tiff_header(xps_context_t *ctx, xps_tiff_t *tiff, byte *buf, int len)
1118
0
{
1119
0
    int code;
1120
0
    unsigned version;
1121
0
    unsigned offset;
1122
0
    unsigned count;
1123
0
    unsigned i;
1124
0
    int error;
1125
1126
0
    memset(tiff, 0, sizeof(xps_tiff_t));
1127
1128
0
    tiff->bp = buf;
1129
0
    tiff->rp = buf;
1130
0
    tiff->ep = buf + len;
1131
1132
    /* tag defaults, where applicable */
1133
0
    tiff->bitspersample = 1;
1134
0
    tiff->compression = 1;
1135
0
    tiff->samplesperpixel = 1;
1136
0
    tiff->resolutionunit = 2;
1137
0
    tiff->rowsperstrip = 0xFFFFFFFF;
1138
0
    tiff->fillorder = 1;
1139
0
    tiff->planar = 1;
1140
0
    tiff->subfiletype = 0;
1141
0
    tiff->predictor = 1;
1142
0
    tiff->ycbcrsubsamp[0] = 2;
1143
0
    tiff->ycbcrsubsamp[1] = 2;
1144
1145
    /*
1146
     * Read IFH
1147
     */
1148
1149
    /* get byte order marker */
1150
0
    tiff->order = TII;
1151
0
    code = readshort(tiff, &tiff->order);
1152
0
    if (code < 0 || (tiff->order != TII && tiff->order != TMM))
1153
0
        return gs_throw(-1, "not a TIFF file, wrong magic marker");
1154
1155
    /* check version */
1156
0
    code = readshort(tiff, &version);
1157
0
    if (code < 0 || version != 42)
1158
0
        return gs_throw(-1, "not a TIFF file, wrong version marker");
1159
1160
    /* get offset of IFD */
1161
1162
0
    code = readlong(tiff, &offset);
1163
0
    if (code < 0 || offset > len - 2)
1164
0
        return gs_throw(-1, "TIFF IFD offset incorrect");
1165
1166
    /*
1167
     * Read IFD
1168
     */
1169
1170
0
    tiff->rp = tiff->bp + offset;
1171
1172
0
    code = readshort(tiff, &count);
1173
1174
0
    if (code < 0 || (offset > (len - 2 - (count * 12))))
1175
0
        return gs_throw(-1, "TIFF IFD offset incorrect");
1176
1177
0
    offset += 2;
1178
0
    for (i = 0; i < count; i++)
1179
0
    {
1180
0
        error = xps_read_tiff_tag(ctx, tiff, offset);
1181
0
        if (error)
1182
0
            return gs_rethrow(error, "could not read TIFF header tag");
1183
0
        offset += 12;
1184
0
    }
1185
1186
0
    return gs_okay;
1187
0
}
1188
1189
int
1190
xps_decode_tiff(xps_context_t *ctx, byte *buf, int len, xps_image_t *image)
1191
0
{
1192
0
    int error = gs_okay;
1193
0
    xps_tiff_t tiffst;
1194
0
    xps_tiff_t *tiff = &tiffst;
1195
1196
0
    error = xps_decode_tiff_header(ctx, tiff, buf, len);
1197
0
    if (error)
1198
0
    {
1199
0
        gs_rethrow(error, "cannot decode tiff header");
1200
0
        goto cleanup;
1201
0
    }
1202
1203
0
    if (!tiff->stripbytecounts)
1204
0
    {
1205
0
        error = gs_error_unknownerror;
1206
0
        gs_throw(error, "stripbytecounts is NULL");
1207
0
        goto cleanup;
1208
0
    }
1209
1210
    /*
1211
     * Decode the image strips
1212
     */
1213
1214
0
    if (tiff->rowsperstrip > tiff->imagelength)
1215
0
        tiff->rowsperstrip = tiff->imagelength;
1216
1217
0
    if (tiff->bitspersample != 1 && tiff->bitspersample != 4 && tiff->bitspersample != 8 && tiff->bitspersample != 16) {
1218
0
        gs_rethrow(error, "Illegal BitsPerSample in TIFF header");
1219
0
        goto cleanup;
1220
0
    }
1221
1222
0
    if (tiff->samplesperpixel != 1 && tiff->samplesperpixel != 3 && tiff->samplesperpixel != 4 && tiff->samplesperpixel != 5) {
1223
0
        gs_rethrow(error, "Illegal SamplesPerPixel in TIFF header");
1224
0
        goto cleanup;
1225
0
    }
1226
1227
0
    if (tiff->compression < 1 || (tiff->compression > 5 && (tiff->compression != 7 && tiff->compression != 32773))) {
1228
0
        gs_rethrow(error, "Illegal Compression in TIFF header");
1229
0
        goto cleanup;
1230
0
    }
1231
1232
0
    error = xps_decode_tiff_strips(ctx, tiff, image);
1233
0
    if (error) {
1234
0
        gs_rethrow(error, "could not decode image data");
1235
0
        goto cleanup;
1236
0
    }
1237
1238
    /*
1239
     * Byte swap 16-bit images to big endian if necessary.
1240
     */
1241
0
    if (image->bits == 16)
1242
0
    {
1243
0
        if (tiff->order == TII)
1244
0
            xps_swap_byte_order(image->samples, image->width * image->height * image->comps);
1245
0
    }
1246
1247
    /*
1248
     * Save ICC profile data
1249
     */
1250
0
    image->profile = tiff->profile;
1251
0
    image->profilesize = tiff->profilesize;
1252
1253
    /*
1254
     * Clean up scratch memory
1255
     */
1256
0
cleanup:
1257
0
    if (tiff->colormap) xps_free(ctx, tiff->colormap);
1258
0
    if (tiff->stripoffsets) xps_free(ctx, tiff->stripoffsets);
1259
0
    if (tiff->stripbytecounts) xps_free(ctx, tiff->stripbytecounts);
1260
1261
0
    return error;
1262
0
}
1263
1264
int
1265
xps_tiff_has_alpha(xps_context_t *ctx, byte *buf, int len)
1266
0
{
1267
0
    int error;
1268
0
    xps_tiff_t tiffst;
1269
0
    xps_tiff_t *tiff = &tiffst;
1270
1271
0
    error = xps_decode_tiff_header(ctx, tiff, buf, len);
1272
1273
0
    if (tiff->profile) xps_free(ctx, tiff->profile);
1274
0
    if (tiff->colormap) xps_free(ctx, tiff->colormap);
1275
0
    if (tiff->stripoffsets) xps_free(ctx, tiff->stripoffsets);
1276
0
    if (tiff->stripbytecounts) xps_free(ctx, tiff->stripbytecounts);
1277
1278
0
    if (error)
1279
0
    {
1280
0
        gs_catch(error, "cannot decode tiff header");
1281
0
        return 0;
1282
0
    }
1283
1284
0
    return tiff->extrasamples == 2 || tiff->extrasamples == 1;
1285
0
}