1 #   include	"bitmapConfig.h"
2 
3 #   include	<stdlib.h>
4 #   include	"bmintern.h"
5 #   include	<appDebugon.h>
6 
7 #   if USE_LIBTIFF
8 
9 #   include	<tiffio.h>
10 
11 /************************************************************************/
12 /*									*/
13 /*  Read a tiff file.							*/
14 /*									*/
15 /*  9)  Allocate an extra byte as the libtiff fax 3 code scribbles	*/
16 /*	beyond the end of the buffer.					*/
17 /*									*/
18 /************************************************************************/
19 
bmReadTiffFile(const MemoryBuffer * filename,unsigned char ** pBuffer,BitmapDescription * bd,int * pPrivateFormat)20 int bmReadTiffFile(	const MemoryBuffer *		filename,
21 			unsigned char **	pBuffer,
22 			BitmapDescription *	bd,
23 			int *			pPrivateFormat )
24     {
25     int				rval= 0;
26 
27     TIFF *			t= (TIFF *)0;
28     unsigned int		col;
29 
30     unsigned char *		buffer= (unsigned char *)0;
31     int				fileFormat;
32 
33     unsigned short		photometric;
34     unsigned short		bitsPerSample;
35     float			resolution;
36 
37     unsigned short		unsignedShort;
38     unsigned short *		whatKind;
39     unsigned long		unsignedLong;
40 
41     unsigned short *		redMap= (unsigned short *)0;
42     unsigned short *		greenMap= (unsigned short *)0;
43     unsigned short *		blueMap= (unsigned short *)0;
44 
45     unsigned short		planarConfig= 1;
46 
47     t= TIFFOpen( utilMemoryBufferGetString( filename ), "r" );
48     if  ( ! t )
49 	{ XDEB(t); rval= -1; goto ready;	}
50 
51     if  ( TIFFGetField( t, TIFFTAG_COMPRESSION, &unsignedShort ) != 1 )
52 	{ LDEB(TIFFTAG_COMPRESSION); rval= -1; goto ready;	}
53     fileFormat= unsignedShort;
54 
55     if  ( TIFFGetField( t, TIFFTAG_IMAGEWIDTH, &unsignedLong ) != 1 )
56 	{ LDEB(TIFFTAG_IMAGEWIDTH); rval= -1; goto ready;	}
57     bd->bdPixelsWide= unsignedLong;
58 
59     if  ( TIFFGetField( t, TIFFTAG_IMAGELENGTH, &unsignedLong ) != 1 )
60 	{ LDEB(TIFFTAG_IMAGELENGTH); rval= -1; goto ready;	}
61     bd->bdPixelsHigh= unsignedLong;
62 
63     if  ( TIFFGetField( t, TIFFTAG_BITSPERSAMPLE, &bitsPerSample ) != 1 )
64 	{ LDEB(TIFFTAG_BITSPERSAMPLE); rval= -1; goto ready; }
65     if  ( bitsPerSample > 8 )
66 	{ LDEB(bitsPerSample); return -1;	}
67     bd->bdBitsPerSample= bitsPerSample;
68 
69     if  ( TIFFGetField( t, TIFFTAG_SAMPLESPERPIXEL, &unsignedShort ) != 1 )
70 	{ LDEB(TIFFTAG_SAMPLESPERPIXEL); rval= -1; goto ready; }
71     bd->bdSamplesPerPixel= unsignedShort;
72 
73     if  ( TIFFGetField( t, TIFFTAG_EXTRASAMPLES, &unsignedShort,
74 							 &whatKind ) != 1 )
75 	{ bd->bdHasAlpha= 0; }
76     else{
77 	switch( unsignedShort )
78 	    {
79 	    case 0:
80 		bd->bdHasAlpha= 0;
81 		break;
82 
83 	    case 1:
84 		if  ( whatKind[0] != EXTRASAMPLE_ASSOCALPHA	&&
85 		      whatKind[0] != EXTRASAMPLE_UNASSALPHA	)
86 		    { LLDEB(TIFFTAG_EXTRASAMPLES,whatKind[0]); return -1;}
87 		bd->bdHasAlpha= 1;
88 		break;
89 
90 	    default:
91 		LLDEB(TIFFTAG_EXTRASAMPLES,unsignedShort);
92 		return -1;
93 	    }
94 	}
95 
96     if  ( TIFFGetField( t, TIFFTAG_PHOTOMETRIC, &photometric ) != 1 )
97 	{ LDEB(TIFFTAG_PHOTOMETRIC); rval= -1; goto ready;	}
98 
99     switch( photometric )
100 	{
101 	case PHOTOMETRIC_MINISWHITE:
102 	    bd->bdColorEncoding= BMcoBLACKWHITE;
103 	    bd->bdBitsPerPixel= bd->bdBitsPerSample* bd->bdSamplesPerPixel;
104 	    break;
105 
106 	case PHOTOMETRIC_MINISBLACK:
107 	    bd->bdColorEncoding= BMcoWHITEBLACK;
108 	    bd->bdBitsPerPixel= bd->bdBitsPerSample* bd->bdSamplesPerPixel;
109 	    break;
110 
111 	case PHOTOMETRIC_RGB:
112 	    bd->bdColorEncoding= BMcoRGB;
113 	    bd->bdBitsPerPixel= bd->bdBitsPerSample* bd->bdSamplesPerPixel;
114 	    break;
115 
116 	case PHOTOMETRIC_PALETTE:
117 	    if  ( TIFFGetField( t, TIFFTAG_COLORMAP,
118 					&redMap, &greenMap, &blueMap ) != 1 )
119 		{ LDEB(TIFFTAG_COLORMAP); rval= -1; goto ready; }
120 
121 	    if  ( bd->bdHasAlpha )
122 		{
123 		if  ( bd->bdSamplesPerPixel != 2 )
124 		    { LDEB(bd->bdSamplesPerPixel); rval= -1; goto ready; }
125 		}
126 	    else{
127 		if  ( bd->bdSamplesPerPixel != 1 )
128 		    { LDEB(bd->bdSamplesPerPixel); rval= -1; goto ready; }
129 		}
130 
131 	    if  ( utilPaletteSetCount( &(bd->bdPalette), 1 << bitsPerSample ) )
132 		{ LDEB(1 << bitsPerSample); rval= -1; goto ready;	}
133 
134 	    for ( col= 0; col < bd->bdPalette.cpColorCount; col++ )
135 		{
136 		bd->bdPalette.cpColors[col].rgb8Red= redMap[col]/256;
137 		bd->bdPalette.cpColors[col].rgb8Green= greenMap[col]/256;
138 		bd->bdPalette.cpColors[col].rgb8Blue= blueMap[col]/256;
139 		}
140 
141 	    bd->bdBitsPerSample= 8;
142 	    bd->bdColorEncoding= BMcoRGB8PALETTE;
143 
144 	    if  ( bd->bdHasAlpha )
145 		{
146 		bd->bdSamplesPerPixel= 4;
147 		bd->bdBitsPerPixel= 2* bitsPerSample;
148 		}
149 	    else{
150 		bd->bdSamplesPerPixel= 3;
151 		bd->bdBitsPerPixel=    bitsPerSample;
152 		}
153 
154 	    break;
155 	default:
156 	    LDEB(photometric); rval= -1; goto ready;
157 	}
158 
159     bd->bdBytesPerRow= ( bd->bdBitsPerPixel* bd->bdPixelsWide + 7 )/ 8;
160     bd->bdBufferLength= bd->bdBytesPerRow* bd->bdPixelsHigh;
161 
162     if  ( bd->bdSamplesPerPixel != 1 )
163 	{
164 	if  ( TIFFGetField( t, TIFFTAG_PLANARCONFIG, &planarConfig ) != 1 )
165 	    { LDEB(TIFFTAG_PLANARCONFIG); rval= -1; goto ready;	}
166 	if  ( planarConfig != 1 )
167 	    {
168 	    LLDEB(bd->bdSamplesPerPixel,planarConfig);
169 	    LLDEB(bd->bdBitsPerSample,bd->bdBitsPerPixel);
170 	    }
171 	}
172 
173     if  ( TIFFGetField( t, TIFFTAG_RESOLUTIONUNIT, &unsignedShort ) != 1 )
174 	{
175 	/* SLDEB(filename,TIFFTAG_RESOLUTIONUNIT); */
176 	bd->bdUnit= BMunPIXEL;
177 	bd->bdXResolution= 1;
178 	bd->bdYResolution= 1;
179 	}
180     else{
181 	switch( unsignedShort )
182 	    {
183 	    case	RESUNIT_INCH:
184 		bd->bdUnit= BMunINCH;
185 		if  ( TIFFGetField( t, TIFFTAG_XRESOLUTION, &resolution ) != 1 )
186 		    { LDEB(TIFFTAG_XRESOLUTION); rval= -1; goto ready; }
187 		bd->bdXResolution= (int)resolution;
188 		if  ( TIFFGetField( t, TIFFTAG_YRESOLUTION, &resolution ) != 1 )
189 		    { LDEB(TIFFTAG_YRESOLUTION); rval= -1; goto ready; }
190 		bd->bdYResolution= (int)resolution;
191 		break;
192 	    case	RESUNIT_CENTIMETER:
193 		bd->bdUnit= BMunM;
194 		if  ( TIFFGetField( t, TIFFTAG_XRESOLUTION, &resolution ) != 1 )
195 		    { LDEB(TIFFTAG_XRESOLUTION); rval= -1; goto ready; }
196 		bd->bdXResolution= (int)100* resolution;
197 		if  ( TIFFGetField( t, TIFFTAG_YRESOLUTION, &resolution ) != 1 )
198 		    { LDEB(TIFFTAG_YRESOLUTION); rval= -1; goto ready; }
199 		bd->bdYResolution= 100* (int)resolution;
200 		break;
201 	    case	RESUNIT_NONE:
202 		bd->bdUnit= BMunPIXEL;
203 		if  ( TIFFGetField( t, TIFFTAG_XRESOLUTION, &resolution ) != 1 )
204 		    { LDEB(TIFFTAG_XRESOLUTION); resolution= 1;	}
205 		bd->bdXResolution= (int)resolution;
206 		if  ( TIFFGetField( t, TIFFTAG_YRESOLUTION, &resolution ) != 1 )
207 		    { LDEB(TIFFTAG_YRESOLUTION); resolution= 1;	}
208 		bd->bdYResolution= (int)resolution;
209 		break;
210 	    default:
211 		LDEB(unsignedShort); rval= -1; goto ready;
212 	    }
213 
214 	if  ( bd->bdXResolution == 0	||
215 	      bd->bdYResolution == 0	)
216 	    {
217 	    LLDEB(bd->bdXResolution,bd->bdYResolution);
218 	    bd->bdUnit= BMunPIXEL;
219 	    bd->bdXResolution= 1;
220 	    bd->bdYResolution= 1;
221 	    }
222 	}
223 
224     /*  9  */
225     buffer= (unsigned char *)malloc( bd->bdBufferLength+ 1 );
226     if  ( ! buffer )
227 	{ XDEB(buffer); rval= -1; goto ready;	}
228 
229     if  ( bd->bdBitsPerPixel % 8 == 0 )
230 	{
231 	int		offset= 0;
232 	int		strip= 0;
233 
234 	while( offset < bd->bdBufferLength )
235 	    {
236 	    int		done;
237 
238 	    done= TIFFReadEncodedStrip( t, strip, buffer+ offset,
239 						bd->bdBufferLength- offset );
240 	    if  ( done < 1 )
241 		{ LDEB(done); free( buffer ); TIFFClose( t ); return -1; }
242 
243 	    offset += done; strip++;
244 	    }
245 	}
246     else{
247 	int	row;
248 
249 	for ( row= 0; row < bd->bdPixelsHigh; row++ )
250 	    {
251 	    if  ( TIFFReadScanline( t, buffer+ row* bd->bdBytesPerRow,
252 								row, 0 ) < 0 )
253 		{ LDEB(row); free( buffer ); TIFFClose( t ); return -1; }
254 	    }
255 	}
256 
257     if  ( planarConfig != 1 )
258 	{
259 	unsigned char *		scratch;
260 
261 	scratch= (unsigned char *)malloc( bd->bdBufferLength+ 1 );
262 	if  ( ! scratch )
263 	    { XDEB(scratch); rval= -1; goto ready;	}
264 
265 	if  ( bmPlanarToChunky( scratch, buffer, bd ) )
266 	    { LDEB(1); free( scratch ); rval= -1; goto ready;	}
267 
268 	free( buffer ); buffer= scratch;
269 	}
270 
271     *pBuffer= buffer; buffer= (unsigned char *)0; /* steal */
272     *pPrivateFormat= fileFormat;
273 
274   ready:
275     if  ( t )
276 	{ TIFFClose( t );	}
277     if  ( buffer )
278 	{ free( buffer );	}
279 
280     return rval;
281     }
282 
283 
bmCanWriteTiffFile(const BitmapDescription * bd,int privateFormat)284 int bmCanWriteTiffFile( const BitmapDescription *	bd,
285 			int				privateFormat )
286     {
287     switch( privateFormat )
288 	{
289 	case COMPRESSION_NONE:
290 	    break;
291 	case COMPRESSION_CCITTRLE:
292 	case COMPRESSION_CCITTFAX3:
293 	case COMPRESSION_CCITTFAX4:
294 	    if  ( bd->bdBitsPerPixel == 1 )
295 		{ break;	}
296 	    else{ return -1;	}
297 	case COMPRESSION_LZW:
298 	    return 0;
299 	case COMPRESSION_JPEG:
300 	    if  ( bd->bdBitsPerSample == 8 )
301 		{ break;	}
302 	    else{ return -1;	}
303 	case COMPRESSION_NEXT:
304 	    return -1;
305 	case COMPRESSION_CCITTRLEW:
306 	case COMPRESSION_PACKBITS:
307 	case COMPRESSION_THUNDERSCAN:
308 	    if  ( bd->bdBitsPerPixel == 1 )
309 		{ break;	}
310 	    else{ return -1;	}
311 	default:
312 	    LDEB(privateFormat); return -1;
313 	}
314 
315     switch( bd->bdColorEncoding )
316 	{
317 	case BMcoRGB8PALETTE:
318 	    switch( bd->bdBitsPerSample )
319 		{
320 		case 4:
321 		case 8:
322 		    break;
323 		default:
324 		    /* LDEB(bd->bdBitsPerSample); */ return -1;
325 		}
326 	    break;
327 	default:
328 	    break;
329 	}
330 
331     return 0;
332     }
333 
334 /************************************************************************/
335 /*									*/
336 /*  Write a bitmap to a TIFF file.					*/
337 /*									*/
338 /************************************************************************/
339 
bmWriteTiffFile(const MemoryBuffer * filename,const unsigned char * buffer,const BitmapDescription * bd,int privateFormat)340 int bmWriteTiffFile(	const MemoryBuffer *		filename,
341 			const unsigned char *		buffer,
342 			const BitmapDescription *	bd,
343 			int				privateFormat )
344     {
345     TIFF *			t;
346     int				colorSpace= PHOTOMETRIC_MINISWHITE; /*bah*/
347     unsigned long		rowsPerStrip;
348     int				unit, xResolution, yResolution;
349     int				row;
350     int				i;
351 
352     t= TIFFOpen( utilMemoryBufferGetString( filename ), "w" );
353     if  ( ! t )
354 	{ XDEB(t); return -1;	}
355 
356     if  ( ! TIFFSetField( t, TIFFTAG_COMPRESSION, privateFormat ) )
357 	{ LLDEB(TIFFTAG_COMPRESSION,privateFormat); return -1; }
358 
359     if  ( ! TIFFSetField( t, TIFFTAG_IMAGELENGTH, (long)bd->bdPixelsHigh ) )
360 	{ LLDEB(TIFFTAG_IMAGELENGTH,(long)bd->bdPixelsHigh); return -1; }
361 
362     if  ( ! TIFFSetField( t, TIFFTAG_IMAGEWIDTH, (long)bd->bdPixelsWide ) )
363 	{ LLDEB(TIFFTAG_IMAGEWIDTH,(long)bd->bdPixelsWide); return -1; }
364 
365     switch( bd->bdColorEncoding )
366 	{
367 	case BMcoBLACKWHITE:	colorSpace= PHOTOMETRIC_MINISWHITE;
368 				break;
369 	case BMcoWHITEBLACK:	colorSpace= PHOTOMETRIC_MINISBLACK;
370 				break;
371 	case BMcoRGB:	colorSpace= PHOTOMETRIC_RGB;
372 				break;
373 	case BMcoRGB8PALETTE: colorSpace= PHOTOMETRIC_PALETTE;
374 				break;
375 	default:
376 		LDEB(bd->bdColorEncoding); return -1;
377 	}
378 
379     if  ( ! TIFFSetField( t, TIFFTAG_PHOTOMETRIC, colorSpace ) )
380 	{ LLDEB(TIFFTAG_PHOTOMETRIC,colorSpace); return -1; }
381 
382     if  ( colorSpace == PHOTOMETRIC_PALETTE )
383 	{
384 	int			colorCountOut;
385 	int			colorCountIn;
386 	unsigned short *	redMap;
387 	unsigned short *	greenMap;
388 	unsigned short *	blueMap;
389 
390 	switch( bd->bdBitsPerPixel )
391 	    {
392 	    case 1:
393 		colorCountIn= 2;
394 		colorCountOut= 16;
395 		break;
396 
397 	    case 2:
398 		colorCountIn= 4;
399 		colorCountOut= 16;
400 		break;
401 
402 	    case 4:
403 		colorCountIn= 16;
404 		colorCountOut= 16;
405 		break;
406 
407 	    case 8:
408 		colorCountIn= 256;
409 		colorCountOut= 256;
410 		break;
411 
412 	    case 16:
413 		if  ( bd->bdHasAlpha )
414 		    {
415 		    colorCountIn= 256;
416 		    colorCountOut= 256;
417 		    }
418 		else{
419 		    LDEB(bd->bdHasAlpha);
420 		    LLDEB(bd->bdBitsPerPixel,bd->bdBitsPerSample); return -1;
421 		    }
422 		break;
423 
424 	    default:
425 		LLDEB(bd->bdBitsPerPixel,bd->bdBitsPerSample); return -1;
426 	    }
427 
428 	if  ( bd->bdPalette.cpColorCount > colorCountIn )
429 	    { LLDEB(bd->bdPalette.cpColorCount,colorCountIn); return -1; }
430 
431 	/*
432 	if  ( colorCountIn != colorCountOut )
433 	    { LLDEB(colorCountIn,colorCountOut); LDEB(bd->bdBitsPerPixel); }
434 	*/
435 
436 	redMap=
437 	    (unsigned short *)malloc( colorCountOut * sizeof(unsigned short) );
438 	greenMap=
439 	    (unsigned short *)malloc( colorCountOut * sizeof(unsigned short) );
440 	blueMap=
441 	    (unsigned short *)malloc( colorCountOut * sizeof(unsigned short) );
442 
443 	if  ( ! redMap || ! greenMap || ! blueMap )
444 	    { LDEB(colorCountOut); return -1; }
445 
446 	for ( i= 0; i < bd->bdPalette.cpColorCount; i++ )
447 	    {
448 	    redMap[i]=	 257* bd->bdPalette.cpColors[i].rgb8Red;
449 	    greenMap[i]= 257* bd->bdPalette.cpColors[i].rgb8Green;
450 	    blueMap[i]=	 257* bd->bdPalette.cpColors[i].rgb8Blue;
451 	    }
452 	for ( ; i < colorCountOut; i++ )
453 	    {
454 	    redMap[i]=	 redMap[i-1];
455 	    greenMap[i]= greenMap[i-1];
456 	    blueMap[i]=	 blueMap[i-1];
457 	    }
458 
459 	if  ( bd->bdHasAlpha )
460 	    {
461 	    if  ( ! TIFFSetField( t, TIFFTAG_BITSPERSAMPLE,
462 						    bd->bdBitsPerPixel/ 2 ) )
463 		{ LLDEB(TIFFTAG_BITSPERSAMPLE,bd->bdBitsPerSample); return -1; }
464 	    if  ( ! TIFFSetField( t, TIFFTAG_SAMPLESPERPIXEL, 2 ) )
465 		{ LLDEB(TIFFTAG_SAMPLESPERPIXEL,1); TIFFClose(t); return -1; }
466 	    }
467 	else{
468 	    if  ( ! TIFFSetField( t, TIFFTAG_BITSPERSAMPLE,
469 						    bd->bdBitsPerPixel ) )
470 		{ LLDEB(TIFFTAG_BITSPERSAMPLE,bd->bdBitsPerSample); return -1; }
471 	    if  ( ! TIFFSetField( t, TIFFTAG_SAMPLESPERPIXEL, 1 ) )
472 		{ LLDEB(TIFFTAG_SAMPLESPERPIXEL,1); TIFFClose(t); return -1; }
473 	    }
474 
475 	if  ( TIFFSetField( t, TIFFTAG_COLORMAP,
476 				    redMap, greenMap, blueMap ) != 1 )
477 	    { LDEB(TIFFTAG_COLORMAP); TIFFClose(t); return -1;	}
478 
479 	free( redMap ); free( greenMap ); free( blueMap );
480 	}
481     else{
482 	if  ( ! TIFFSetField( t, TIFFTAG_BITSPERSAMPLE, bd->bdBitsPerSample ) )
483 	    { LLDEB(TIFFTAG_BITSPERSAMPLE,bd->bdBitsPerSample); return -1; }
484 
485 	if  ( ! TIFFSetField( t, TIFFTAG_SAMPLESPERPIXEL,
486 						bd->bdSamplesPerPixel ) )
487 	    { LLDEB(TIFFTAG_SAMPLESPERPIXEL,bd->bdSamplesPerPixel); return -1; }
488 	}
489 
490     if  ( ! TIFFSetField( t, TIFFTAG_PLANARCONFIG, 1 ) )
491 	{ LLDEB(TIFFTAG_PLANARCONFIG,1); TIFFClose(t); return -1; }
492 
493 					/********************************/
494 					/*  To make PC's happy, make	*/
495 					/*  strips that are a little	*/
496 					/*  smaller than 64K.		*/
497 					/*  JPEG compression works per	*/
498 					/*  strip. It requires that the	*/
499 					/*  height of a strip be a	*/
500 					/*  multiple of 8. An attempt	*/
501 					/*  is made to combine these	*/
502 					/*  restrictions.		*/
503 					/********************************/
504 
505     rowsPerStrip= 65000/ bd->bdBytesPerRow;
506     if  ( rowsPerStrip % 8 )
507 	{ rowsPerStrip= 8* ( rowsPerStrip/ 8 );	}
508     if  ( rowsPerStrip < 1 )
509 	{ rowsPerStrip= 1;	}
510 
511     if  ( ! TIFFSetField( t, TIFFTAG_ROWSPERSTRIP, rowsPerStrip ) )
512 	{ LLDEB(TIFFTAG_ROWSPERSTRIP,rowsPerStrip); TIFFClose(t); return -1; }
513 
514     if  ( bd->bdHasAlpha )
515 	{
516 	unsigned short	value= EXTRASAMPLE_ASSOCALPHA;
517 
518 	if  ( ! TIFFSetField( t, TIFFTAG_EXTRASAMPLES, 1, &value ) )
519 	    {
520 	    LLDEB(colorSpace,bd->bdSamplesPerPixel);
521 	    LLDEB(TIFFTAG_EXTRASAMPLES,bd->bdHasAlpha);
522 	    TIFFClose(t); return -1;
523 	    }
524 	}
525 
526     switch( bd->bdUnit )
527 	{
528 	case	BMunM:
529 	    unit= RESUNIT_CENTIMETER;
530 	    xResolution= ( bd->bdXResolution+ 50 )/ 100;
531 	    yResolution= ( bd->bdYResolution+ 50 )/ 100;
532 	    break;
533 
534 	case	BMunINCH:
535 	    unit= RESUNIT_INCH;
536 	    xResolution= bd->bdXResolution;
537 	    yResolution= bd->bdYResolution;
538 	    break;
539 
540 	case	BMunPOINT:
541 	    unit= RESUNIT_INCH;
542 	    xResolution= bd->bdXResolution* 72;
543 	    yResolution= bd->bdYResolution* 72;
544 	    break;
545 
546 	case BMunPIXEL:
547 	    unit= RESUNIT_NONE;
548 	    xResolution= bd->bdXResolution;
549 	    yResolution= bd->bdYResolution;
550 	    break;
551 
552 	default:
553 	    LDEB(bd->bdUnit);
554 	    unit= RESUNIT_NONE;
555 	    xResolution= bd->bdXResolution;
556 	    yResolution= bd->bdYResolution;
557 	    break;
558 	}
559 
560     if  ( ! TIFFSetField( t, TIFFTAG_RESOLUTIONUNIT, unit ) )
561 	{ LLDEB(TIFFTAG_RESOLUTIONUNIT, unit); return -1; }
562 
563     if  ( ! TIFFSetField( t, TIFFTAG_XRESOLUTION, (float)xResolution ) )
564 	{ LLDEB(TIFFTAG_XRESOLUTION, xResolution); return -1; }
565 
566     if  ( ! TIFFSetField( t, TIFFTAG_YRESOLUTION, (float)yResolution ) )
567 	{ LLDEB(TIFFTAG_YRESOLUTION, yResolution); return -1; }
568 
569     if  ( ! TIFFSetField( t, TIFFTAG_SOFTWARE, "appFrame:"
570 		    " Mark de Does,"
571 		    " mark@mdedoes.com" ) )
572 	{ LDEB(TIFFTAG_SOFTWARE); return -1; }
573 
574     for ( row= 0; row < bd->bdPixelsHigh; row++ )
575 	{
576 	if  ( TIFFWriteScanline( t, (char *) buffer+ row* bd->bdBytesPerRow,
577 								row, 0 ) < 0 )
578 	    { LDEB(row); return -1; }
579 	}
580 
581     TIFFClose( t );
582 
583     return 0;
584     }
585 
586 #   endif /* TIFF_FOUND */
587