Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4680 | right-hear | 1 | #include "fitz.h" |
2 | #include "muxps.h" |
||
3 | |||
4 | /* |
||
5 | * TIFF image loader. Should be enough to support TIFF files in XPS. |
||
6 | * Baseline TIFF 6.0 plus CMYK, LZW, Flate and JPEG support. |
||
7 | * Limited bit depths (1,2,4,8). |
||
8 | * Limited planar configurations (1=chunky). |
||
9 | * No tiles (easy fix if necessary). |
||
10 | * TODO: RGBPal images |
||
11 | */ |
||
12 | |||
13 | struct tiff |
||
14 | { |
||
15 | /* "file" */ |
||
16 | byte *bp, *rp, *ep; |
||
17 | |||
18 | /* byte order */ |
||
19 | unsigned order; |
||
20 | |||
21 | /* where we can find the strips of image data */ |
||
22 | unsigned rowsperstrip; |
||
23 | unsigned *stripoffsets; |
||
24 | unsigned *stripbytecounts; |
||
25 | |||
26 | /* colormap */ |
||
27 | unsigned *colormap; |
||
28 | |||
29 | /* assorted tags */ |
||
30 | unsigned subfiletype; |
||
31 | unsigned photometric; |
||
32 | unsigned compression; |
||
33 | unsigned imagewidth; |
||
34 | unsigned imagelength; |
||
35 | unsigned samplesperpixel; |
||
36 | unsigned bitspersample; |
||
37 | unsigned planar; |
||
38 | unsigned extrasamples; |
||
39 | unsigned xresolution; |
||
40 | unsigned yresolution; |
||
41 | unsigned resolutionunit; |
||
42 | unsigned fillorder; |
||
43 | unsigned g3opts; |
||
44 | unsigned g4opts; |
||
45 | unsigned predictor; |
||
46 | |||
47 | unsigned ycbcrsubsamp[2]; |
||
48 | |||
49 | byte *jpegtables; /* point into "file" buffer */ |
||
50 | unsigned jpegtableslen; |
||
51 | |||
52 | byte *profile; |
||
53 | int profilesize; |
||
54 | |||
55 | /* decoded data */ |
||
56 | fz_colorspace *colorspace; |
||
57 | byte *samples; |
||
58 | int stride; |
||
59 | }; |
||
60 | |||
61 | enum |
||
62 | { |
||
63 | TII = 0x4949, /* 'II' */ |
||
64 | TMM = 0x4d4d, /* 'MM' */ |
||
65 | TBYTE = 1, |
||
66 | TASCII = 2, |
||
67 | TSHORT = 3, |
||
68 | TLONG = 4, |
||
69 | TRATIONAL = 5 |
||
70 | }; |
||
71 | |||
72 | #define NewSubfileType 254 |
||
73 | #define ImageWidth 256 |
||
74 | #define ImageLength 257 |
||
75 | #define BitsPerSample 258 |
||
76 | #define Compression 259 |
||
77 | #define PhotometricInterpretation 262 |
||
78 | #define FillOrder 266 |
||
79 | #define StripOffsets 273 |
||
80 | #define SamplesPerPixel 277 |
||
81 | #define RowsPerStrip 278 |
||
82 | #define StripByteCounts 279 |
||
83 | #define XResolution 282 |
||
84 | #define YResolution 283 |
||
85 | #define PlanarConfiguration 284 |
||
86 | #define T4Options 292 |
||
87 | #define T6Options 293 |
||
88 | #define ResolutionUnit 296 |
||
89 | #define Predictor 317 |
||
90 | #define ColorMap 320 |
||
91 | #define TileWidth 322 |
||
92 | #define TileLength 323 |
||
93 | #define TileOffsets 324 |
||
94 | #define TileByteCounts 325 |
||
95 | #define ExtraSamples 338 |
||
96 | #define JPEGTables 347 |
||
97 | #define YCbCrSubSampling 520 |
||
98 | #define ICCProfile 34675 |
||
99 | |||
100 | static const byte bitrev[256] = |
||
101 | { |
||
102 | 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, |
||
103 | 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, |
||
104 | 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, |
||
105 | 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, |
||
106 | 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, |
||
107 | 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, |
||
108 | 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, |
||
109 | 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, |
||
110 | 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, |
||
111 | 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, |
||
112 | 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, |
||
113 | 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, |
||
114 | 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, |
||
115 | 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, |
||
116 | 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, |
||
117 | 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, |
||
118 | 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, |
||
119 | 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, |
||
120 | 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, |
||
121 | 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, |
||
122 | 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, |
||
123 | 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, |
||
124 | 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, |
||
125 | 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, |
||
126 | 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, |
||
127 | 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, |
||
128 | 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, |
||
129 | 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, |
||
130 | 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, |
||
131 | 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, |
||
132 | 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, |
||
133 | 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff |
||
134 | }; |
||
135 | |||
136 | static int |
||
137 | xps_decode_tiff_uncompressed(struct tiff *tiff, fz_stream *stm, byte *wp, int wlen) |
||
138 | { |
||
139 | int n = fz_read(stm, wp, wlen); |
||
140 | fz_close(stm); |
||
141 | if (n < 0) |
||
142 | return fz_rethrow(n, "cannot read uncompressed strip"); |
||
143 | return fz_okay; |
||
144 | } |
||
145 | |||
146 | static int |
||
147 | xps_decode_tiff_packbits(struct tiff *tiff, fz_stream *chain, byte *wp, int wlen) |
||
148 | { |
||
149 | fz_stream *stm = fz_open_rld(chain); |
||
150 | int n = fz_read(stm, wp, wlen); |
||
151 | fz_close(stm); |
||
152 | if (n < 0) |
||
153 | return fz_rethrow(n, "cannot read packbits strip"); |
||
154 | return fz_okay; |
||
155 | } |
||
156 | |||
157 | static int |
||
158 | xps_decode_tiff_lzw(struct tiff *tiff, fz_stream *chain, byte *wp, int wlen) |
||
159 | { |
||
160 | fz_stream *stm = fz_open_lzwd(chain, NULL); |
||
161 | int n = fz_read(stm, wp, wlen); |
||
162 | fz_close(stm); |
||
163 | if (n < 0) |
||
164 | return fz_rethrow(n, "cannot read lzw strip"); |
||
165 | return fz_okay; |
||
166 | } |
||
167 | static int |
||
168 | xps_decode_tiff_flate(struct tiff *tiff, fz_stream *chain, byte *wp, int wlen) |
||
169 | { |
||
170 | fz_stream *stm = fz_open_flated(chain); |
||
171 | int n = fz_read(stm, wp, wlen); |
||
172 | fz_close(stm); |
||
173 | if (n < 0) |
||
174 | return fz_rethrow(n, "cannot read flate strip"); |
||
175 | return fz_okay; |
||
176 | } |
||
177 | |||
178 | static int |
||
179 | xps_decode_tiff_fax(struct tiff *tiff, int comp, fz_stream *chain, byte *wp, int wlen) |
||
180 | { |
||
181 | fz_stream *stm; |
||
182 | fz_obj *params; |
||
183 | fz_obj *columns, *rows, *black_is_1, *k, *encoded_byte_align; |
||
184 | int n; |
||
185 | |||
186 | columns = fz_new_int(tiff->imagewidth); |
||
187 | rows = fz_new_int(tiff->imagelength); |
||
188 | black_is_1 = fz_new_bool(tiff->photometric == 0); |
||
189 | k = fz_new_int(comp == 4 ? -1 : 0); |
||
190 | encoded_byte_align = fz_new_bool(comp == 2); |
||
191 | |||
192 | params = fz_new_dict(5); |
||
193 | fz_dict_puts(params, "Columns", columns); |
||
194 | fz_dict_puts(params, "Rows", rows); |
||
195 | fz_dict_puts(params, "BlackIs1", black_is_1); |
||
196 | fz_dict_puts(params, "K", k); |
||
197 | fz_dict_puts(params, "EncodedByteAlign", encoded_byte_align); |
||
198 | |||
199 | fz_drop_obj(columns); |
||
200 | fz_drop_obj(rows); |
||
201 | fz_drop_obj(black_is_1); |
||
202 | fz_drop_obj(k); |
||
203 | fz_drop_obj(encoded_byte_align); |
||
204 | |||
205 | stm = fz_open_faxd(chain, params); |
||
206 | n = fz_read(stm, wp, wlen); |
||
207 | fz_close(stm); |
||
208 | fz_drop_obj(params); |
||
209 | |||
210 | if (n < 0) |
||
211 | return fz_rethrow(n, "cannot read fax strip"); |
||
212 | return fz_okay; |
||
213 | } |
||
214 | |||
215 | static int |
||
216 | xps_decode_tiff_jpeg(struct tiff *tiff, fz_stream *chain, byte *wp, int wlen) |
||
217 | { |
||
218 | fz_stream *stm = fz_open_dctd(chain, NULL); |
||
219 | int n = fz_read(stm, wp, wlen); |
||
220 | fz_close(stm); |
||
221 | if (n < 0) |
||
222 | return fz_rethrow(n, "cannot read jpeg strip"); |
||
223 | return fz_okay; |
||
224 | } |
||
225 | |||
226 | static inline int getcomp(byte *line, int x, int bpc) |
||
227 | { |
||
228 | switch (bpc) |
||
229 | { |
||
230 | case 1: return (line[x >> 3] >> ( 7 - (x & 7) ) ) & 1; |
||
231 | case 2: return (line[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3; |
||
232 | case 4: return (line[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15; |
||
233 | case 8: return line[x]; |
||
234 | case 16: return line[x << 1] << 8 | line[(x << 1) + 1]; |
||
235 | } |
||
236 | return 0; |
||
237 | } |
||
238 | |||
239 | static inline void putcomp(byte *line, int x, int bpc, int value) |
||
240 | { |
||
241 | int maxval = (1 << bpc) - 1; |
||
242 | |||
243 | switch (bpc) |
||
244 | { |
||
245 | case 1: line[x >> 3] &= ~(maxval << (7 - (x & 7))); break; |
||
246 | case 2: line[x >> 2] &= ~(maxval << ((3 - (x & 3)) << 1)); break; |
||
247 | case 4: line[x >> 1] &= ~(maxval << ((1 - (x & 1)) << 2)); break; |
||
248 | } |
||
249 | |||
250 | switch (bpc) |
||
251 | { |
||
252 | case 1: line[x >> 3] |= value << (7 - (x & 7)); break; |
||
253 | case 2: line[x >> 2] |= value << ((3 - (x & 3)) << 1); break; |
||
254 | case 4: line[x >> 1] |= value << ((1 - (x & 1)) << 2); break; |
||
255 | case 8: line[x] = value; break; |
||
256 | case 16: line[x << 1] = value >> 8; line[(x << 1) + 1] = value & 0xFF; break; |
||
257 | } |
||
258 | } |
||
259 | |||
260 | static void |
||
261 | xps_unpredict_tiff(byte *line, int width, int comps, int bits) |
||
262 | { |
||
263 | byte left[32]; |
||
264 | int i, k, v; |
||
265 | |||
266 | for (k = 0; k < comps; k++) |
||
267 | left[k] = 0; |
||
268 | |||
269 | for (i = 0; i < width; i++) |
||
270 | { |
||
271 | for (k = 0; k < comps; k++) |
||
272 | { |
||
273 | v = getcomp(line, i * comps + k, bits); |
||
274 | v = v + left[k]; |
||
275 | v = v % (1 << bits); |
||
276 | putcomp(line, i * comps + k, bits, v); |
||
277 | left[k] = v; |
||
278 | } |
||
279 | } |
||
280 | } |
||
281 | |||
282 | static void |
||
283 | xps_invert_tiff(byte *line, int width, int comps, int bits, int alpha) |
||
284 | { |
||
285 | int i, k, v; |
||
286 | int m = (1 << bits) - 1; |
||
287 | |||
288 | for (i = 0; i < width; i++) |
||
289 | { |
||
290 | for (k = 0; k < comps; k++) |
||
291 | { |
||
292 | v = getcomp(line, i * comps + k, bits); |
||
293 | if (!alpha || k < comps - 1) |
||
294 | v = m - v; |
||
295 | putcomp(line, i * comps + k, bits, v); |
||
296 | } |
||
297 | } |
||
298 | } |
||
299 | |||
300 | static int |
||
301 | xps_expand_tiff_colormap(struct tiff *tiff) |
||
302 | { |
||
303 | int maxval = 1 << tiff->bitspersample; |
||
304 | byte *samples; |
||
305 | byte *src, *dst; |
||
306 | unsigned int x, y; |
||
307 | unsigned int stride; |
||
308 | |||
309 | /* colormap has first all red, then all green, then all blue values */ |
||
310 | /* colormap values are 0..65535, bits is 4 or 8 */ |
||
311 | /* image can be with or without extrasamples: comps is 1 or 2 */ |
||
312 | |||
313 | if (tiff->samplesperpixel != 1 && tiff->samplesperpixel != 2) |
||
314 | return fz_throw("invalid number of samples for RGBPal"); |
||
315 | |||
316 | if (tiff->bitspersample != 4 && tiff->bitspersample != 8) |
||
317 | return fz_throw("invalid number of bits for RGBPal"); |
||
318 | |||
319 | stride = tiff->imagewidth * (tiff->samplesperpixel + 2); |
||
320 | |||
321 | samples = fz_malloc(stride * tiff->imagelength); |
||
322 | |||
323 | for (y = 0; y < tiff->imagelength; y++) |
||
324 | { |
||
325 | src = tiff->samples + (tiff->stride * y); |
||
326 | dst = samples + (stride * y); |
||
327 | |||
328 | for (x = 0; x < tiff->imagewidth; x++) |
||
329 | { |
||
330 | if (tiff->extrasamples) |
||
331 | { |
||
332 | int c = getcomp(src, x * 2, tiff->bitspersample); |
||
333 | int a = getcomp(src, x * 2 + 1, tiff->bitspersample); |
||
334 | *dst++ = tiff->colormap[c + 0] >> 8; |
||
335 | *dst++ = tiff->colormap[c + maxval] >> 8; |
||
336 | *dst++ = tiff->colormap[c + maxval * 2] >> 8; |
||
337 | *dst++ = a << (8 - tiff->bitspersample); |
||
338 | } |
||
339 | else |
||
340 | { |
||
341 | int c = getcomp(src, x, tiff->bitspersample); |
||
342 | *dst++ = tiff->colormap[c + 0] >> 8; |
||
343 | *dst++ = tiff->colormap[c + maxval] >> 8; |
||
344 | *dst++ = tiff->colormap[c + maxval * 2] >> 8; |
||
345 | } |
||
346 | } |
||
347 | } |
||
348 | |||
349 | tiff->samplesperpixel += 2; |
||
350 | tiff->bitspersample = 8; |
||
351 | tiff->stride = stride; |
||
352 | tiff->samples = samples; |
||
353 | return fz_okay; |
||
354 | } |
||
355 | |||
356 | static int |
||
357 | xps_decode_tiff_strips(struct tiff *tiff) |
||
358 | { |
||
359 | fz_stream *stm; |
||
360 | int error; |
||
361 | |||
362 | /* switch on compression to create a filter */ |
||
363 | /* feed each strip to the filter */ |
||
364 | /* read out the data and pack the samples into an xps_image */ |
||
365 | |||
366 | /* type 32773 / packbits -- nothing special (same row-padding as PDF) */ |
||
367 | /* type 2 / ccitt rle -- no EOL, no RTC, rows are byte-aligned */ |
||
368 | /* type 3 and 4 / g3 and g4 -- each strip starts new section */ |
||
369 | /* type 5 / lzw -- each strip is handled separately */ |
||
370 | |||
371 | byte *wp; |
||
372 | unsigned row; |
||
373 | unsigned strip; |
||
374 | unsigned i; |
||
375 | |||
376 | if (!tiff->rowsperstrip || !tiff->stripoffsets || !tiff->rowsperstrip) |
||
377 | return fz_throw("no image data in tiff; maybe it is tiled"); |
||
378 | |||
379 | if (tiff->planar != 1) |
||
380 | return fz_throw("image data is not in chunky format"); |
||
381 | |||
382 | tiff->stride = (tiff->imagewidth * tiff->samplesperpixel * tiff->bitspersample + 7) / 8; |
||
383 | |||
384 | switch (tiff->photometric) |
||
385 | { |
||
386 | case 0: /* WhiteIsZero -- inverted */ |
||
387 | tiff->colorspace = fz_device_gray; |
||
388 | break; |
||
389 | case 1: /* BlackIsZero */ |
||
390 | tiff->colorspace = fz_device_gray; |
||
391 | break; |
||
392 | case 2: /* RGB */ |
||
393 | tiff->colorspace = fz_device_rgb; |
||
394 | break; |
||
395 | case 3: /* RGBPal */ |
||
396 | tiff->colorspace = fz_device_rgb; |
||
397 | break; |
||
398 | case 5: /* CMYK */ |
||
399 | tiff->colorspace = fz_device_cmyk; |
||
400 | break; |
||
401 | case 6: /* YCbCr */ |
||
402 | /* it's probably a jpeg ... we let jpeg convert to rgb */ |
||
403 | tiff->colorspace = fz_device_rgb; |
||
404 | break; |
||
405 | default: |
||
406 | return fz_throw("unknown photometric: %d", tiff->photometric); |
||
407 | } |
||
408 | |||
409 | switch (tiff->resolutionunit) |
||
410 | { |
||
411 | case 2: |
||
412 | /* no unit conversion needed */ |
||
413 | break; |
||
414 | case 3: |
||
415 | tiff->xresolution = tiff->xresolution * 254 / 100; |
||
416 | tiff->yresolution = tiff->yresolution * 254 / 100; |
||
417 | break; |
||
418 | default: |
||
419 | tiff->xresolution = 96; |
||
420 | tiff->yresolution = 96; |
||
421 | break; |
||
422 | } |
||
423 | |||
424 | /* Note xres and yres could be 0 even if unit was set. If so default to 96dpi. */ |
||
425 | if (tiff->xresolution == 0 || tiff->yresolution == 0) |
||
426 | { |
||
427 | tiff->xresolution = 96; |
||
428 | tiff->yresolution = 96; |
||
429 | } |
||
430 | |||
431 | tiff->samples = fz_calloc(tiff->imagelength, tiff->stride); |
||
432 | memset(tiff->samples, 0x55, tiff->imagelength * tiff->stride); |
||
433 | wp = tiff->samples; |
||
434 | |||
435 | strip = 0; |
||
436 | for (row = 0; row < tiff->imagelength; row += tiff->rowsperstrip) |
||
437 | { |
||
438 | unsigned offset = tiff->stripoffsets[strip]; |
||
439 | unsigned rlen = tiff->stripbytecounts[strip]; |
||
440 | unsigned wlen = tiff->stride * tiff->rowsperstrip; |
||
441 | byte *rp = tiff->bp + offset; |
||
442 | |||
443 | if (wp + wlen > tiff->samples + tiff->stride * tiff->imagelength) |
||
444 | wlen = tiff->samples + tiff->stride * tiff->imagelength - wp; |
||
445 | |||
446 | if (rp + rlen > tiff->ep) |
||
447 | return fz_throw("strip extends beyond the end of the file"); |
||
448 | |||
449 | /* the bits are in un-natural order */ |
||
450 | if (tiff->fillorder == 2) |
||
451 | for (i = 0; i < rlen; i++) |
||
452 | rp[i] = bitrev[rp[i]]; |
||
453 | |||
454 | /* the strip decoders will close this */ |
||
455 | stm = fz_open_memory(rp, rlen); |
||
456 | |||
457 | switch (tiff->compression) |
||
458 | { |
||
459 | case 1: |
||
460 | error = xps_decode_tiff_uncompressed(tiff, stm, wp, wlen); |
||
461 | break; |
||
462 | case 2: |
||
463 | error = xps_decode_tiff_fax(tiff, 2, stm, wp, wlen); |
||
464 | break; |
||
465 | case 3: |
||
466 | error = xps_decode_tiff_fax(tiff, 3, stm, wp, wlen); |
||
467 | break; |
||
468 | case 4: |
||
469 | error = xps_decode_tiff_fax(tiff, 4, stm, wp, wlen); |
||
470 | break; |
||
471 | case 5: |
||
472 | error = xps_decode_tiff_lzw(tiff, stm, wp, wlen); |
||
473 | break; |
||
474 | case 6: |
||
475 | error = fz_throw("deprecated JPEG in TIFF compression not supported"); |
||
476 | break; |
||
477 | case 7: |
||
478 | error = xps_decode_tiff_jpeg(tiff, stm, wp, wlen); |
||
479 | break; |
||
480 | case 8: |
||
481 | error = xps_decode_tiff_flate(tiff, stm, wp, wlen); |
||
482 | break; |
||
483 | case 32773: |
||
484 | error = xps_decode_tiff_packbits(tiff, stm, wp, wlen); |
||
485 | break; |
||
486 | default: |
||
487 | error = fz_throw("unknown TIFF compression: %d", tiff->compression); |
||
488 | } |
||
489 | |||
490 | if (error) |
||
491 | return fz_rethrow(error, "cannot decode strip %d", row / tiff->rowsperstrip); |
||
492 | |||
493 | /* scramble the bits back into original order */ |
||
494 | if (tiff->fillorder == 2) |
||
495 | for (i = 0; i < rlen; i++) |
||
496 | rp[i] = bitrev[rp[i]]; |
||
497 | |||
498 | wp += tiff->stride * tiff->rowsperstrip; |
||
499 | strip ++; |
||
500 | } |
||
501 | |||
502 | /* Predictor (only for LZW and Flate) */ |
||
503 | if ((tiff->compression == 5 || tiff->compression == 8) && tiff->predictor == 2) |
||
504 | { |
||
505 | byte *p = tiff->samples; |
||
506 | for (i = 0; i < tiff->imagelength; i++) |
||
507 | { |
||
508 | xps_unpredict_tiff(p, tiff->imagewidth, tiff->samplesperpixel, tiff->bitspersample); |
||
509 | p += tiff->stride; |
||
510 | } |
||
511 | } |
||
512 | |||
513 | /* RGBPal */ |
||
514 | if (tiff->photometric == 3 && tiff->colormap) |
||
515 | { |
||
516 | error = xps_expand_tiff_colormap(tiff); |
||
517 | if (error) |
||
518 | return fz_rethrow(error, "cannot expand colormap"); |
||
519 | } |
||
520 | |||
521 | /* WhiteIsZero .. invert */ |
||
522 | if (tiff->photometric == 0) |
||
523 | { |
||
524 | byte *p = tiff->samples; |
||
525 | for (i = 0; i < tiff->imagelength; i++) |
||
526 | { |
||
527 | xps_invert_tiff(p, tiff->imagewidth, tiff->samplesperpixel, tiff->bitspersample, tiff->extrasamples); |
||
528 | p += tiff->stride; |
||
529 | } |
||
530 | } |
||
531 | |||
532 | return fz_okay; |
||
533 | } |
||
534 | |||
535 | static inline int readbyte(struct tiff *tiff) |
||
536 | { |
||
537 | if (tiff->rp < tiff->ep) |
||
538 | return *tiff->rp++; |
||
539 | return EOF; |
||
540 | } |
||
541 | |||
542 | static inline unsigned readshort(struct tiff *tiff) |
||
543 | { |
||
544 | unsigned a = readbyte(tiff); |
||
545 | unsigned b = readbyte(tiff); |
||
546 | if (tiff->order == TII) |
||
547 | return (b << 8) | a; |
||
548 | return (a << 8) | b; |
||
549 | } |
||
550 | |||
551 | static inline unsigned readlong(struct tiff *tiff) |
||
552 | { |
||
553 | unsigned a = readbyte(tiff); |
||
554 | unsigned b = readbyte(tiff); |
||
555 | unsigned c = readbyte(tiff); |
||
556 | unsigned d = readbyte(tiff); |
||
557 | if (tiff->order == TII) |
||
558 | return (d << 24) | (c << 16) | (b << 8) | a; |
||
559 | return (a << 24) | (b << 16) | (c << 8) | d; |
||
560 | } |
||
561 | |||
562 | static void |
||
563 | xps_read_tiff_bytes(unsigned char *p, struct tiff *tiff, unsigned ofs, unsigned n) |
||
564 | { |
||
565 | tiff->rp = tiff->bp + ofs; |
||
566 | if (tiff->rp > tiff->ep) |
||
567 | tiff->rp = tiff->bp; |
||
568 | |||
569 | while (n--) |
||
570 | *p++ = readbyte(tiff); |
||
571 | } |
||
572 | |||
573 | static void |
||
574 | xps_read_tiff_tag_value(unsigned *p, struct tiff *tiff, unsigned type, unsigned ofs, unsigned n) |
||
575 | { |
||
576 | tiff->rp = tiff->bp + ofs; |
||
577 | if (tiff->rp > tiff->ep) |
||
578 | tiff->rp = tiff->bp; |
||
579 | |||
580 | while (n--) |
||
581 | { |
||
582 | switch (type) |
||
583 | { |
||
584 | case TRATIONAL: |
||
585 | *p = readlong(tiff); |
||
586 | *p = *p / readlong(tiff); |
||
587 | p ++; |
||
588 | break; |
||
589 | case TBYTE: *p++ = readbyte(tiff); break; |
||
590 | case TSHORT: *p++ = readshort(tiff); break; |
||
591 | case TLONG: *p++ = readlong(tiff); break; |
||
592 | default: *p++ = 0; break; |
||
593 | } |
||
594 | } |
||
595 | } |
||
596 | |||
597 | static int |
||
598 | xps_read_tiff_tag(struct tiff *tiff, unsigned offset) |
||
599 | { |
||
600 | unsigned tag; |
||
601 | unsigned type; |
||
602 | unsigned count; |
||
603 | unsigned value; |
||
604 | |||
605 | tiff->rp = tiff->bp + offset; |
||
606 | |||
607 | tag = readshort(tiff); |
||
608 | type = readshort(tiff); |
||
609 | count = readlong(tiff); |
||
610 | |||
611 | if ((type == TBYTE && count <= 4) || |
||
612 | (type == TSHORT && count <= 2) || |
||
613 | (type == TLONG && count <= 1)) |
||
614 | value = tiff->rp - tiff->bp; |
||
615 | else |
||
616 | value = readlong(tiff); |
||
617 | |||
618 | switch (tag) |
||
619 | { |
||
620 | case NewSubfileType: |
||
621 | xps_read_tiff_tag_value(&tiff->subfiletype, tiff, type, value, 1); |
||
622 | break; |
||
623 | case ImageWidth: |
||
624 | xps_read_tiff_tag_value(&tiff->imagewidth, tiff, type, value, 1); |
||
625 | break; |
||
626 | case ImageLength: |
||
627 | xps_read_tiff_tag_value(&tiff->imagelength, tiff, type, value, 1); |
||
628 | break; |
||
629 | case BitsPerSample: |
||
630 | xps_read_tiff_tag_value(&tiff->bitspersample, tiff, type, value, 1); |
||
631 | break; |
||
632 | case Compression: |
||
633 | xps_read_tiff_tag_value(&tiff->compression, tiff, type, value, 1); |
||
634 | break; |
||
635 | case PhotometricInterpretation: |
||
636 | xps_read_tiff_tag_value(&tiff->photometric, tiff, type, value, 1); |
||
637 | break; |
||
638 | case FillOrder: |
||
639 | xps_read_tiff_tag_value(&tiff->fillorder, tiff, type, value, 1); |
||
640 | break; |
||
641 | case SamplesPerPixel: |
||
642 | xps_read_tiff_tag_value(&tiff->samplesperpixel, tiff, type, value, 1); |
||
643 | break; |
||
644 | case RowsPerStrip: |
||
645 | xps_read_tiff_tag_value(&tiff->rowsperstrip, tiff, type, value, 1); |
||
646 | break; |
||
647 | case XResolution: |
||
648 | xps_read_tiff_tag_value(&tiff->xresolution, tiff, type, value, 1); |
||
649 | break; |
||
650 | case YResolution: |
||
651 | xps_read_tiff_tag_value(&tiff->yresolution, tiff, type, value, 1); |
||
652 | break; |
||
653 | case PlanarConfiguration: |
||
654 | xps_read_tiff_tag_value(&tiff->planar, tiff, type, value, 1); |
||
655 | break; |
||
656 | case T4Options: |
||
657 | xps_read_tiff_tag_value(&tiff->g3opts, tiff, type, value, 1); |
||
658 | break; |
||
659 | case T6Options: |
||
660 | xps_read_tiff_tag_value(&tiff->g4opts, tiff, type, value, 1); |
||
661 | break; |
||
662 | case Predictor: |
||
663 | xps_read_tiff_tag_value(&tiff->predictor, tiff, type, value, 1); |
||
664 | break; |
||
665 | case ResolutionUnit: |
||
666 | xps_read_tiff_tag_value(&tiff->resolutionunit, tiff, type, value, 1); |
||
667 | break; |
||
668 | case YCbCrSubSampling: |
||
669 | xps_read_tiff_tag_value(tiff->ycbcrsubsamp, tiff, type, value, 2); |
||
670 | break; |
||
671 | case ExtraSamples: |
||
672 | xps_read_tiff_tag_value(&tiff->extrasamples, tiff, type, value, 1); |
||
673 | break; |
||
674 | |||
675 | case ICCProfile: |
||
676 | tiff->profile = fz_malloc(count); |
||
677 | /* ICC profile data type is set to UNDEFINED. |
||
678 | * TBYTE reading not correct in xps_read_tiff_tag_value */ |
||
679 | xps_read_tiff_bytes(tiff->profile, tiff, value, count); |
||
680 | tiff->profilesize = count; |
||
681 | break; |
||
682 | |||
683 | case JPEGTables: |
||
684 | fz_warn("jpeg tables in tiff not implemented"); |
||
685 | tiff->jpegtables = tiff->bp + value; |
||
686 | tiff->jpegtableslen = count; |
||
687 | break; |
||
688 | |||
689 | case StripOffsets: |
||
690 | tiff->stripoffsets = fz_calloc(count, sizeof(unsigned)); |
||
691 | xps_read_tiff_tag_value(tiff->stripoffsets, tiff, type, value, count); |
||
692 | break; |
||
693 | |||
694 | case StripByteCounts: |
||
695 | tiff->stripbytecounts = fz_calloc(count, sizeof(unsigned)); |
||
696 | xps_read_tiff_tag_value(tiff->stripbytecounts, tiff, type, value, count); |
||
697 | break; |
||
698 | |||
699 | case ColorMap: |
||
700 | tiff->colormap = fz_calloc(count, sizeof(unsigned)); |
||
701 | xps_read_tiff_tag_value(tiff->colormap, tiff, type, value, count); |
||
702 | break; |
||
703 | |||
704 | case TileWidth: |
||
705 | case TileLength: |
||
706 | case TileOffsets: |
||
707 | case TileByteCounts: |
||
708 | return fz_throw("tiled tiffs not supported"); |
||
709 | |||
710 | default: |
||
711 | /* printf("unknown tag: %d t=%d n=%d\n", tag, type, count); */ |
||
712 | break; |
||
713 | } |
||
714 | |||
715 | return fz_okay; |
||
716 | } |
||
717 | |||
718 | static void |
||
719 | xps_swap_byte_order(byte *buf, int n) |
||
720 | { |
||
721 | int i, t; |
||
722 | for (i = 0; i < n; i++) |
||
723 | { |
||
724 | t = buf[i * 2 + 0]; |
||
725 | buf[i * 2 + 0] = buf[i * 2 + 1]; |
||
726 | buf[i * 2 + 1] = t; |
||
727 | } |
||
728 | } |
||
729 | |||
730 | static int |
||
731 | xps_decode_tiff_header(struct tiff *tiff, byte *buf, int len) |
||
732 | { |
||
733 | unsigned version; |
||
734 | unsigned offset; |
||
735 | unsigned count; |
||
736 | unsigned i; |
||
737 | int error; |
||
738 | |||
739 | memset(tiff, 0, sizeof(struct tiff)); |
||
740 | |||
741 | tiff->bp = buf; |
||
742 | tiff->rp = buf; |
||
743 | tiff->ep = buf + len; |
||
744 | |||
745 | /* tag defaults, where applicable */ |
||
746 | tiff->bitspersample = 1; |
||
747 | tiff->compression = 1; |
||
748 | tiff->samplesperpixel = 1; |
||
749 | tiff->resolutionunit = 2; |
||
750 | tiff->rowsperstrip = 0xFFFFFFFF; |
||
751 | tiff->fillorder = 1; |
||
752 | tiff->planar = 1; |
||
753 | tiff->subfiletype = 0; |
||
754 | tiff->predictor = 1; |
||
755 | tiff->ycbcrsubsamp[0] = 2; |
||
756 | tiff->ycbcrsubsamp[1] = 2; |
||
757 | |||
758 | /* |
||
759 | * Read IFH |
||
760 | */ |
||
761 | |||
762 | /* get byte order marker */ |
||
763 | tiff->order = TII; |
||
764 | tiff->order = readshort(tiff); |
||
765 | if (tiff->order != TII && tiff->order != TMM) |
||
766 | return fz_throw("not a TIFF file, wrong magic marker"); |
||
767 | |||
768 | /* check version */ |
||
769 | version = readshort(tiff); |
||
770 | if (version != 42) |
||
771 | return fz_throw("not a TIFF file, wrong version marker"); |
||
772 | |||
773 | /* get offset of IFD */ |
||
774 | offset = readlong(tiff); |
||
775 | |||
776 | /* |
||
777 | * Read IFD |
||
778 | */ |
||
779 | |||
780 | tiff->rp = tiff->bp + offset; |
||
781 | |||
782 | count = readshort(tiff); |
||
783 | |||
784 | offset += 2; |
||
785 | for (i = 0; i < count; i++) |
||
786 | { |
||
787 | error = xps_read_tiff_tag(tiff, offset); |
||
788 | if (error) |
||
789 | return fz_rethrow(error, "cannot read TIFF header tag"); |
||
790 | offset += 12; |
||
791 | } |
||
792 | |||
793 | return fz_okay; |
||
794 | } |
||
795 | |||
796 | int |
||
797 | xps_decode_tiff(fz_pixmap **imagep, byte *buf, int len) |
||
798 | { |
||
799 | int error; |
||
800 | fz_pixmap *image; |
||
801 | struct tiff tiff; |
||
802 | |||
803 | error = xps_decode_tiff_header(&tiff, buf, len); |
||
804 | if (error) |
||
805 | return fz_rethrow(error, "cannot decode tiff header"); |
||
806 | |||
807 | /* Decode the image strips */ |
||
808 | |||
809 | if (tiff.rowsperstrip > tiff.imagelength) |
||
810 | tiff.rowsperstrip = tiff.imagelength; |
||
811 | |||
812 | error = xps_decode_tiff_strips(&tiff); |
||
813 | if (error) |
||
814 | return fz_rethrow(error, "cannot decode image data"); |
||
815 | |||
816 | /* Byte swap 16-bit images to big endian if necessary */ |
||
817 | if (tiff.bitspersample == 16) |
||
818 | { |
||
819 | if (tiff.order == TII) |
||
820 | xps_swap_byte_order(tiff.samples, tiff.imagewidth * tiff.imagelength * tiff.samplesperpixel); |
||
821 | } |
||
822 | |||
823 | /* Expand into fz_pixmap struct */ |
||
824 | |||
825 | image = fz_new_pixmap_with_limit(tiff.colorspace, tiff.imagewidth, tiff.imagelength); |
||
826 | if (!image) |
||
827 | { |
||
828 | if (tiff.colormap) fz_free(tiff.colormap); |
||
829 | if (tiff.stripoffsets) fz_free(tiff.stripoffsets); |
||
830 | if (tiff.stripbytecounts) fz_free(tiff.stripbytecounts); |
||
831 | if (tiff.samples) fz_free(tiff.samples); |
||
832 | return fz_throw("out of memory"); |
||
833 | } |
||
834 | |||
835 | image->xres = tiff.xresolution; |
||
836 | image->yres = tiff.yresolution; |
||
837 | |||
838 | fz_unpack_tile(image, tiff.samples, tiff.samplesperpixel, tiff.bitspersample, tiff.stride, 0); |
||
839 | |||
840 | /* We should only do this on non-pre-multiplied images, but files in the wild are bad */ |
||
841 | if (tiff.extrasamples /* == 2 */) |
||
842 | { |
||
843 | /* CMYK is a subtractive colorspace, we want additive for premul alpha */ |
||
844 | if (image->n == 5) |
||
845 | { |
||
846 | fz_pixmap *rgb = fz_new_pixmap(fz_device_rgb, image->w, image->h); |
||
847 | fz_convert_pixmap(image, rgb); |
||
848 | rgb->xres = image->xres; |
||
849 | rgb->yres = image->yres; |
||
850 | fz_drop_pixmap(image); |
||
851 | image = rgb; |
||
852 | } |
||
853 | fz_premultiply_pixmap(image); |
||
854 | } |
||
855 | |||
856 | /* Clean up scratch memory */ |
||
857 | |||
858 | if (tiff.colormap) fz_free(tiff.colormap); |
||
859 | if (tiff.stripoffsets) fz_free(tiff.stripoffsets); |
||
860 | if (tiff.stripbytecounts) fz_free(tiff.stripbytecounts); |
||
861 | if (tiff.samples) fz_free(tiff.samples); |
||
862 | |||
863 | *imagep = image; |
||
864 | return fz_okay; |
||
865 | }>>=>=>=>><>><>><>><>><>><>><>><>>>>>>>><>>>><>>>>><>><>>>>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>>>>>>> |