1 | /*
|
---|
2 |
|
---|
3 | gbmtif.c - Microsoft/Aldus Tagged Image File Format support
|
---|
4 |
|
---|
5 | Reads and writes 1,4,8 and 24 bit colour files.
|
---|
6 | Supports uncompressed, Packbits and LZW compressed files only.
|
---|
7 | Input option: index=N (default is 0)
|
---|
8 | Output options: artist=,software=,make=,model=,host=,documentname=,pagename=,
|
---|
9 | imagedescription=,pal1bpp
|
---|
10 |
|
---|
11 | Added support to allow SamplePerPixel>=3 for RGB data (TIFF 6.0 new feature).
|
---|
12 | Added rejection test of FillOrder!=1.
|
---|
13 | Added rejection test of PlanarConfiguration!=1.
|
---|
14 | Added support for CMYK images.
|
---|
15 | Changed write of 1bpp data to Baseline black and white write.
|
---|
16 | Added pal1bpp output option meaning don't force Baseline write of 1bpp data.
|
---|
17 | Improved error messages substantially.
|
---|
18 | Fixed Packbits compression.
|
---|
19 | Added support for PlanarConfiguration==2 for RGB images only.
|
---|
20 | Added Predictor==2 support for bps==8, spp=1 case.
|
---|
21 | Added Predictor==2 support for bps==8, spp>=3 case.
|
---|
22 | Removed Too Many Strips limitation.
|
---|
23 | Faster LZW code.
|
---|
24 | Fixes to LZW compressor (and #ifdef DEBUG debug code).
|
---|
25 |
|
---|
26 | */
|
---|
27 |
|
---|
28 | /*...sincludes:0:*/
|
---|
29 | #include <stdio.h>
|
---|
30 | #include <ctype.h>
|
---|
31 | #include <stddef.h>
|
---|
32 | #include <stdlib.h>
|
---|
33 | #include <string.h>
|
---|
34 | #include "gbm.h"
|
---|
35 | #include "gbmhelp.h"
|
---|
36 | #include "gbmtifh.h"
|
---|
37 |
|
---|
38 | /*...vgbm\46\h:0:*/
|
---|
39 | /*...vgbmhelp\46\h:0:*/
|
---|
40 | /*...vgbmtifh\46\h:0:*/
|
---|
41 |
|
---|
42 | #ifndef min
|
---|
43 | #define min(a,b) (((a)<(b))?(a):(b))
|
---|
44 | #endif
|
---|
45 | /*...e*/
|
---|
46 |
|
---|
47 | /* #define DEBUG */
|
---|
48 |
|
---|
49 | static GBMFT tif_gbmft =
|
---|
50 | {
|
---|
51 | "TIFF",
|
---|
52 | "Tagged Image File Format support (almost TIFF 6.0 Baseline)",
|
---|
53 | "TIF TIFF",
|
---|
54 | GBM_FT_R1|GBM_FT_R4|GBM_FT_R8|GBM_FT_R24|
|
---|
55 | GBM_FT_W1|GBM_FT_W4|GBM_FT_W8|GBM_FT_W24,
|
---|
56 | };
|
---|
57 |
|
---|
58 | /*...serror codes:0:*/
|
---|
59 | #define GBM_ERR_TIF_VERSION ((GBM_ERR) 800)
|
---|
60 | #define GBM_ERR_TIF_N_TAGS ((GBM_ERR) 801)
|
---|
61 | #define GBM_ERR_TIF_TAG_TYPE ((GBM_ERR) 802)
|
---|
62 | #define GBM_ERR_TIF_HEADER ((GBM_ERR) 803)
|
---|
63 | #define GBM_ERR_TIF_MISSING_TAG ((GBM_ERR) 804)
|
---|
64 | #define GBM_ERR_TIF_SPP_BIT ((GBM_ERR) 805)
|
---|
65 | #define GBM_ERR_TIF_BPS_BIT ((GBM_ERR) 806)
|
---|
66 | #define GBM_ERR_TIF_SPP_RGB ((GBM_ERR) 807)
|
---|
67 | #define GBM_ERR_TIF_BPS_RGB ((GBM_ERR) 808)
|
---|
68 | #define GBM_ERR_TIF_SPP_PAL ((GBM_ERR) 809)
|
---|
69 | #define GBM_ERR_TIF_BPS_PAL ((GBM_ERR) 810)
|
---|
70 | #define GBM_ERR_TIF_SPP_CMYK ((GBM_ERR) 811)
|
---|
71 | #define GBM_ERR_TIF_BPS_CMYK ((GBM_ERR) 812)
|
---|
72 | #define GBM_ERR_TIF_COMP_1D_MH ((GBM_ERR) 813)
|
---|
73 | #define GBM_ERR_TIF_COMP_T4 ((GBM_ERR) 814)
|
---|
74 | #define GBM_ERR_TIF_COMP_T6 ((GBM_ERR) 815)
|
---|
75 | #define GBM_ERR_TIF_COMP ((GBM_ERR) 816)
|
---|
76 | #define GBM_ERR_TIF_COLORMAP ((GBM_ERR) 817)
|
---|
77 | #define GBM_ERR_TIF_CORRUPT ((GBM_ERR) 818)
|
---|
78 | #define GBM_ERR_TIF_PREDICTOR ((GBM_ERR) 819)
|
---|
79 | #define GBM_ERR_TIF_PHOTO_TRANS ((GBM_ERR) 821)
|
---|
80 | #define GBM_ERR_TIF_PHOTO_Y_Cb_Cr ((GBM_ERR) 822)
|
---|
81 | #define GBM_ERR_TIF_PHOTO ((GBM_ERR) 823)
|
---|
82 | #define GBM_ERR_TIF_FILLORDER ((GBM_ERR) 824)
|
---|
83 | #define GBM_ERR_TIF_PLANARCONFIG_1 ((GBM_ERR) 825)
|
---|
84 | #define GBM_ERR_TIF_PLANARCONFIG_12 ((GBM_ERR) 826)
|
---|
85 | #define GBM_ERR_TIF_INKSET ((GBM_ERR) 827)
|
---|
86 | #define GBM_ERR_TIF_ORIENT ((GBM_ERR) 828)
|
---|
87 | #define GBM_ERR_TIF_INDEX ((GBM_ERR) 829)
|
---|
88 | /*...e*/
|
---|
89 |
|
---|
90 | /*...sdefns:0:*/
|
---|
91 | /*
|
---|
92 | #define MAX_STRIPS 200
|
---|
93 | */
|
---|
94 | #define MAX_STRIPS ((PRIV_SIZE-9*sizeof(int)-0x100*sizeof(GBMRGB))/sizeof(long))
|
---|
95 |
|
---|
96 | typedef struct
|
---|
97 | {
|
---|
98 | GBMRGB gbmrgb[0x100];
|
---|
99 | int rps, spp, bps, comp, photo, orient, planar, predictor, inx;
|
---|
100 | long so[MAX_STRIPS];
|
---|
101 | } TIF_PRIV;
|
---|
102 |
|
---|
103 | #define ENC_NONE ((int) 1)
|
---|
104 | #define ENC_G3_1D_MH ((int) 2)
|
---|
105 | #define ENC_T4 ((int) 3)
|
---|
106 | #define ENC_T6 ((int) 4)
|
---|
107 | #define ENC_LZW ((int) 5)
|
---|
108 | #define ENC_PACKBITS ((int) 32773)
|
---|
109 |
|
---|
110 | #define PHOTO_BIT0 0
|
---|
111 | #define PHOTO_BIT1 1
|
---|
112 | #define PHOTO_RGB 2
|
---|
113 | #define PHOTO_PAL 3
|
---|
114 | #define PHOTO_TRANS 4
|
---|
115 | #define PHOTO_CMYK 5
|
---|
116 | #define PHOTO_Y_Cb_Cr 6
|
---|
117 |
|
---|
118 | /* TIFF LZW definitions */
|
---|
119 |
|
---|
120 | #define INIT_CODE_SIZE 9
|
---|
121 | #define CLEAR_CODE 0x100
|
---|
122 | #define EOI_CODE 0x101
|
---|
123 | #define FIRST_FREE_CODE 0x102
|
---|
124 | /*...e*/
|
---|
125 |
|
---|
126 | /*...srgb_bgr:0:*/
|
---|
127 | static void rgb_bgr(const byte *p, byte *q, int n)
|
---|
128 | {
|
---|
129 | while ( n-- )
|
---|
130 | {
|
---|
131 | byte r = *p++;
|
---|
132 | byte g = *p++;
|
---|
133 | byte b = *p++;
|
---|
134 |
|
---|
135 | *q++ = b;
|
---|
136 | *q++ = g;
|
---|
137 | *q++ = r;
|
---|
138 | }
|
---|
139 | }
|
---|
140 | /*...e*/
|
---|
141 |
|
---|
142 | typedef unsigned int cword;
|
---|
143 |
|
---|
144 | #ifdef DEBUG
|
---|
145 | #define LOG(args) printf args
|
---|
146 | #else
|
---|
147 | #define LOG(args)
|
---|
148 | #endif
|
---|
149 |
|
---|
150 | /*...stif_qft:0:*/
|
---|
151 | GBM_ERR tif_qft(GBMFT *gbmft)
|
---|
152 | {
|
---|
153 | *gbmft = tif_gbmft;
|
---|
154 | return GBM_ERR_OK;
|
---|
155 | }
|
---|
156 | /*...e*/
|
---|
157 | /*...stif_rhdr:0:*/
|
---|
158 | /*...svalue_of_tag_def:0:*/
|
---|
159 | static long value_of_tag_def(IFD *ifd, short type, long def)
|
---|
160 | {
|
---|
161 | TAG *tag;
|
---|
162 |
|
---|
163 | if ( (tag = locate_tag(ifd, type)) != NULL )
|
---|
164 | return value_of_tag(tag);
|
---|
165 | else
|
---|
166 | return def;
|
---|
167 | }
|
---|
168 | /*...e*/
|
---|
169 |
|
---|
170 | GBM_ERR tif_rhdr(const char *fn, int fd, GBM *gbm, const char *opt)
|
---|
171 | {
|
---|
172 | TIF_PRIV *tif_priv = (TIF_PRIV *) gbm->priv;
|
---|
173 | TAG *tag_w, *tag_h, *tag_so;
|
---|
174 | GBM_ERR rc;
|
---|
175 | IFH *ifh;
|
---|
176 | IFD *ifd;
|
---|
177 | int inx = 0, strip, n_strips, fillorder;
|
---|
178 | const char *index;
|
---|
179 |
|
---|
180 | if ( (index = gbm_find_word_prefix(opt, "index=")) != NULL )
|
---|
181 | sscanf(index + 6, "%d", &inx);
|
---|
182 | tif_priv->inx = inx;
|
---|
183 |
|
---|
184 | fn=fn; /* Suppress 'unref arg' compiler warnings */
|
---|
185 |
|
---|
186 | switch ( read_ifh_and_ifd(fd, inx, &ifh) )
|
---|
187 | {
|
---|
188 | case TE_OK: rc = GBM_ERR_OK; break;
|
---|
189 | case TE_MEM: rc = GBM_ERR_MEM; break;
|
---|
190 | case TE_VERSION: rc = GBM_ERR_TIF_VERSION; break;
|
---|
191 | case TE_N_TAGS: rc = GBM_ERR_TIF_N_TAGS; break;
|
---|
192 | case TE_TAG_TYPE: rc = GBM_ERR_TIF_TAG_TYPE; break;
|
---|
193 | case TE_N_IFD: rc = GBM_ERR_TIF_INDEX; break;
|
---|
194 | default: rc = GBM_ERR_TIF_HEADER; break;
|
---|
195 | }
|
---|
196 |
|
---|
197 | if ( rc != GBM_ERR_OK )
|
---|
198 | return rc;
|
---|
199 |
|
---|
200 | ifd = ifh->ifd;
|
---|
201 |
|
---|
202 | if ( (tag_w = locate_tag(ifd, T_IMAGEWIDTH )) == NULL ||
|
---|
203 | (tag_h = locate_tag(ifd, T_IMAGELENGTH )) == NULL ||
|
---|
204 | (tag_so = locate_tag(ifd, T_STRIPOFFSETS)) == NULL )
|
---|
205 | {
|
---|
206 | free_ifh(ifh);
|
---|
207 | return GBM_ERR_TIF_MISSING_TAG;
|
---|
208 | }
|
---|
209 |
|
---|
210 | gbm->w = (int) value_of_tag(tag_w);
|
---|
211 | gbm->h = (int) value_of_tag(tag_h);
|
---|
212 | tif_priv->photo = (int) value_of_tag_def(ifd, T_PHOTOMETRIC , 1L);
|
---|
213 | tif_priv->rps = (int) value_of_tag_def(ifd, T_ROWSPERSTRIP , (long) gbm->h);
|
---|
214 | tif_priv->spp = (int) value_of_tag_def(ifd, T_SAMPLESPERPIXEL, 1L);
|
---|
215 | tif_priv->bps = (int) value_of_tag_def(ifd, T_BITSPERSAMPLE , 1L);
|
---|
216 | tif_priv->comp = (int) value_of_tag_def(ifd, T_COMPRESSION , 1L);
|
---|
217 | tif_priv->orient = (int) value_of_tag_def(ifd, T_ORIENTATION , 1L);
|
---|
218 | tif_priv->planar = (int) value_of_tag_def(ifd, T_PLANARCONFIG , 1L);
|
---|
219 |
|
---|
220 | rc = GBM_ERR_OK;
|
---|
221 | switch ( tif_priv->photo )
|
---|
222 | {
|
---|
223 | /*...sPHOTO_BITx \45\ bitmap or greyscale:16:*/
|
---|
224 | case PHOTO_BIT0:
|
---|
225 | case PHOTO_BIT1:
|
---|
226 | if ( tif_priv->spp != 1 )
|
---|
227 | rc = GBM_ERR_TIF_SPP_BIT;
|
---|
228 | else if ( tif_priv->bps != 1 && tif_priv->bps != 4 && tif_priv->bps != 8 )
|
---|
229 | rc = GBM_ERR_TIF_BPS_BIT;
|
---|
230 | else
|
---|
231 | {
|
---|
232 | int i, n_pal;
|
---|
233 |
|
---|
234 | n_pal = ( 1 << tif_priv->bps );
|
---|
235 | for ( i = 0; i < n_pal; i++ )
|
---|
236 | {
|
---|
237 | tif_priv->gbmrgb[i].r =
|
---|
238 | tif_priv->gbmrgb[i].g =
|
---|
239 | tif_priv->gbmrgb[i].b = (byte) ((0xff * i) / (n_pal - 1));
|
---|
240 | }
|
---|
241 | if ( tif_priv->photo == PHOTO_BIT0 )
|
---|
242 | for ( i = 0; i < n_pal; i++ )
|
---|
243 | {
|
---|
244 | tif_priv->gbmrgb[i].r ^= 0xff;
|
---|
245 | tif_priv->gbmrgb[i].g ^= 0xff;
|
---|
246 | tif_priv->gbmrgb[i].b ^= 0xff;
|
---|
247 | }
|
---|
248 | }
|
---|
249 | gbm->bpp = tif_priv->bps;
|
---|
250 | break;
|
---|
251 | /*...e*/
|
---|
252 | /*...sPHOTO_RGB \45\ 24 bit data:16:*/
|
---|
253 | /* It is possible for sample per pixel to be greater than 3.
|
---|
254 | This implies there are extra samples (which we will ignore).
|
---|
255 | This is a new TIFF 6.0 feature. */
|
---|
256 |
|
---|
257 | case PHOTO_RGB:
|
---|
258 | if ( tif_priv->spp < 3 )
|
---|
259 | rc = GBM_ERR_TIF_SPP_RGB;
|
---|
260 | else if ( tif_priv->bps != 8 )
|
---|
261 | rc = GBM_ERR_TIF_BPS_RGB;
|
---|
262 | gbm->bpp = 24;
|
---|
263 | break;
|
---|
264 | /*...e*/
|
---|
265 | /*...sPHOTO_PAL \45\ palettised:16:*/
|
---|
266 | /*
|
---|
267 | There are 2 known bugs in commonly available TIFF files today.
|
---|
268 | UBU will only write a ColorMap tag with a length field of 256 (not 256 * 3).
|
---|
269 | This bug is fixed inside my TIFF library itself!
|
---|
270 | OS/2 Image Support will write all palette entrys as bytes!
|
---|
271 | */
|
---|
272 |
|
---|
273 | case PHOTO_PAL:
|
---|
274 | if ( tif_priv->spp != 1 )
|
---|
275 | rc = GBM_ERR_TIF_SPP_PAL;
|
---|
276 | else if ( tif_priv->bps != 1 && tif_priv->bps != 4 && tif_priv->bps != 8 )
|
---|
277 | rc = GBM_ERR_TIF_BPS_PAL;
|
---|
278 | else
|
---|
279 | {
|
---|
280 | int i, n_pal;
|
---|
281 | TAG *tag_cm;
|
---|
282 |
|
---|
283 | n_pal = (1 << tif_priv->bps);
|
---|
284 | if ( (tag_cm = locate_tag(ifd, T_COLORMAP)) != NULL )
|
---|
285 | {
|
---|
286 | GBMRGB *gbmrgb;
|
---|
287 |
|
---|
288 | for ( i = 0, gbmrgb = tif_priv->gbmrgb; i < n_pal; i++, gbmrgb++ )
|
---|
289 | {
|
---|
290 | gbmrgb->r = (byte) ((unsigned)value_of_tag_n(tag_cm, i) >> 8);
|
---|
291 | gbmrgb->g = (byte) ((unsigned)value_of_tag_n(tag_cm, n_pal + i) >> 8);
|
---|
292 | gbmrgb->b = (byte) ((unsigned)value_of_tag_n(tag_cm, 2 * n_pal + i) >> 8);
|
---|
293 | }
|
---|
294 | /*...sfix for OS\47\2 Image Support \40\and others\41\:40:*/
|
---|
295 | {
|
---|
296 | byte bugfix = 0;
|
---|
297 |
|
---|
298 | for ( i = 0, gbmrgb = tif_priv->gbmrgb; i < n_pal; i++, gbmrgb++ )
|
---|
299 | bugfix |= (gbmrgb->r | gbmrgb->g | gbmrgb->b);
|
---|
300 |
|
---|
301 | if ( bugfix == 0 )
|
---|
302 | for ( i = 0, gbmrgb = tif_priv->gbmrgb; i < n_pal; i++, gbmrgb++ )
|
---|
303 | {
|
---|
304 | gbmrgb->r = (byte) value_of_tag_n(tag_cm, i);
|
---|
305 | gbmrgb->g = (byte) value_of_tag_n(tag_cm, n_pal + i);
|
---|
306 | gbmrgb->b = (byte) value_of_tag_n(tag_cm, 2 * n_pal + i);
|
---|
307 | }
|
---|
308 | }
|
---|
309 | /*...e*/
|
---|
310 | }
|
---|
311 | else
|
---|
312 | rc = GBM_ERR_TIF_COLORMAP;
|
---|
313 | }
|
---|
314 | gbm->bpp = tif_priv->bps;
|
---|
315 | break;
|
---|
316 | /*...e*/
|
---|
317 | /*...sPHOTO_TRANS \45\ transparency mask:16:*/
|
---|
318 | case PHOTO_TRANS:
|
---|
319 | rc = GBM_ERR_TIF_PHOTO_TRANS;
|
---|
320 | break;
|
---|
321 | /*...e*/
|
---|
322 | /*...sPHOTO_CMYK \45\ CMYK or other seperated image:16:*/
|
---|
323 | /* This is a colour seperated image.
|
---|
324 | Typically expect 4 seperations, for CMYK.
|
---|
325 | Can be other numbers, and possibly 4 with non standard ink colours.
|
---|
326 | Ignore all but 4 seperations which are CMYK.
|
---|
327 | Consider this a 24 bit RGB, mapping will occur from CMYK to RGB. */
|
---|
328 |
|
---|
329 | case PHOTO_CMYK:
|
---|
330 | if ( tif_priv->spp != 4 )
|
---|
331 | rc = GBM_ERR_TIF_SPP_CMYK;
|
---|
332 | else if ( tif_priv->bps != 8 )
|
---|
333 | rc = GBM_ERR_TIF_BPS_CMYK;
|
---|
334 | else if ( value_of_tag_def(ifd, T_INKSET, 1L) != 1 )
|
---|
335 | rc = GBM_ERR_TIF_INKSET;
|
---|
336 | else
|
---|
337 | gbm->bpp = 24;
|
---|
338 | break;
|
---|
339 | /*...e*/
|
---|
340 | /*...sPHOTO_Y_Cb_Cr \45\ Y\45\Cb\45\Cr colour space:16:*/
|
---|
341 | case PHOTO_Y_Cb_Cr:
|
---|
342 | rc = GBM_ERR_TIF_PHOTO_Y_Cb_Cr;
|
---|
343 | break;
|
---|
344 | /*...e*/
|
---|
345 | /*...sdefault \45\ wierd PhotometricInterpretation:16:*/
|
---|
346 | default:
|
---|
347 | rc = GBM_ERR_TIF_PHOTO;
|
---|
348 | break;
|
---|
349 | /*...e*/
|
---|
350 | }
|
---|
351 |
|
---|
352 | if ( rc != GBM_ERR_OK )
|
---|
353 | { free_ifh(ifh); return rc; }
|
---|
354 |
|
---|
355 | /* Remember where strips are, and how big they are */
|
---|
356 |
|
---|
357 | n_strips = (gbm->h + (tif_priv->rps - 1)) / tif_priv->rps;
|
---|
358 | if ( tif_priv->photo == PHOTO_RGB && tif_priv->planar == 2 )
|
---|
359 | n_strips *= 3;
|
---|
360 |
|
---|
361 | if ( n_strips <= MAX_STRIPS )
|
---|
362 | for ( strip = 0; strip < n_strips; strip++ )
|
---|
363 | tif_priv->so[strip] = value_of_tag_n(tag_so, strip);
|
---|
364 |
|
---|
365 | if ( tif_priv->comp != ENC_NONE &&
|
---|
366 | tif_priv->comp != ENC_PACKBITS &&
|
---|
367 | tif_priv->comp != ENC_LZW )
|
---|
368 | /*...sreject compression type:16:*/
|
---|
369 | {
|
---|
370 | free_ifh(ifh);
|
---|
371 | switch ( tif_priv->comp )
|
---|
372 | {
|
---|
373 | case ENC_G3_1D_MH: return GBM_ERR_TIF_COMP_1D_MH;
|
---|
374 | case ENC_T4: return GBM_ERR_TIF_COMP_T4 ;
|
---|
375 | case ENC_T6: return GBM_ERR_TIF_COMP_T6 ;
|
---|
376 | default: return GBM_ERR_TIF_COMP ;
|
---|
377 | }
|
---|
378 | }
|
---|
379 | /*...e*/
|
---|
380 |
|
---|
381 | if ( tif_priv->orient != 1 && tif_priv->orient != 4 )
|
---|
382 | { free_ifh(ifh); return GBM_ERR_TIF_ORIENT; }
|
---|
383 |
|
---|
384 | fillorder = (int) value_of_tag_def(ifd, T_FILLORDER, 1L);
|
---|
385 | if ( fillorder != 1 )
|
---|
386 | { free_ifh(ifh); return GBM_ERR_TIF_FILLORDER; }
|
---|
387 |
|
---|
388 | if ( tif_priv->photo == PHOTO_RGB )
|
---|
389 | /* Allow photo of 1 or 2 */
|
---|
390 | {
|
---|
391 | if ( tif_priv->planar != 1 && tif_priv->planar != 2 )
|
---|
392 | { free_ifh(ifh); return GBM_ERR_TIF_PLANARCONFIG_12; }
|
---|
393 | }
|
---|
394 | else
|
---|
395 | /* Allow photo of 1 only */
|
---|
396 | {
|
---|
397 | if ( tif_priv->planar != 1 )
|
---|
398 | { free_ifh(ifh); return GBM_ERR_TIF_PLANARCONFIG_1; }
|
---|
399 | }
|
---|
400 |
|
---|
401 | tif_priv->predictor = (int) value_of_tag_def(ifd, T_PREDICTOR, 1L);
|
---|
402 |
|
---|
403 | /* Only allow predictor of 1, unless a special case we handle */
|
---|
404 | if ( tif_priv->predictor != 1 &&
|
---|
405 | !(tif_priv->comp == ENC_LZW &&
|
---|
406 | tif_priv->bps == 8 &&
|
---|
407 | (tif_priv->spp == 1 || tif_priv->spp >= 3)) )
|
---|
408 | { free_ifh(ifh); return GBM_ERR_TIF_PREDICTOR; }
|
---|
409 |
|
---|
410 | free_ifh(ifh);
|
---|
411 |
|
---|
412 | return GBM_ERR_OK;
|
---|
413 | }
|
---|
414 | /*...e*/
|
---|
415 | /*...stif_rpal:0:*/
|
---|
416 | GBM_ERR tif_rpal(int fd, GBM *gbm, GBMRGB *gbmrgb)
|
---|
417 | {
|
---|
418 | TIF_PRIV *tif_priv = (TIF_PRIV *) gbm->priv;
|
---|
419 |
|
---|
420 | fd=fd; /* Suppress 'unref arg' compiler warning */
|
---|
421 |
|
---|
422 | if ( gbm->bpp != 24 )
|
---|
423 | memcpy(gbmrgb, tif_priv->gbmrgb, (1 << gbm->bpp) * sizeof(GBMRGB));
|
---|
424 |
|
---|
425 | return GBM_ERR_OK;
|
---|
426 | }
|
---|
427 | /*...e*/
|
---|
428 | /*...stif_rdata:0:*/
|
---|
429 | /*
|
---|
430 | TIFF data is usually stored top-left-origin based.
|
---|
431 | ie: We ignore the private "Orientation" tag.
|
---|
432 | Our data format in memory has bigger padding than TIFF.
|
---|
433 | It has 'istride' bytes per line, GBM uses/requires 'stride' bytes per line.
|
---|
434 | Therefore we read it to the part of the strip area and then expand downwards.
|
---|
435 | */
|
---|
436 |
|
---|
437 | /*...sget_strip_packbits \45\ get bytes with packbits decompression:0:*/
|
---|
438 | static GBM_ERR get_strip_packbits(int fd, byte *dest, long n_bytes)
|
---|
439 | {
|
---|
440 | AHEAD *ahead;
|
---|
441 |
|
---|
442 | if ( (ahead = gbm_create_ahead(fd)) == NULL )
|
---|
443 | return GBM_ERR_MEM;
|
---|
444 |
|
---|
445 | while ( n_bytes > 0 )
|
---|
446 | {
|
---|
447 | byte b = (byte) gbm_read_ahead(ahead);
|
---|
448 |
|
---|
449 | if ( b < 0x80 )
|
---|
450 | {
|
---|
451 | unsigned int count = b + 1;
|
---|
452 |
|
---|
453 | do
|
---|
454 | *dest++ = (byte) gbm_read_ahead(ahead);
|
---|
455 | while ( --count > 0 );
|
---|
456 | n_bytes -= (b + 1);
|
---|
457 | }
|
---|
458 | else if ( b > 0x80 )
|
---|
459 | {
|
---|
460 | unsigned int count = 0x101 - (unsigned int) b;
|
---|
461 | byte c = (byte) gbm_read_ahead(ahead);
|
---|
462 |
|
---|
463 | memset(dest, c, count);
|
---|
464 | dest += count;
|
---|
465 | n_bytes -= count;
|
---|
466 | }
|
---|
467 | }
|
---|
468 |
|
---|
469 | gbm_destroy_ahead(ahead);
|
---|
470 | return GBM_ERR_OK;
|
---|
471 | }
|
---|
472 | /*...e*/
|
---|
473 | /*...sget_strip_lzw \45\ get bytes with TIFF style LZW decompression:0:*/
|
---|
474 | /*
|
---|
475 | This code runs on output of FotoTouch and some sample TIFFs from an afs
|
---|
476 | directory on the IBM IP-network.
|
---|
477 | */
|
---|
478 |
|
---|
479 | /*...sread context:0:*/
|
---|
480 | typedef struct
|
---|
481 | {
|
---|
482 | int fd; /* File descriptor to read */
|
---|
483 | int inx, size; /* Index and size in bits */
|
---|
484 | byte buf[255+3]; /* Buffer holding bits */
|
---|
485 | int code_size; /* Number of bits to return at once */
|
---|
486 | cword read_mask; /* 2^code_size-1 */
|
---|
487 | } READ_CONTEXT;
|
---|
488 |
|
---|
489 | static cword read_code(READ_CONTEXT *c)
|
---|
490 | {
|
---|
491 | dword raw_code; int byte_inx;
|
---|
492 |
|
---|
493 | while ( c->inx + c->code_size > c->size )
|
---|
494 | /*...snot enough bits in buffer\44\ refill it:16:*/
|
---|
495 | /* Not very efficient, but infrequently called */
|
---|
496 |
|
---|
497 | {
|
---|
498 | int bytes_to_lose = ((unsigned)c->inx >> 3);
|
---|
499 | int bytes;
|
---|
500 |
|
---|
501 | /* Note biggest code size is 12 bits */
|
---|
502 | /* And this can at worst span 3 bytes */
|
---|
503 | memcpy(c->buf, c->buf + bytes_to_lose, 3);
|
---|
504 | (c->inx) &= 7;
|
---|
505 | (c->size) -= (bytes_to_lose << 3);
|
---|
506 | bytes = 255 - ( (unsigned)c->size >> 3 );
|
---|
507 | if ( (bytes = gbm_file_read(c->fd, c->buf + ((unsigned)c->size >> 3), bytes)) <= 0 )
|
---|
508 | return 0xffff;
|
---|
509 | (c->size) += (bytes << 3);
|
---|
510 | }
|
---|
511 | /*...e*/
|
---|
512 |
|
---|
513 | byte_inx = ((unsigned)c->inx >> 3);
|
---|
514 | raw_code = ((c->buf[byte_inx ]) << 16) +
|
---|
515 | ((c->buf[byte_inx + 1]) << 8) +
|
---|
516 | ( c->buf[byte_inx + 2] ) ;
|
---|
517 | raw_code <<= ((c->inx) & 7);
|
---|
518 | (c->inx) += (byte) (c->code_size);
|
---|
519 | raw_code >>= ( 24 - c->code_size );
|
---|
520 | return (cword) raw_code & c->read_mask;
|
---|
521 | }
|
---|
522 | /*...e*/
|
---|
523 |
|
---|
524 | static GBM_ERR get_strip_lzw(int fd, byte *dest, long n_bytes)
|
---|
525 | {
|
---|
526 | cword max_code; /* 1 << code_size */
|
---|
527 | cword free_code; /* Next available free code slot */
|
---|
528 | int i, out_count = 0;
|
---|
529 | cword code, cur_code, old_code, in_code, fin_char;
|
---|
530 | cword *prefix, *suffix, *outcode;
|
---|
531 | READ_CONTEXT c;
|
---|
532 | BOOLEAN table_full = FALSE;
|
---|
533 | byte *limit = dest+n_bytes;
|
---|
534 |
|
---|
535 | if ( (prefix = (cword *) malloc((size_t) (4096 * sizeof(cword)))) == NULL )
|
---|
536 | return GBM_ERR_MEM;
|
---|
537 | if ( (suffix = (cword *) malloc((size_t) (4096 * sizeof(cword)))) == NULL )
|
---|
538 | {
|
---|
539 | free(prefix);
|
---|
540 | return GBM_ERR_MEM;
|
---|
541 | }
|
---|
542 | if ( (outcode = (cword *) malloc((size_t) (4097 * sizeof(cword)))) == NULL )
|
---|
543 | {
|
---|
544 | free(suffix);
|
---|
545 | free(prefix);
|
---|
546 | return GBM_ERR_MEM;
|
---|
547 | }
|
---|
548 |
|
---|
549 | /* Initial read context */
|
---|
550 |
|
---|
551 | c.inx = 0;
|
---|
552 | c.size = 0;
|
---|
553 | c.fd = fd;
|
---|
554 | c.code_size = INIT_CODE_SIZE;
|
---|
555 | c.read_mask = (cword) ( (1 << INIT_CODE_SIZE) - 1 );
|
---|
556 |
|
---|
557 | /* 2^min_code size accounts for all colours in file */
|
---|
558 |
|
---|
559 | free_code = FIRST_FREE_CODE;
|
---|
560 | max_code = (cword) ( 1 << INIT_CODE_SIZE );
|
---|
561 |
|
---|
562 | LOG(("STRIP\n"));
|
---|
563 | while ( dest < limit && (code = read_code(&c)) != EOI_CODE && code != 0xffff )
|
---|
564 | {
|
---|
565 | if ( code == CLEAR_CODE )
|
---|
566 | {
|
---|
567 | LOG(("CLEARED\n"));
|
---|
568 | c.code_size = INIT_CODE_SIZE;
|
---|
569 | c.read_mask = (cword) ( (1 << INIT_CODE_SIZE) - 1);
|
---|
570 | max_code = (cword) ( 1 << INIT_CODE_SIZE );
|
---|
571 | free_code = FIRST_FREE_CODE;
|
---|
572 | cur_code = old_code = code = read_code(&c);
|
---|
573 | if ( code == EOI_CODE || code == 0xffff )
|
---|
574 | break;
|
---|
575 | fin_char = cur_code;
|
---|
576 | if ( cur_code >= 0x100 )
|
---|
577 | {
|
---|
578 | free(outcode);
|
---|
579 | free(suffix);
|
---|
580 | free(prefix);
|
---|
581 | LOG(("CORRUPT1\n"));
|
---|
582 | return GBM_ERR_TIF_CORRUPT;
|
---|
583 | }
|
---|
584 | *dest++ = (byte) fin_char;
|
---|
585 | LOG(("%02x ", (byte) fin_char));
|
---|
586 | LOG(("%03x:%u\n", code, c.code_size));
|
---|
587 | table_full = FALSE;
|
---|
588 | }
|
---|
589 | else
|
---|
590 | {
|
---|
591 | cur_code = in_code = code;
|
---|
592 | if ( cur_code >= free_code )
|
---|
593 | {
|
---|
594 | cur_code = old_code;
|
---|
595 | outcode[out_count++] = fin_char;
|
---|
596 | }
|
---|
597 | while ( cur_code > 0xff )
|
---|
598 | {
|
---|
599 | if ( out_count > 4096 )
|
---|
600 | {
|
---|
601 | free(outcode);
|
---|
602 | free(suffix);
|
---|
603 | free(prefix);
|
---|
604 | LOG(("CORRUPT2\n"));
|
---|
605 | return GBM_ERR_TIF_CORRUPT;
|
---|
606 | }
|
---|
607 | outcode[out_count++] = suffix[cur_code];
|
---|
608 | cur_code = prefix[cur_code];
|
---|
609 | }
|
---|
610 | fin_char = cur_code;
|
---|
611 | outcode[out_count++] = fin_char;
|
---|
612 | for ( i = out_count - 1; i >= 0; i-- )
|
---|
613 | {
|
---|
614 | *dest++ = (byte) outcode[i];
|
---|
615 | LOG(("%02x ", (byte) outcode[i]));
|
---|
616 | }
|
---|
617 | LOG(("%03x:%u\n", code, c.code_size));
|
---|
618 | out_count = 0;
|
---|
619 |
|
---|
620 | /* Update dictionary */
|
---|
621 |
|
---|
622 | if ( !table_full )
|
---|
623 | {
|
---|
624 | prefix[free_code] = old_code;
|
---|
625 | suffix[free_code] = fin_char;
|
---|
626 |
|
---|
627 | /* Advance to next free slot */
|
---|
628 |
|
---|
629 | if ( ++free_code >= max_code - 1 )
|
---|
630 | {
|
---|
631 | if ( c.code_size < 12 )
|
---|
632 | {
|
---|
633 | c.code_size++;
|
---|
634 | max_code <<= 1;
|
---|
635 | c.read_mask = (cword) (( 1 << c.code_size ) - 1);
|
---|
636 | }
|
---|
637 | else
|
---|
638 | {
|
---|
639 | table_full = TRUE;
|
---|
640 | LOG(("FULL\n"));
|
---|
641 | }
|
---|
642 | }
|
---|
643 | }
|
---|
644 | old_code = in_code;
|
---|
645 | }
|
---|
646 | }
|
---|
647 |
|
---|
648 | free(outcode);
|
---|
649 | free(suffix);
|
---|
650 | free(prefix);
|
---|
651 |
|
---|
652 | if ( dest < limit && code == 0xffff )
|
---|
653 | return GBM_ERR_READ;
|
---|
654 |
|
---|
655 | return GBM_ERR_OK;
|
---|
656 | }
|
---|
657 | /*...e*/
|
---|
658 | /*...sget_strip_lzw_pred \45\ get_strip_lzw with non 1 predictor fixup:0:*/
|
---|
659 | static GBM_ERR get_strip_lzw_pred(
|
---|
660 | int fd,
|
---|
661 | byte *dest,
|
---|
662 | long n_bytes,
|
---|
663 | TIF_PRIV *tif_priv,
|
---|
664 | int w, int h
|
---|
665 | )
|
---|
666 | {
|
---|
667 | GBM_ERR rc;
|
---|
668 |
|
---|
669 | if ( (rc = get_strip_lzw(fd, dest, n_bytes)) != GBM_ERR_OK )
|
---|
670 | return rc;
|
---|
671 |
|
---|
672 | if ( tif_priv->predictor == 2 )
|
---|
673 | /* Note: This is only allowed if bps==8 */
|
---|
674 | {
|
---|
675 | int x, y, spp = tif_priv->spp;
|
---|
676 | for ( y = 0; y < h; y++, dest += w * spp )
|
---|
677 | for ( x = spp; x < w * spp; x++ )
|
---|
678 | dest[x] += dest[x - spp];
|
---|
679 | }
|
---|
680 |
|
---|
681 | return GBM_ERR_OK;
|
---|
682 | }
|
---|
683 | /*...e*/
|
---|
684 | /*...sget_strip_comp \45\ get strip\44\ dealing with any compression:0:*/
|
---|
685 | /* n_bytes is passed in as istride * n_lines */
|
---|
686 |
|
---|
687 | static GBM_ERR get_strip_comp(
|
---|
688 | int fd,
|
---|
689 | byte *dest,
|
---|
690 | long so, long n_bytes,
|
---|
691 | TIF_PRIV *tif_priv,
|
---|
692 | int w, int h
|
---|
693 | )
|
---|
694 | {
|
---|
695 | gbm_file_lseek(fd, so, SEEK_SET);
|
---|
696 | switch ( tif_priv->comp )
|
---|
697 | {
|
---|
698 | /*...sENC_NONE \45\ no compression:16:*/
|
---|
699 | case ENC_NONE:
|
---|
700 | return ( (int) n_bytes == gbm_file_read(fd, dest, (int) n_bytes) ) ?
|
---|
701 | GBM_ERR_OK : GBM_ERR_READ;
|
---|
702 | /*...e*/
|
---|
703 | /*...sENC_PACKBITS \45\ packbits:16:*/
|
---|
704 | case ENC_PACKBITS:
|
---|
705 | return get_strip_packbits(fd, dest, n_bytes);
|
---|
706 | /*...e*/
|
---|
707 | /*...sENC_LZW \45\ lzw:16:*/
|
---|
708 | case ENC_LZW:
|
---|
709 | return get_strip_lzw_pred(fd, dest, n_bytes, tif_priv, w, h);
|
---|
710 | /*...e*/
|
---|
711 | }
|
---|
712 | return GBM_ERR_NOT_SUPP;
|
---|
713 | }
|
---|
714 | /*...e*/
|
---|
715 | /*...sget_strip \45\ get strip\44\ discarding extra samples\44\ and CMYK mapping:0:*/
|
---|
716 | /*
|
---|
717 | If there are too many samples per pixel, this code can ignore the extra ones.
|
---|
718 | Also, if CMYK data is being read, it will read the CMYK, and convert.
|
---|
719 | This requires a temporary buffer, to read the original data in.
|
---|
720 | The original data is then 'converted'.
|
---|
721 | */
|
---|
722 |
|
---|
723 | static GBM_ERR get_strip(
|
---|
724 | int fd,
|
---|
725 | byte *dest,
|
---|
726 | long so, long n_bytes,
|
---|
727 | TIF_PRIV *tif_priv,
|
---|
728 | int w, int h
|
---|
729 | )
|
---|
730 | {
|
---|
731 | byte *buf = dest;
|
---|
732 | GBM_ERR rc;
|
---|
733 |
|
---|
734 | if ( tif_priv->photo == PHOTO_CMYK )
|
---|
735 | /*...sallocate space for CMYK image:16:*/
|
---|
736 | {
|
---|
737 | n_bytes = (long) w * 4L * (long) h;
|
---|
738 | if ( (buf = malloc((size_t) n_bytes)) == NULL )
|
---|
739 | return GBM_ERR_MEM;
|
---|
740 | }
|
---|
741 | /*...e*/
|
---|
742 | else if ( tif_priv->photo == PHOTO_RGB && tif_priv->spp > 3 )
|
---|
743 | /*...sallocate space for image \43\ extra samples:16:*/
|
---|
744 | {
|
---|
745 | n_bytes = (long) w * tif_priv->spp * (long) h;
|
---|
746 | if ( (buf = malloc((size_t) n_bytes)) == NULL )
|
---|
747 | return GBM_ERR_MEM;
|
---|
748 | }
|
---|
749 | /*...e*/
|
---|
750 |
|
---|
751 | if ( (rc = get_strip_comp(fd, buf, so, n_bytes, tif_priv, w, h)) != GBM_ERR_OK )
|
---|
752 | {
|
---|
753 | if ( buf != dest )
|
---|
754 | free(buf);
|
---|
755 | return rc;
|
---|
756 | }
|
---|
757 |
|
---|
758 | if ( tif_priv->photo == PHOTO_CMYK )
|
---|
759 | /*...sconvert from CMYK to RGB:16:*/
|
---|
760 | {
|
---|
761 | int x, yy;
|
---|
762 | byte *buf_p = buf, *dest_p = dest;
|
---|
763 | for ( yy = 0; yy < h; yy++ )
|
---|
764 | for ( x = 0; x < w; x++ )
|
---|
765 | {
|
---|
766 | word c = *buf_p++;
|
---|
767 | word m = *buf_p++;
|
---|
768 | word y = *buf_p++;
|
---|
769 | word k = *buf_p++;
|
---|
770 |
|
---|
771 | /* Exploit 8 bit modulo arithmetic by biasing by + 0x100 */
|
---|
772 |
|
---|
773 | word r = 0x1ff - (c + k);
|
---|
774 | word g = 0x1ff - (m + k);
|
---|
775 | word b = 0x1ff - (y + k);
|
---|
776 |
|
---|
777 | if ( r < 0x100 ) r = 0x100;
|
---|
778 | if ( g < 0x100 ) g = 0x100;
|
---|
779 | if ( b < 0x100 ) b = 0x100;
|
---|
780 |
|
---|
781 | *dest_p++ = (byte) r;
|
---|
782 | *dest_p++ = (byte) g;
|
---|
783 | *dest_p++ = (byte) b;
|
---|
784 | }
|
---|
785 |
|
---|
786 | free(buf);
|
---|
787 | }
|
---|
788 | /*...e*/
|
---|
789 | else if ( tif_priv->photo == PHOTO_RGB && tif_priv->spp > 3 )
|
---|
790 | /*...sextract\44\ ignoring extra\45\samples:16:*/
|
---|
791 | {
|
---|
792 | int x, y, skip = tif_priv->spp - 2;
|
---|
793 | byte *buf_p = buf, *dest_p = dest;
|
---|
794 | for ( y = 0; y < h; y++ )
|
---|
795 | for ( x = 0; x < w; x++ )
|
---|
796 | {
|
---|
797 | *dest_p++ = *buf_p++;
|
---|
798 | *dest_p++ = *buf_p++;
|
---|
799 | *dest_p++ = *buf_p ;
|
---|
800 | buf_p += skip;
|
---|
801 | }
|
---|
802 |
|
---|
803 | free(buf);
|
---|
804 | }
|
---|
805 | /*...e*/
|
---|
806 |
|
---|
807 | return GBM_ERR_OK;
|
---|
808 | }
|
---|
809 | /*...e*/
|
---|
810 | /*...sget_image \45\ get all strips\44\ result is whole image:0:*/
|
---|
811 | /*
|
---|
812 | This routine calls get_strip() to get strips data one after another until it
|
---|
813 | has read the entire images worth of data. Of course, scan lines are aligned on
|
---|
814 | byte boundaries, and the data is usually considered to be image top to bottom.
|
---|
815 | */
|
---|
816 |
|
---|
817 | static GBM_ERR get_image(
|
---|
818 | int fd,
|
---|
819 | byte *dest,
|
---|
820 | TIF_PRIV *tif_priv,
|
---|
821 | long *so,
|
---|
822 | GBM *gbm,
|
---|
823 | int *strip
|
---|
824 | )
|
---|
825 | {
|
---|
826 | GBM_ERR rc;
|
---|
827 | int y, istride = ((gbm->w * gbm->bpp + 7) / 8);
|
---|
828 |
|
---|
829 | for ( y = 0; y < gbm->h; y += tif_priv->rps, (*strip)++ )
|
---|
830 | {
|
---|
831 | int n_lines = min(tif_priv->rps, gbm->h - y);
|
---|
832 | if ( (rc = get_strip(fd, dest + y * istride,
|
---|
833 | so[*strip],
|
---|
834 | (long) n_lines * (long) istride,
|
---|
835 | tif_priv,
|
---|
836 | gbm->w, n_lines)) != GBM_ERR_OK )
|
---|
837 | return rc;
|
---|
838 | }
|
---|
839 |
|
---|
840 | return GBM_ERR_OK;
|
---|
841 | }
|
---|
842 | /*...e*/
|
---|
843 | /*...sget_image_planar \45\ get all strips\44\ allowing for PlanarConfiguration:0:*/
|
---|
844 | /*
|
---|
845 | get_image() will assume the data is in PlanarConfiguration==1, ie: chunky
|
---|
846 | pixel mode. This is TRUE most of the time. But sometimes we will actually
|
---|
847 | allow PlanarConfiguration==2. In this case, use get_image() and then fix-up
|
---|
848 | the results.
|
---|
849 | */
|
---|
850 |
|
---|
851 | static GBM_ERR get_image_planar(
|
---|
852 | int fd,
|
---|
853 | byte *dest,
|
---|
854 | TIF_PRIV *tif_priv,
|
---|
855 | long *so,
|
---|
856 | GBM *gbm
|
---|
857 | )
|
---|
858 | {
|
---|
859 | int strip = 0;
|
---|
860 |
|
---|
861 | if ( tif_priv->photo == PHOTO_RGB &&
|
---|
862 | tif_priv->planar == 2 )
|
---|
863 | /*...sread 3 seperate planes\44\ and combine them:16:*/
|
---|
864 | /*
|
---|
865 | If PhotometricInterpretation==RGB and
|
---|
866 | SamplesPerPixel>=3 and
|
---|
867 | BitsPerSample==8 then
|
---|
868 | we allow PlanarConfiguration==2
|
---|
869 |
|
---|
870 | I have successfully read in a PlanarConfiguration==2 RGB TIFF file by using
|
---|
871 | the "read 3 images" logic below. This image had RowsPerStrip==1, and so
|
---|
872 | technically either fold below would have worked. I think the read 3 images
|
---|
873 | logic is a better interpretation of the TIFF 6.0 spec., but until I find
|
---|
874 | some other images I can handle, I will keep the alternative peice of code.
|
---|
875 | */
|
---|
876 |
|
---|
877 | {
|
---|
878 | GBM_ERR rc;
|
---|
879 | GBM gbm_planar;
|
---|
880 | int saved_spp = tif_priv->spp;
|
---|
881 | int n_bytes = gbm->w * gbm->h;
|
---|
882 | int x, y;
|
---|
883 | byte *buf, *p[3];
|
---|
884 |
|
---|
885 | if ( (buf = malloc((size_t) (n_bytes * 3))) == NULL )
|
---|
886 | return GBM_ERR_MEM;
|
---|
887 | p[0] = buf;
|
---|
888 | p[1] = p[0] + n_bytes;
|
---|
889 | p[2] = p[1] + n_bytes;
|
---|
890 |
|
---|
891 | tif_priv->spp = 1;
|
---|
892 | /*...sread 3 images:16:*/
|
---|
893 | {
|
---|
894 | int i;
|
---|
895 |
|
---|
896 | gbm_planar.w = gbm->w;
|
---|
897 | gbm_planar.h = gbm->h;
|
---|
898 | gbm_planar.bpp = 8;
|
---|
899 | for ( i = 0; i < 3; i++ )
|
---|
900 | if ( (rc = get_image(fd, p[i], tif_priv, so, &gbm_planar, &strip)) != GBM_ERR_OK )
|
---|
901 | {
|
---|
902 | tif_priv->spp = saved_spp;
|
---|
903 | free(buf);
|
---|
904 | return rc;
|
---|
905 | }
|
---|
906 | }
|
---|
907 | /*...e*/
|
---|
908 | #ifdef NEVER
|
---|
909 | /*...sread single image 3x too high:16:*/
|
---|
910 | gbm_planar.w = gbm->w;
|
---|
911 | gbm_planar.h = gbm->h * 3;
|
---|
912 | gbm_planar.bpp = 8;
|
---|
913 | if ( (rc = get_image(fd, buf, tif_priv, so, &gbm_planar, &strip)) != GBM_ERR_OK )
|
---|
914 | {
|
---|
915 | tif_priv->spp = saved_spp;
|
---|
916 | free(buf);
|
---|
917 | return rc;
|
---|
918 | }
|
---|
919 | /*...e*/
|
---|
920 | #endif
|
---|
921 | tif_priv->spp = saved_spp;
|
---|
922 |
|
---|
923 | for ( y = 0; y < gbm->h; y++ )
|
---|
924 | for ( x = 0; x < gbm->w; x++ )
|
---|
925 | {
|
---|
926 | *dest++ = *(p[0])++;
|
---|
927 | *dest++ = *(p[1])++;
|
---|
928 | *dest++ = *(p[2])++;
|
---|
929 | }
|
---|
930 | free(buf);
|
---|
931 | return GBM_ERR_OK;
|
---|
932 | }
|
---|
933 | /*...e*/
|
---|
934 | else
|
---|
935 | return get_image(fd, dest, tif_priv, so, gbm, &strip);
|
---|
936 | }
|
---|
937 | /*...e*/
|
---|
938 | /*...sget_image_orient \45\ get all strips\44\ correctly orientated:0:*/
|
---|
939 | static GBM_ERR get_image_orient(
|
---|
940 | int fd,
|
---|
941 | byte *dest,
|
---|
942 | TIF_PRIV *tif_priv,
|
---|
943 | long *so,
|
---|
944 | GBM *gbm
|
---|
945 | )
|
---|
946 | {
|
---|
947 | switch ( tif_priv->orient )
|
---|
948 | {
|
---|
949 | /*...s1 \45\ usual Baseline required case:16:*/
|
---|
950 | /*
|
---|
951 | File has array[scanlines_down] of array[pixels_across] of pixel.
|
---|
952 | GBMs bitmap data is array[scanlines_up] of array[pixels_across] of pixel.
|
---|
953 | So call get_image_planar(), and vertically reflect resulting data.
|
---|
954 | */
|
---|
955 |
|
---|
956 | case 1:
|
---|
957 | {
|
---|
958 | int istride = ((gbm->bpp * gbm->w + 7) / 8);
|
---|
959 | byte *p0, *p1, *p2;
|
---|
960 | GBM_ERR rc;
|
---|
961 | if ( (rc = get_image_planar(fd, dest, tif_priv, so, gbm)) != GBM_ERR_OK )
|
---|
962 | return rc;
|
---|
963 | if ( (p0 = malloc((size_t) istride)) == NULL )
|
---|
964 | return GBM_ERR_MEM;
|
---|
965 | for ( p1 = dest, p2 = p1 + (gbm->h - 1) * istride;
|
---|
966 | p1 < p2;
|
---|
967 | p1 += istride, p2 -= istride )
|
---|
968 | {
|
---|
969 | memcpy(p0, p1, istride);
|
---|
970 | memcpy(p1, p2, istride);
|
---|
971 | memcpy(p2, p0, istride);
|
---|
972 | }
|
---|
973 | free(p0);
|
---|
974 | return GBM_ERR_OK;
|
---|
975 | }
|
---|
976 | /*...e*/
|
---|
977 | /*...s4 \45\ vertically swapped case we can easily handle:16:*/
|
---|
978 | /*
|
---|
979 | File has array[scanlines_up] of array[pixels_across] of pixel.
|
---|
980 | Exactly matches GBMs layout of a bitmap.
|
---|
981 | So simply call get_image() and be done with.
|
---|
982 | */
|
---|
983 |
|
---|
984 | case 4:
|
---|
985 | return get_image_planar(fd, dest, tif_priv, so, gbm);
|
---|
986 | /*...e*/
|
---|
987 | }
|
---|
988 | return GBM_ERR_NOT_SUPP; /* Shouldn't get here */
|
---|
989 | }
|
---|
990 | /*...e*/
|
---|
991 | /*...sget_image_strippy \45\ get all strips\44\ when there are loads of them:0:*/
|
---|
992 | static GBM_ERR get_image_strippy(
|
---|
993 | int fd,
|
---|
994 | byte *dest,
|
---|
995 | TIF_PRIV *tif_priv,
|
---|
996 | GBM *gbm
|
---|
997 | )
|
---|
998 | {
|
---|
999 | int n_strips = (gbm->h + (tif_priv->rps - 1)) / tif_priv->rps;
|
---|
1000 | long *so = tif_priv->so;
|
---|
1001 |
|
---|
1002 | if ( n_strips > MAX_STRIPS )
|
---|
1003 | /*...sre\45\read TIFF file header:16:*/
|
---|
1004 | {
|
---|
1005 | GBM_ERR rc;
|
---|
1006 | int strip;
|
---|
1007 | IFH *ifh;
|
---|
1008 | IFD *ifd;
|
---|
1009 | TAG *tag_so;
|
---|
1010 |
|
---|
1011 | if ( (so = malloc((size_t) (n_strips * sizeof(long)))) == NULL )
|
---|
1012 | return GBM_ERR_MEM;
|
---|
1013 |
|
---|
1014 | gbm_file_lseek(fd, 0L, SEEK_SET);
|
---|
1015 | if ( read_ifh_and_ifd(fd, tif_priv->inx, &ifh) != TE_OK )
|
---|
1016 | {
|
---|
1017 | free(so);
|
---|
1018 | return GBM_ERR_MEM;
|
---|
1019 | }
|
---|
1020 | ifd = ifh->ifd;
|
---|
1021 | tag_so = locate_tag(ifd, T_STRIPOFFSETS);
|
---|
1022 | for ( strip = 0; strip < n_strips; strip++ )
|
---|
1023 | so[strip] = value_of_tag_n(tag_so, strip);
|
---|
1024 | free_ifh(ifh);
|
---|
1025 |
|
---|
1026 | rc = get_image_orient(fd, dest, tif_priv, so, gbm);
|
---|
1027 |
|
---|
1028 | free(so);
|
---|
1029 | return rc;
|
---|
1030 | }
|
---|
1031 | /*...e*/
|
---|
1032 | else
|
---|
1033 | return get_image_orient(fd, dest, tif_priv, so, gbm);
|
---|
1034 | }
|
---|
1035 | /*...e*/
|
---|
1036 |
|
---|
1037 | GBM_ERR tif_rdata(int fd, GBM *gbm, byte *data)
|
---|
1038 | {
|
---|
1039 | TIF_PRIV *tif_priv = (TIF_PRIV *) gbm->priv;
|
---|
1040 | int stride = ((gbm->bpp * gbm->w + 31) / 32) * 4;
|
---|
1041 | int istride = ((gbm->bpp * gbm->w + 7) / 8);
|
---|
1042 | int bias = gbm->h * (stride - istride);
|
---|
1043 | GBM_ERR rc;
|
---|
1044 |
|
---|
1045 | /* Read in data, packed close, and upside down */
|
---|
1046 |
|
---|
1047 | if ( (rc = get_image_strippy(fd, data + bias, tif_priv, gbm)) != GBM_ERR_OK )
|
---|
1048 | return rc;
|
---|
1049 |
|
---|
1050 | /*...snow expand out from byte padding to dword padding:8:*/
|
---|
1051 | if ( bias )
|
---|
1052 | {
|
---|
1053 | int y;
|
---|
1054 | byte *dest = data, *src = data + bias;
|
---|
1055 |
|
---|
1056 | for ( y = 0; y < gbm->h; y++, dest += stride, src += istride )
|
---|
1057 | memcpy(dest, src, istride);
|
---|
1058 | }
|
---|
1059 | /*...e*/
|
---|
1060 | /*...snow RGB\45\\62\BGR if 24 bit data returned:8:*/
|
---|
1061 | if ( gbm->bpp == 24 )
|
---|
1062 | {
|
---|
1063 | int y;
|
---|
1064 | byte *p = data;
|
---|
1065 |
|
---|
1066 | for ( y = 0; y < gbm->h; y++, p += stride )
|
---|
1067 | rgb_bgr(p, p, gbm->w);
|
---|
1068 | }
|
---|
1069 | /*...e*/
|
---|
1070 |
|
---|
1071 | return GBM_ERR_OK;
|
---|
1072 | }
|
---|
1073 | /*...e*/
|
---|
1074 | /*...stif_w:0:*/
|
---|
1075 | /*
|
---|
1076 | Write out data in a single large strip for now.
|
---|
1077 | Note that the palette entrys are written as ((r << 8) | r).
|
---|
1078 | This means they are 257/256 too big (insignificant).
|
---|
1079 | Most programs only look at the top 8 bits (ie: no error).
|
---|
1080 | A few (incorrectly) look at the bottom 8 bits.
|
---|
1081 | Therefore we cater for all programs, with minimal fuss.
|
---|
1082 | */
|
---|
1083 |
|
---|
1084 | /*...suser_tag:0:*/
|
---|
1085 | static BOOLEAN user_tag(IFD *ifd, char *name, short type, const char *opt, char *def)
|
---|
1086 | {
|
---|
1087 | char buf[200+1];
|
---|
1088 | const char *s;
|
---|
1089 |
|
---|
1090 | if ( (s = gbm_find_word_prefix(opt, name)) != NULL )
|
---|
1091 | sscanf(s + strlen(name), "%s", buf);
|
---|
1092 | else
|
---|
1093 | strcpy(buf, def);
|
---|
1094 |
|
---|
1095 | if ( *buf == '\0' )
|
---|
1096 | return TRUE;
|
---|
1097 |
|
---|
1098 | return add_ascii_tag(ifd, type, buf);
|
---|
1099 | }
|
---|
1100 | /*...e*/
|
---|
1101 | /*...swrite_strip:0:*/
|
---|
1102 | static GBM_ERR write_strip(int fd, int w, int h, int bpp, const byte *data)
|
---|
1103 | {
|
---|
1104 | int stride = ((bpp * w + 31) / 32) * 4;
|
---|
1105 | int ostride = ((bpp * w + 7) / 8);
|
---|
1106 | int y;
|
---|
1107 | data += ((h - 1) * stride);
|
---|
1108 | if ( bpp == 24 )
|
---|
1109 | /*...sreverse rgb\47\bgr ordering and write:16:*/
|
---|
1110 | {
|
---|
1111 | byte *line;
|
---|
1112 |
|
---|
1113 | if ( (line = malloc((size_t) ostride)) == NULL )
|
---|
1114 | return GBM_ERR_MEM;
|
---|
1115 | for ( y = 0; y < h; y++, data -= stride )
|
---|
1116 | {
|
---|
1117 | rgb_bgr(data, line, w);
|
---|
1118 | if ( gbm_file_write(fd, line, ostride) != ostride )
|
---|
1119 | {
|
---|
1120 | free(line);
|
---|
1121 | return GBM_ERR_WRITE;
|
---|
1122 | }
|
---|
1123 | }
|
---|
1124 | free(line);
|
---|
1125 | }
|
---|
1126 | /*...e*/
|
---|
1127 | else
|
---|
1128 | /*...swrite:16:*/
|
---|
1129 | for ( y = 0; y < h; y++, data -= stride )
|
---|
1130 | if ( gbm_file_write(fd, data, ostride) != ostride )
|
---|
1131 | return GBM_ERR_WRITE;
|
---|
1132 | /*...e*/
|
---|
1133 | return GBM_ERR_OK;
|
---|
1134 | }
|
---|
1135 | /*...e*/
|
---|
1136 | /*...swrite_strip_lzw \45\ new fast tail\43\col lookup version:0:*/
|
---|
1137 | /*
|
---|
1138 | This is a tricky bit of code to get right.
|
---|
1139 | This code blantantly copied and hacked from that in gbmgif.c!
|
---|
1140 | hashvalue is calculated from a string of pixels cumulatively.
|
---|
1141 | hashtable is searched starting at index hashvalue for to find the entry.
|
---|
1142 | hashtable is big enough so that MAX_HASH > 4*MAX_DICT.
|
---|
1143 | */
|
---|
1144 |
|
---|
1145 | /*...swrite context:0:*/
|
---|
1146 | #define L_BUF 1024
|
---|
1147 |
|
---|
1148 | typedef struct
|
---|
1149 | {
|
---|
1150 | int fd; /* Open file descriptor to write to */
|
---|
1151 | int inx; /* Bit index into buf */
|
---|
1152 | int code_size; /* Code size in bits */
|
---|
1153 | byte buf[L_BUF+2]; /* Biggest block + overflow space */
|
---|
1154 | } WRITE_CONTEXT;
|
---|
1155 |
|
---|
1156 | static BOOLEAN write_code(cword code, WRITE_CONTEXT *w)
|
---|
1157 | {
|
---|
1158 | byte *buf = w->buf + ((unsigned)w->inx >> 3);
|
---|
1159 |
|
---|
1160 | LOG(("%03x:%u\n", code, w->code_size));
|
---|
1161 | code <<= (24-w->code_size);
|
---|
1162 | code >>= (w->inx&7U);
|
---|
1163 | *buf++ |= (byte) (code >> 16);
|
---|
1164 | *buf++ = (byte) (code >> 8);
|
---|
1165 | *buf = (byte) code ;
|
---|
1166 |
|
---|
1167 | (w->inx) += (w->code_size);
|
---|
1168 | if ( w->inx >= L_BUF * 8 )
|
---|
1169 | /* Flush out full buffer */
|
---|
1170 | {
|
---|
1171 | if ( gbm_file_write(w->fd, w->buf, L_BUF) != L_BUF )
|
---|
1172 | return FALSE;
|
---|
1173 | memcpy(w->buf, w->buf + L_BUF, 2);
|
---|
1174 | memset(w->buf + 2, 0, L_BUF);
|
---|
1175 | (w->inx) -= (L_BUF * 8);
|
---|
1176 | }
|
---|
1177 |
|
---|
1178 | return TRUE;
|
---|
1179 | }
|
---|
1180 |
|
---|
1181 | static BOOLEAN flush_code(WRITE_CONTEXT *w)
|
---|
1182 | {
|
---|
1183 | int bytes = (((unsigned)w->inx + 7) >> 3);
|
---|
1184 |
|
---|
1185 | if ( bytes )
|
---|
1186 | {
|
---|
1187 | if ( gbm_file_write(w->fd, w->buf, bytes) != bytes )
|
---|
1188 | return FALSE;
|
---|
1189 | }
|
---|
1190 |
|
---|
1191 | return TRUE;
|
---|
1192 | }
|
---|
1193 | /*...e*/
|
---|
1194 |
|
---|
1195 | #define MAX_HASH 17777 /* Probably prime, and > 4096 */
|
---|
1196 | #define MAX_DICT 4096 /* Dictionary size */
|
---|
1197 | #define INIT_HASH(p) (((p)+3)*301) /* Initial hash value */
|
---|
1198 |
|
---|
1199 | typedef struct { cword tail; byte col; } DICT;
|
---|
1200 |
|
---|
1201 | static GBM_ERR write_strip_lzw(int fd, int w, int h, int bpp, const byte *data)
|
---|
1202 | {
|
---|
1203 | int stride = ((bpp * w + 31) / 32) * 4;
|
---|
1204 | int ostride = ((bpp * w + 7) / 8);
|
---|
1205 | WRITE_CONTEXT wc;
|
---|
1206 | cword last_code, max_code, tail;
|
---|
1207 | int x, y;
|
---|
1208 | unsigned int hashvalue, lenstring, j;
|
---|
1209 | DICT *dict, **hashtable;
|
---|
1210 |
|
---|
1211 | if ( (dict = (DICT *) malloc((size_t) (MAX_DICT * sizeof(DICT)))) == NULL )
|
---|
1212 | return GBM_ERR_MEM;
|
---|
1213 |
|
---|
1214 | if ( (hashtable = (DICT **) malloc((size_t) (MAX_HASH * sizeof(DICT *)))) == NULL )
|
---|
1215 | {
|
---|
1216 | free(dict);
|
---|
1217 | return GBM_ERR_MEM;
|
---|
1218 | }
|
---|
1219 |
|
---|
1220 | /* Setup write context */
|
---|
1221 |
|
---|
1222 | wc.fd = fd;
|
---|
1223 | wc.inx = 0;
|
---|
1224 | wc.code_size = INIT_CODE_SIZE;
|
---|
1225 | memset(wc.buf, 0, sizeof(wc.buf));
|
---|
1226 |
|
---|
1227 | if ( !write_code(CLEAR_CODE, &wc) )
|
---|
1228 | {
|
---|
1229 | free(hashtable);
|
---|
1230 | free(dict);
|
---|
1231 | return GBM_ERR_WRITE;
|
---|
1232 | }
|
---|
1233 |
|
---|
1234 | last_code = EOI_CODE;
|
---|
1235 | max_code = ( 1 << INIT_CODE_SIZE );
|
---|
1236 | lenstring = 0;
|
---|
1237 |
|
---|
1238 | for ( j = 0; j < MAX_HASH; j++ )
|
---|
1239 | hashtable[j] = NULL;
|
---|
1240 |
|
---|
1241 | data += ( (h - 1) * stride );
|
---|
1242 | for ( y = h - 1; y >= 0; y--, data -= stride )
|
---|
1243 | {
|
---|
1244 | int inx1 = 0, inx2 = 2;
|
---|
1245 | for ( x = 0; x < ostride; x++ )
|
---|
1246 | {
|
---|
1247 | byte col;
|
---|
1248 | /*...sget byte to write to col:24:*/
|
---|
1249 | if ( bpp == 24 )
|
---|
1250 | /* Have to handle rgb/bgr reverse as we go along */
|
---|
1251 | {
|
---|
1252 | col = data[inx1+inx2];
|
---|
1253 | if ( --inx2 < 0 )
|
---|
1254 | {
|
---|
1255 | inx1 += 3; inx2 = 2;
|
---|
1256 | }
|
---|
1257 | }
|
---|
1258 | else
|
---|
1259 | col = data[x];
|
---|
1260 | /*...e*/
|
---|
1261 | /*...sLZW encode:24:*/
|
---|
1262 | if ( ++lenstring == 1 )
|
---|
1263 | {
|
---|
1264 | tail = col;
|
---|
1265 | hashvalue = INIT_HASH(col);
|
---|
1266 | }
|
---|
1267 | else
|
---|
1268 | {
|
---|
1269 | hashvalue *= ( col + lenstring + 4 );
|
---|
1270 | j = ( hashvalue %= MAX_HASH );
|
---|
1271 | while ( hashtable[j] != NULL &&
|
---|
1272 | ( hashtable[j]->tail != tail ||
|
---|
1273 | hashtable[j]->col != col ) )
|
---|
1274 | if ( ++j >= MAX_HASH )
|
---|
1275 | j = 0;
|
---|
1276 | if ( hashtable[j] != NULL )
|
---|
1277 | /* Found in the strings table */
|
---|
1278 | {
|
---|
1279 | tail = (hashtable[j]-dict);
|
---|
1280 | LOG(("%02x ", col));
|
---|
1281 | }
|
---|
1282 | else
|
---|
1283 | /* Not found */
|
---|
1284 | {
|
---|
1285 | if ( !write_code(tail, &wc) )
|
---|
1286 | {
|
---|
1287 | free(hashtable);
|
---|
1288 | free(dict);
|
---|
1289 | return GBM_ERR_WRITE;
|
---|
1290 | }
|
---|
1291 | hashtable[j] = dict + ++last_code;
|
---|
1292 | hashtable[j]->tail = tail;
|
---|
1293 | hashtable[j]->col = col;
|
---|
1294 | LOG(("%02x ", col));
|
---|
1295 | tail = col;
|
---|
1296 | hashvalue = INIT_HASH(col);
|
---|
1297 | lenstring = 1;
|
---|
1298 |
|
---|
1299 | /* Note: Things change 1 earlier than in the GIF LZW case, hence -1. */
|
---|
1300 | if ( last_code >= max_code -1 )
|
---|
1301 | /* Next code will be written longer */
|
---|
1302 | {
|
---|
1303 | max_code <<= 1;
|
---|
1304 | wc.code_size++;
|
---|
1305 | }
|
---|
1306 | else if ( last_code >= MAX_DICT-2 )
|
---|
1307 | /* Reset tables */
|
---|
1308 | {
|
---|
1309 | if ( !write_code(tail , &wc) ||
|
---|
1310 | !write_code(CLEAR_CODE, &wc) )
|
---|
1311 | {
|
---|
1312 | free(hashtable);
|
---|
1313 | free(dict);
|
---|
1314 | return GBM_ERR_WRITE;
|
---|
1315 | }
|
---|
1316 | lenstring = 0;
|
---|
1317 | last_code = EOI_CODE;
|
---|
1318 | wc.code_size = INIT_CODE_SIZE;
|
---|
1319 | max_code = ( 1 << INIT_CODE_SIZE );
|
---|
1320 | for ( j = 0; j < MAX_HASH; j++ )
|
---|
1321 | hashtable[j] = NULL;
|
---|
1322 | }
|
---|
1323 | }
|
---|
1324 | }
|
---|
1325 | /*...e*/
|
---|
1326 | }
|
---|
1327 | }
|
---|
1328 |
|
---|
1329 | free(hashtable);
|
---|
1330 | free(dict);
|
---|
1331 |
|
---|
1332 | if ( lenstring != 0 )
|
---|
1333 | /* Only write tail if no code written for some input */
|
---|
1334 | {
|
---|
1335 | if ( !write_code(tail, &wc) )
|
---|
1336 | return GBM_ERR_WRITE;
|
---|
1337 | if ( ++last_code >= max_code -1 )
|
---|
1338 | /* Next code will be written longer */
|
---|
1339 | wc.code_size++;
|
---|
1340 | }
|
---|
1341 |
|
---|
1342 | if ( !write_code(EOI_CODE, &wc) ||
|
---|
1343 | !flush_code( &wc) )
|
---|
1344 | return GBM_ERR_WRITE;
|
---|
1345 |
|
---|
1346 | return GBM_ERR_OK;
|
---|
1347 | }
|
---|
1348 | /*...e*/
|
---|
1349 |
|
---|
1350 | GBM_ERR tif_w(const char *fn, int fd, const GBM *gbm, const GBMRGB *gbmrgb, const byte *data, const char *opt)
|
---|
1351 | {
|
---|
1352 | BOOLEAN baseline = ( gbm_find_word(opt, "pal1bpp") == NULL );
|
---|
1353 | BOOLEAN lzw = ( gbm_find_word(opt, "lzw" ) != NULL );
|
---|
1354 | IFH *ifh;
|
---|
1355 | IFD *ifd;
|
---|
1356 | long w = gbm->w;
|
---|
1357 | long h = gbm->h;
|
---|
1358 | long stripoffset, stripbytecount;
|
---|
1359 | short samplesperpixel, bitspersample[3], photo, comp;
|
---|
1360 | short colormap[0x100+0x100+0x100];
|
---|
1361 | BOOLEAN ok;
|
---|
1362 | GBM_ERR rc;
|
---|
1363 |
|
---|
1364 | fn=fn; /* Suppress 'unref arg' compiler warning */
|
---|
1365 |
|
---|
1366 | if ( (ifh = make_ifh()) == NULL )
|
---|
1367 | return GBM_ERR_MEM;
|
---|
1368 |
|
---|
1369 | ifd = ifh->ifd;
|
---|
1370 |
|
---|
1371 | if ( gbm->bpp == 1 && baseline )
|
---|
1372 | {
|
---|
1373 | word k0 = (word) gbmrgb[0].r + (word) gbmrgb[0].g + (word) gbmrgb[0].b;
|
---|
1374 | word k1 = (word) gbmrgb[1].r + (word) gbmrgb[1].g + (word) gbmrgb[1].b;
|
---|
1375 | samplesperpixel = 1;
|
---|
1376 | bitspersample[0] = 1;
|
---|
1377 | photo = ( k0 < k1 ) ? PHOTO_BIT1 : PHOTO_BIT0; /* Black is zero : White is zero */
|
---|
1378 | }
|
---|
1379 | else if ( gbm->bpp == 24 )
|
---|
1380 | {
|
---|
1381 | samplesperpixel = 3;
|
---|
1382 | bitspersample[0] =
|
---|
1383 | bitspersample[1] =
|
---|
1384 | bitspersample[2] = 8;
|
---|
1385 | photo = PHOTO_RGB;
|
---|
1386 | }
|
---|
1387 | else
|
---|
1388 | {
|
---|
1389 | samplesperpixel = 1;
|
---|
1390 | bitspersample[0] = (short) gbm->bpp;
|
---|
1391 | photo = PHOTO_PAL;
|
---|
1392 | }
|
---|
1393 |
|
---|
1394 | comp = ( lzw ) ? ENC_LZW : ENC_NONE;
|
---|
1395 |
|
---|
1396 | ok = add_long_tag(ifd, T_IMAGEWIDTH, &w, 1) &&
|
---|
1397 | add_long_tag(ifd, T_IMAGELENGTH, &h, 1) &&
|
---|
1398 | add_long_tag(ifd, T_STRIPOFFSETS, &stripoffset, 1) &&
|
---|
1399 | add_long_tag(ifd, T_STRIPBYTECOUNTS, &stripbytecount, 1) &&
|
---|
1400 | add_short_tag(ifd, T_SAMPLESPERPIXEL, &samplesperpixel, 1) &&
|
---|
1401 | add_short_tag(ifd, T_BITSPERSAMPLE, bitspersample, samplesperpixel) &&
|
---|
1402 | add_short_tag(ifd, T_PHOTOMETRIC, &photo, 1) &&
|
---|
1403 | add_short_tag(ifd, T_COMPRESSION, &comp, 1) &&
|
---|
1404 | user_tag(ifd, "artist=", T_ARTIST, opt, "") &&
|
---|
1405 | user_tag(ifd, "software=", T_MAKE, opt, "") &&
|
---|
1406 | user_tag(ifd, "make=", T_MAKE, opt, "") &&
|
---|
1407 | user_tag(ifd, "model=", T_MODEL, opt, "") &&
|
---|
1408 | user_tag(ifd, "hostcomputer=", T_HOSTCOMPUTER, opt, "") &&
|
---|
1409 | user_tag(ifd, "documentname=", T_DOCNAME, opt, "") &&
|
---|
1410 | user_tag(ifd, "pagename=", T_PAGENAME, opt, "") &&
|
---|
1411 | user_tag(ifd, "imagedescription=", T_DESCRIPTION, opt, "");
|
---|
1412 |
|
---|
1413 | if ( gbm->bpp != 24 )
|
---|
1414 | {
|
---|
1415 | int i, n_cols = (1 << gbm->bpp);
|
---|
1416 |
|
---|
1417 | for ( i = 0; i < n_cols; i++ )
|
---|
1418 | {
|
---|
1419 | short r = (short) gbmrgb[i].r;
|
---|
1420 | short g = (short) gbmrgb[i].g;
|
---|
1421 | short b = (short) gbmrgb[i].b;
|
---|
1422 |
|
---|
1423 | colormap[ i] = ((r << 8) | r);
|
---|
1424 | colormap[ n_cols + i] = ((g << 8) | g);
|
---|
1425 | colormap[2 * n_cols + i] = ((b << 8) | b);
|
---|
1426 | }
|
---|
1427 | if ( gbm->bpp != 1 || !baseline )
|
---|
1428 | ok &= add_short_tag(ifd, T_COLORMAP, colormap, n_cols * 3);
|
---|
1429 | }
|
---|
1430 |
|
---|
1431 | if ( !ok )
|
---|
1432 | {
|
---|
1433 | free_ifh(ifh);
|
---|
1434 | return GBM_ERR_MEM;
|
---|
1435 | }
|
---|
1436 |
|
---|
1437 | if ( !write_ifh_and_ifd(ifh, fd) )
|
---|
1438 | {
|
---|
1439 | free_ifh(ifh);
|
---|
1440 | return GBM_ERR_WRITE;
|
---|
1441 | }
|
---|
1442 |
|
---|
1443 | stripoffset = gbm_file_lseek(fd, 0L, SEEK_CUR);
|
---|
1444 |
|
---|
1445 | if ( lzw )
|
---|
1446 | rc = write_strip_lzw(fd, gbm->w, gbm->h, gbm->bpp, data);
|
---|
1447 | else
|
---|
1448 | rc = write_strip(fd, gbm->w, gbm->h, gbm->bpp, data);
|
---|
1449 |
|
---|
1450 | if ( rc != GBM_ERR_OK )
|
---|
1451 | {
|
---|
1452 | free_ifh(ifh);
|
---|
1453 | return rc;
|
---|
1454 | }
|
---|
1455 |
|
---|
1456 | stripbytecount = gbm_file_lseek(fd, 0L, SEEK_CUR) - stripoffset;
|
---|
1457 |
|
---|
1458 | update_long_tag(ifd, T_STRIPOFFSETS, &stripoffset);
|
---|
1459 | update_long_tag(ifd, T_STRIPBYTECOUNTS, &stripbytecount);
|
---|
1460 |
|
---|
1461 | if ( !update_ifd(ifd, fd) )
|
---|
1462 | {
|
---|
1463 | free_ifh(ifh);
|
---|
1464 | return GBM_ERR_WRITE;
|
---|
1465 | }
|
---|
1466 |
|
---|
1467 | free_ifh(ifh);
|
---|
1468 |
|
---|
1469 | return GBM_ERR_OK;
|
---|
1470 | }
|
---|
1471 | /*...e*/
|
---|
1472 | /*...stif_err:0:*/
|
---|
1473 | const char *tif_err(GBM_ERR rc)
|
---|
1474 | {
|
---|
1475 | switch ( (int) rc )
|
---|
1476 | {
|
---|
1477 | case GBM_ERR_TIF_VERSION:
|
---|
1478 | return "version number not 42";
|
---|
1479 | case GBM_ERR_TIF_N_TAGS:
|
---|
1480 | return "too many tags in file";
|
---|
1481 | case GBM_ERR_TIF_TAG_TYPE:
|
---|
1482 | return "bad tag type";
|
---|
1483 | case GBM_ERR_TIF_HEADER:
|
---|
1484 | return "corrupt header";
|
---|
1485 | case GBM_ERR_TIF_MISSING_TAG:
|
---|
1486 | return "ImageWidth, ImageLength or StripOffsets tag missing";
|
---|
1487 | case GBM_ERR_TIF_SPP_BIT:
|
---|
1488 | return "SamplesPerPixel tag must be 1 for bitmap or greyscale file";
|
---|
1489 | case GBM_ERR_TIF_BPS_BIT:
|
---|
1490 | return "BitsPerSample tag must be 1,4 or 8 for bitmap or greyscale file";
|
---|
1491 | case GBM_ERR_TIF_SPP_RGB:
|
---|
1492 | return "SamplesPerPixel tag must be 3 or more for RGB file";
|
---|
1493 | case GBM_ERR_TIF_BPS_RGB:
|
---|
1494 | return "BitsPerSample tag must be 8 for RGB file";
|
---|
1495 | case GBM_ERR_TIF_SPP_PAL:
|
---|
1496 | return "SamplesPerPixel tag must be 1 for palettised file";
|
---|
1497 | case GBM_ERR_TIF_BPS_PAL:
|
---|
1498 | return "BitsPerSample tag must be 1,4 or 8 for palettised file";
|
---|
1499 | case GBM_ERR_TIF_SPP_CMYK:
|
---|
1500 | return "SamplesPerPixel tag must be 4 for CMYK file";
|
---|
1501 | case GBM_ERR_TIF_BPS_CMYK:
|
---|
1502 | return "BitsPerSample tag must be 8 for CMYK file";
|
---|
1503 | case GBM_ERR_TIF_COMP_1D_MH:
|
---|
1504 | return "Compression tag is CCITT 1D Modified Huffman, not supported";
|
---|
1505 | case GBM_ERR_TIF_COMP_T4:
|
---|
1506 | return "Compression tag is CCITT T.4 G3 Facsimile, not supported";
|
---|
1507 | case GBM_ERR_TIF_COMP_T6:
|
---|
1508 | return "Compression tag is CCITT T.6 G4 Facsimile, not supported";
|
---|
1509 | case GBM_ERR_TIF_COMP:
|
---|
1510 | return "Compression tag not uncompressed, PackBits or LZW, not supported";
|
---|
1511 | case GBM_ERR_TIF_COLORMAP:
|
---|
1512 | return "ColorMap tag missing";
|
---|
1513 | case GBM_ERR_TIF_CORRUPT:
|
---|
1514 | return "encoded data is corrupt";
|
---|
1515 | case GBM_ERR_TIF_PREDICTOR:
|
---|
1516 | return "Predictor tag bad";
|
---|
1517 | case GBM_ERR_TIF_PHOTO_TRANS:
|
---|
1518 | return "PhotometricInterpretation tag is transparency mask, not supported";
|
---|
1519 | case GBM_ERR_TIF_PHOTO_Y_Cb_Cr:
|
---|
1520 | return "PhotometricInterpreation tag is Y-Cb-Cr colour space, not supported";
|
---|
1521 | case GBM_ERR_TIF_PHOTO:
|
---|
1522 | return "PhotometricInterpretation tag unsupported/bad";
|
---|
1523 | case GBM_ERR_TIF_FILLORDER:
|
---|
1524 | return "FillOrder tag must be 1";
|
---|
1525 | case GBM_ERR_TIF_PLANARCONFIG_1:
|
---|
1526 | return "PlanarConfiguration tag must be 1 for non RGB files";
|
---|
1527 | case GBM_ERR_TIF_PLANARCONFIG_12:
|
---|
1528 | return "PlanarConfiguration tag must be 1 or 2 for RGB files";
|
---|
1529 | case GBM_ERR_TIF_INKSET:
|
---|
1530 | return "InkSet tag indicates non-CMYK colour seperations";
|
---|
1531 | case GBM_ERR_TIF_ORIENT:
|
---|
1532 | return "Orientation tag must be 1 or 4";
|
---|
1533 | case GBM_ERR_TIF_INDEX:
|
---|
1534 | return "less bitmaps in file than index requested";
|
---|
1535 | }
|
---|
1536 | return NULL;
|
---|
1537 | }
|
---|
1538 | /*...e*/
|
---|