1 /*
2 * This software is copyrighted as noted below. It may be freely copied,
3 * modified, and redistributed, provided that the copyright notice is
4 * preserved on all copies.
5 *
6 * There is no warranty or other guarantee of fitness for this software,
7 * it is provided solely "as is". Bug reports or fixes may be sent
8 * to the author, who may or may not act on them as he desires.
9 *
10 * You may not include this software in a program or other software product
11 * without supplying the source, or without informing the end-user that the
12 * source is available for no extra charge.
13 *
14 * If you modify this software, you should include a notice giving the
15 * name of the person performing the modification, the date of modification,
16 * and the reason for such modification.
17 */
18 /*
19 * tiff.c - interface with Aldus-Microsoft TIFF format.
20 *
21 * Author: Raul Rivero
22 * Mathematics Dept.
23 * University of Oviedo
24 * Date: Sat Jan 18 1992
25 * Copyright (c) 1992, Raul Rivero
26 *
27 */
28 /*
29 * Raul Rivero - 04/14/94
30 * Added support for images with any # of colors.
31 *
32 */
33
34 #include <lug.h>
35 #include <lugfnts.h>
36
37
38 /*
39 * Look here !!!
40 * =============
41 *
42 * This code is valid only if we have defined the iTIFF
43 * macro ( read the root Makefile for more information ).
44 *
45 */
46
47 #ifdef iTIFF
48
49 #include <tiffio.h>
50
51 #define GetField(a,b,c) if ( TIFFGetField(a,b,c) == 0 ) error( 21 );
52
53 extern int LUGverbose;
54
read_tiff_file(name,image)55 read_tiff_file( name, image )
56 char *name;
57 bitmap_hdr *image;
58 {
59 register int i, j;
60 TIFF *handle;
61 long xsize, ysize;
62 ushort samplesperpixel;
63 ushort bitspersample;
64 ushort photometric;
65 ushort planarconfig;
66 ushort iscmyk = 0;
67 ushort c, m, y, k;
68 ushort *rTIFFcmap, *gTIFFcmap, *bTIFFcmap;
69 byte *r, *g, *b;
70 int totalsize;
71 byte *ptr;
72 byte *TIFFline;
73 double val, inc;
74
75 /*
76 * Open the file.
77 */
78 if ( name )
79 handle = TIFFOpen( name, "rb" );
80 else handle = TIFFFdOpen( 0, "stdin", "rb" );
81 if ( handle == NULL )
82 error( 1 );
83
84 /*
85 * Get TIFF configuration.
86 */
87 GetField( handle, TIFFTAG_IMAGEWIDTH, &xsize );
88 GetField( handle, TIFFTAG_IMAGELENGTH, &ysize );
89 GetField( handle, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel );
90 GetField( handle, TIFFTAG_BITSPERSAMPLE, &bitspersample );
91 GetField( handle, TIFFTAG_PHOTOMETRIC, &photometric );
92 GetField( handle, TIFFTAG_PLANARCONFIG, &planarconfig );
93
94 /*
95 * ... ok. Fill our header.
96 */
97 image->magic = LUGUSED;
98 image->xsize = (int) xsize;
99 image->ysize = (int) ysize;
100 image->depth = ( samplesperpixel < 4 ? samplesperpixel : 3 ) * bitspersample;
101 image->colors = 1 << image->depth;
102
103 /*
104 * New LIBTIFF library has changed the calling parameters
105 * of the TIFFPrintDirectory functions, so ... what version
106 * are you using ?.
107 */
108 if ( LUGverbose )
109 #if TIFF_VERSION >= 42
110 TIFFPrintDirectory( handle, stderr, 0L );
111 #else
112 TIFFPrintDirectory( handle, stderr, 1, 0, 0 );
113 #endif
114
115 switch ( photometric ) {
116 case PHOTOMETRIC_MINISBLACK :
117 /* Get the increments while building the cmap table */
118 inc = 255. / (((double)image->colors)-1.);
119 /* Allocate memory for our cmap and build it */
120 ptr = image->cmap = (byte *) Malloc( 3 * image->colors );
121 for ( i = 0, val = 0.; i < image->colors; i++, val += inc ) {
122 *ptr++ = (byte) val;
123 *ptr++ = *(ptr-1);
124 *ptr++ = *(ptr-1);
125 }
126 break;
127 case PHOTOMETRIC_MINISWHITE :
128 /* Get the increments while building the cmap table */
129 inc = 255. / (((double)image->colors)-1.);
130 /* Allocate memory for our cmap and build it */
131 ptr = image->cmap = (byte *) Malloc( 3 * image->colors );
132 for ( i = 0, val = 255.; i < image->colors; i++, val -=inc ) {
133 *ptr++ = (byte) val;
134 *ptr++ = *(ptr-1);
135 *ptr++ = *(ptr-1);
136 }
137 break;
138 case PHOTOMETRIC_PALETTE :
139 /* Read the TIFF cmap */
140 if ( !TIFFGetField( handle, TIFFTAG_COLORMAP,
141 &rTIFFcmap, &gTIFFcmap, &bTIFFcmap ) )
142 error( 9 );
143 /* Allocate memory for our cmap and get it */
144 ptr = image->cmap = (byte *) Malloc( 3 * image->colors );
145 for ( i = 0; i < image->colors; i++ ) {
146 *ptr++ = ( rTIFFcmap[i] >> 8 );
147 *ptr++ = ( gTIFFcmap[i] >> 8 );
148 *ptr++ = ( bTIFFcmap[i] >> 8 );
149 }
150 break;
151 case PHOTOMETRIC_RGB :
152 break;
153 case PHOTOMETRIC_SEPARATED:
154 if ( TIFFGetField( handle, TIFFTAG_INKSET, &iscmyk ) == 0 ) {
155 if ( samplesperpixel == 4 ) {
156 /*
157 * Photoshop doesn't save the INKSET tag. So ... we hope
158 * in a good CMYK's file if we have 4 samples per pixel.
159 */
160 VPRINTF( stderr, "Warning, cannot get the INKSET tag (possible further errors)\n" );
161 iscmyk = 4;
162 }else {
163 VPRINTF( stderr, "A possible CMYK image without INKSET tag neither 4 samples per pixel\n" );
164 error( 99 );
165 }
166 }else {
167 if ( iscmyk != INKSET_CMYK ) {
168 fprintf( stderr, "Separated Photometric image but not CMYK\n" );
169 error( 99 );
170 }
171 }
172 break;
173 default:
174 fprintf( stderr, "Not supported photometric configuration\n");
175 error( 99 );
176 }
177 if ( image->depth > 8 ) {
178 switch ( planarconfig ) {
179 case PLANARCONFIG_CONTIG :
180 break;
181 case PLANARCONFIG_SEPARATE :
182 fprintf( stderr, "Separate planar configuration is not supported, yet.\n");
183 error( 99 );
184 break;
185 default:
186 fprintf( stderr, "Unknown planar configuration\n");
187 error( 99 );
188 }
189 }
190
191
192 /*
193 * Allocate memory for bitmap.
194 */
195 totalsize = (int) (xsize * ysize);
196 r = image->r = (byte *) Malloc( totalsize );
197 if ( image->depth > 8 ) {
198 /* A real RGB image */
199 g = image->g = (byte *) Malloc( totalsize );
200 b = image->b = (byte *) Malloc( totalsize );
201 }
202
203 /*
204 * Get TIFF raster lines.
205 */
206 TIFFline = (byte *) Malloc( TIFFScanlineSize(handle) );
207 /*
208 * This ...if... could be done inside the loop but what we
209 * wanna is efficacy :-), so ...
210 */
211 if ( image->depth >= 8 ) {
212 /* We have a 'beatiful' raw image */
213 for ( i = 0; i < ysize; i++ ) {
214 TIFFReadScanline( handle, TIFFline, i, 0 );
215 if ( !iscmyk ) {
216 /* Great!, a RGB image :) */
217 for ( j = 0, ptr = TIFFline; j < xsize; j++ ) {
218 *r++ = *ptr++;
219 if ( image->depth > 8 ) {
220 *g++ = *ptr++;
221 *b++ = *ptr++;
222 if ( samplesperpixel == 4 ) {
223 /* Skip alpha channel */
224 ptr++;
225 }
226 }
227 }
228 }else {
229 /* Oooopss!, a CMYK image */
230 for ( j = 0, ptr = TIFFline; j < xsize; j++ ) {
231 c = 255 - *ptr++;
232 m = 255 - *ptr++;
233 y = 255 - *ptr++;
234 k = 255 - *ptr++;
235 *r++ = ((int)k*c/255);
236 *g++ = ((int)k*m/255);
237 *b++ = ((int)k*y/255);
238 }
239 }
240 }
241 }else {
242 /* Ooopss, we have packed bits */
243 int mask = ( 1 << bitspersample ) - 1;
244 int offset;
245
246 for ( i = 0; i < ysize; i++ ) {
247 TIFFReadScanline( handle, TIFFline, i, 0 );
248 for ( j = 0, ptr = TIFFline, offset = 8 - bitspersample;
249 j < xsize;
250 j++, offset -= bitspersample) {
251 *r++ = (*ptr >> offset ) & mask;
252 if ( !offset ) {
253 offset = 8;
254 ptr++;
255 }
256 }
257 }
258 }
259
260 /*
261 * Free our raster line and close the TIFF file.
262 */
263 free( TIFFline );
264 TIFFClose( handle );
265 }
266
write_tiff_file(name,image)267 write_tiff_file( name, image )
268 char *name;
269 bitmap_hdr *image;
270 {
271 register int i, j;
272 TIFF *handle;
273 byte *r, *g, *b;
274 byte *buffer, *ptr;
275 long rows_per_strip;
276 int banks = (image->depth > 8 ? 3 : 1);
277 long xsize, ysize;
278 ushort *rTIFFcmap, *gTIFFcmap, *bTIFFcmap;
279
280 if ( image->magic != LUGUSED )
281 error( 19 );
282
283 VPRINTF( stderr, "Writting TIFF file\n" );
284 /*
285 * Open the TIFF file.
286 */
287 if ( name )
288 handle = TIFFOpen( name, "wb" );
289 else handle = TIFFFdOpen( 1, "stdout", "wb" );
290 if ( handle == NULL)
291 error( 1 );
292
293 /*
294 * Configure the TIFF image.
295 */
296 xsize = image->xsize;
297 ysize = image->ysize;
298 TIFFSetField( handle,TIFFTAG_IMAGEWIDTH, xsize );
299 TIFFSetField( handle,TIFFTAG_IMAGELENGTH, ysize );
300 TIFFSetField( handle, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
301 TIFFSetField( handle, TIFFTAG_PREDICTOR, 2);
302 rows_per_strip = 16*1024 / (image->xsize);
303 if ( rows_per_strip < 1 )
304 rows_per_strip = 1;
305 TIFFSetField( handle, TIFFTAG_ROWSPERSTRIP, rows_per_strip);
306 TIFFSetField( handle, TIFFTAG_XRESOLUTION, 72.0 );
307 TIFFSetField( handle, TIFFTAG_YRESOLUTION, 72.0 );
308 TIFFSetField( handle, TIFFTAG_RESOLUTIONUNIT, 1 );
309 TIFFSetField( handle, TIFFTAG_BITSPERSAMPLE, 8 );
310 TIFFSetField( handle, TIFFTAG_SAMPLESPERPIXEL, banks );
311 TIFFSetField( handle, TIFFTAG_PLANARCONFIG, 1 );
312 if ( banks > 1 ) {
313 /*
314 * A true color image.
315 */
316 TIFFSetField( handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
317 }else {
318 /*
319 * If a mapped image, the we need build the cmap.
320 */
321 TIFFSetField( handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
322 rTIFFcmap = (ushort *) Malloc( sizeof(short) * 256 );
323 gTIFFcmap = (ushort *) Malloc( sizeof(short) * 256 );
324 bTIFFcmap = (ushort *) Malloc( sizeof(short) * 256 );
325 for ( i = 0, ptr = image->cmap; i < image->colors; i++ ) {
326 rTIFFcmap[i] = ( *ptr++ << 8 );
327 gTIFFcmap[i] = ( *ptr++ << 8 );
328 bTIFFcmap[i] = ( *ptr++ << 8 );
329 }
330 TIFFSetField( handle, TIFFTAG_COLORMAP, rTIFFcmap, gTIFFcmap, bTIFFcmap );
331 }
332
333 /*
334 * Set pointers.
335 */
336 r = image->r;
337 if ( image->depth > 8 ) {
338 g = image->g;
339 b = image->b;
340 }
341 buffer = (byte *) Malloc( banks * image->xsize );
342
343 /*
344 * Dump each line.
345 */
346 for ( i = 0; i < image->ysize; i++ ) {
347 /* TIFF library needs a RGBRGB...RGB raster line so ... */
348 for ( j = 0, ptr = buffer; j < image->xsize; j++ ) {
349 *ptr++ = *r++;
350 if ( banks > 1 ) {
351 *ptr++ = *g++;
352 *ptr++ = *b++;
353 }
354 }
355 TIFFWriteScanline( handle, buffer, i, 1);
356 }
357
358 /*
359 * Close the TIFF file.
360 */
361 TIFFClose( handle );
362
363 /*
364 * Free memory.
365 */
366 free( buffer );
367 if ( banks < 3 ) {
368 free( rTIFFcmap );
369 free( gTIFFcmap );
370 free( bTIFFcmap );
371 }
372 TIFFClose( handle );
373 }
374
375
376 #endif /* iTIFF */
377