1 /* $Id: bmp2tiff.c,v 1.20 2006/03/23 14:54:02 dron Exp $
2  *
3  * Project:  libtiff tools
4  * Purpose:  Convert Windows BMP files in TIFF.
5  * Author:   Andrey Kiselev, dron@ak4719.spb.edu
6  *
7  ******************************************************************************
8  * Copyright (c) 2004, Andrey Kiselev <dron@ak4719.spb.edu>
9  *
10  * Permission to use, copy, modify, distribute, and sell this software and
11  * its documentation for any purpose is hereby granted without fee, provided
12  * that (i) the above copyright notices and this permission notice appear in
13  * all copies of the software and related documentation, and (ii) the names of
14  * Sam Leffler and Silicon Graphics may not be used in any advertising or
15  * publicity relating to the software without the specific, prior written
16  * permission of Sam Leffler and Silicon Graphics.
17  *
18  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
20  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
21  *
22  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
23  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
24  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
25  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
26  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
27  * OF THIS SOFTWARE.
28  */
29 
30 #include "tif_config.h"
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 
39 #ifdef HAVE_UNISTD_H
40 # include <unistd.h>
41 #endif
42 
43 #if HAVE_FCNTL_H
44 # include <fcntl.h>
45 #endif
46 
47 #if HAVE_SYS_TYPES_H
48 # include <sys/types.h>
49 #endif
50 
51 #if HAVE_IO_H
52 # include <io.h>
53 #endif
54 
55 #include "tiffio.h"
56 
57 #ifndef O_BINARY
58 # define O_BINARY 0
59 #endif
60 
61 enum BMPType
62 {
63     BMPT_WIN4,      /* BMP used in Windows 3.0/NT 3.51/95 */
64     BMPT_WIN5,      /* BMP used in Windows NT 4.0/98/Me/2000/XP */
65     BMPT_OS21,      /* BMP used in OS/2 PM 1.x */
66     BMPT_OS22       /* BMP used in OS/2 PM 2.x */
67 };
68 
69 /*
70  * Bitmap file consists of a BMPFileHeader structure followed by a
71  * BMPInfoHeader structure. An array of BMPColorEntry structures (also called
72  * a colour table) follows the bitmap information header structure. The colour
73  * table is followed by a second array of indexes into the colour table (the
74  * actual bitmap data). Data may be comressed, for 4-bpp and 8-bpp used RLE
75  * compression.
76  *
77  * +---------------------+
78  * | BMPFileHeader       |
79  * +---------------------+
80  * | BMPInfoHeader       |
81  * +---------------------+
82  * | BMPColorEntry array |
83  * +---------------------+
84  * | Colour-index array  |
85  * +---------------------+
86  *
87  * All numbers stored in Intel order with least significant byte first.
88  */
89 
90 enum BMPComprMethod
91 {
92     BMPC_RGB = 0L,          /* Uncompressed */
93     BMPC_RLE8 = 1L,         /* RLE for 8 bpp images */
94     BMPC_RLE4 = 2L,         /* RLE for 4 bpp images */
95     BMPC_BITFIELDS = 3L,    /* Bitmap is not compressed and the colour table
96 			     * consists of three DWORD color masks that specify
97 			     * the red, green, and blue components of each
98 			     * pixel. This is valid when used with
99 			     * 16- and 32-bpp bitmaps. */
100     BMPC_JPEG = 4L,         /* Indicates that the image is a JPEG image. */
101     BMPC_PNG = 5L           /* Indicates that the image is a PNG image. */
102 };
103 
104 enum BMPLCSType                 /* Type of logical color space. */
105 {
106     BMPLT_CALIBRATED_RGB = 0,	/* This value indicates that endpoints and
107 				 * gamma values are given in the appropriate
108 				 * fields. */
109     BMPLT_DEVICE_RGB = 1,
110     BMPLT_DEVICE_CMYK = 2
111 };
112 
113 typedef struct
114 {
115     int32   iCIEX;
116     int32   iCIEY;
117     int32   iCIEZ;
118 } BMPCIEXYZ;
119 
120 typedef struct                  /* This structure contains the x, y, and z */
121 {				/* coordinates of the three colors that */
122 				/* correspond */
123     BMPCIEXYZ   iCIERed;        /* to the red, green, and blue endpoints for */
124     BMPCIEXYZ   iCIEGreen;      /* a specified logical color space. */
125     BMPCIEXYZ	iCIEBlue;
126 } BMPCIEXYZTriple;
127 
128 typedef struct
129 {
130     char	bType[2];       /* Signature "BM" */
131     uint32	iSize;          /* Size in bytes of the bitmap file. Should
132 				 * always be ignored while reading because
133 				 * of error in Windows 3.0 SDK's description
134 				 * of this field */
135     uint16	iReserved1;     /* Reserved, set as 0 */
136     uint16	iReserved2;     /* Reserved, set as 0 */
137     uint32	iOffBits;       /* Offset of the image from file start in bytes */
138 } BMPFileHeader;
139 
140 /* File header size in bytes: */
141 const int       BFH_SIZE = 14;
142 
143 typedef struct
144 {
145     uint32	iSize;          /* Size of BMPInfoHeader structure in bytes.
146 				 * Should be used to determine start of the
147 				 * colour table */
148     int32	iWidth;         /* Image width */
149     int32	iHeight;        /* Image height. If positive, image has bottom
150 				 * left origin, if negative --- top left. */
151     int16	iPlanes;        /* Number of image planes (must be set to 1) */
152     int16	iBitCount;      /* Number of bits per pixel (1, 4, 8, 16, 24
153 				 * or 32). If 0 then the number of bits per
154 				 * pixel is specified or is implied by the
155 				 * JPEG or PNG format. */
156     uint32	iCompression;	/* Compression method */
157     uint32	iSizeImage;     /* Size of uncomressed image in bytes. May
158 				 * be 0 for BMPC_RGB bitmaps. If iCompression
159 				 * is BI_JPEG or BI_PNG, iSizeImage indicates
160 				 * the size of the JPEG or PNG image buffer. */
161     int32	iXPelsPerMeter; /* X resolution, pixels per meter (0 if not used) */
162     int32	iYPelsPerMeter; /* Y resolution, pixels per meter (0 if not used) */
163     uint32	iClrUsed;       /* Size of colour table. If 0, iBitCount should
164 				 * be used to calculate this value
165 				 * (1<<iBitCount). This value should be
166 				 * unsigned for proper shifting. */
167     int32	iClrImportant;  /* Number of important colours. If 0, all
168 				 * colours are required */
169 
170     /*
171      * Fields above should be used for bitmaps, compatible with Windows NT 3.51
172      * and earlier. Windows 98/Me, Windows 2000/XP introduces additional fields:
173      */
174 
175     int32	iRedMask;       /* Colour mask that specifies the red component
176 				 * of each pixel, valid only if iCompression
177 				 * is set to BI_BITFIELDS. */
178     int32	iGreenMask;     /* The same for green component */
179     int32	iBlueMask;      /* The same for blue component */
180     int32	iAlphaMask;     /* Colour mask that specifies the alpha
181 				 * component of each pixel. */
182     uint32	iCSType;        /* Colour space of the DIB. */
183     BMPCIEXYZTriple sEndpoints; /* This member is ignored unless the iCSType
184 				 * member specifies BMPLT_CALIBRATED_RGB. */
185     int32	iGammaRed;      /* Toned response curve for red. This member
186 				 * is ignored unless color values are
187 				 * calibrated RGB values and iCSType is set to
188 				 * BMPLT_CALIBRATED_RGB. Specified
189 				 * in 16^16 format. */
190     int32	iGammaGreen;    /* Toned response curve for green. */
191     int32	iGammaBlue;     /* Toned response curve for blue. */
192 } BMPInfoHeader;
193 
194 /*
195  * Info header size in bytes:
196  */
197 const unsigned int  BIH_WIN4SIZE = 40; /* for BMPT_WIN4 */
198 const unsigned int  BIH_WIN5SIZE = 57; /* for BMPT_WIN5 */
199 const unsigned int  BIH_OS21SIZE = 12; /* for BMPT_OS21 */
200 const unsigned int  BIH_OS22SIZE = 64; /* for BMPT_OS22 */
201 
202 /*
203  * We will use plain byte array instead of this structure, but declaration
204  * provided for reference
205  */
206 typedef struct
207 {
208     char       bBlue;
209     char       bGreen;
210     char       bRed;
211     char       bReserved;      /* Must be 0 */
212 } BMPColorEntry;
213 
214 static	uint16 compression = (uint16) -1;
215 static	int jpegcolormode = JPEGCOLORMODE_RGB;
216 static	int quality = 75;		/* JPEG quality */
217 static	uint16 predictor = 0;
218 
219 static void usage(void);
220 static int processCompressOptions(char*);
221 static void rearrangePixels(char *, uint32, uint32);
222 
223 int
main(int argc,char * argv[])224 main(int argc, char* argv[])
225 {
226 	uint32	width, length;
227 	uint16	nbands = 1;		/* number of bands in input image */
228         uint16	depth = 8;		/* bits per pixel in input image */
229 	uint32	rowsperstrip = (uint32) -1;
230         uint16	photometric = PHOTOMETRIC_MINISBLACK;
231 	int	fd = 0;
232 	struct stat instat;
233 	char	*outfilename = NULL, *infilename = NULL;
234 	TIFF	*out = NULL;
235 
236 	BMPFileHeader file_hdr;
237         BMPInfoHeader info_hdr;
238         int     bmp_type;
239         uint32  clr_tbl_size, n_clr_elems = 3;
240         unsigned char *clr_tbl;
241 	unsigned short *red_tbl = NULL, *green_tbl = NULL, *blue_tbl = NULL;
242 	uint32	row, clr;
243 
244 	int	c;
245 	extern int optind;
246 	extern char* optarg;
247 
248 	while ((c = getopt(argc, argv, "c:r:o:h")) != -1) {
249 		switch (c) {
250 		case 'c':		/* compression scheme */
251 			if (!processCompressOptions(optarg))
252 				usage();
253 			break;
254 		case 'r':		/* rows/strip */
255 			rowsperstrip = atoi(optarg);
256 			break;
257 		case 'o':
258 			outfilename = optarg;
259 			break;
260 		case 'h':
261 			usage();
262 		default:
263 			break;
264 		}
265 	}
266 
267 	if (argc - optind < 2)
268 		usage();
269 
270 	if (outfilename == NULL)
271 		outfilename = argv[argc-1];
272 	out = TIFFOpen(outfilename, "w");
273 	if (out == NULL) {
274 		TIFFError(infilename, "Cannot open file %s for output",
275 			  outfilename);
276 		goto bad3;
277 	}
278 
279 
280 	while (optind < argc-1) {
281 		infilename = argv[optind];
282 		optind++;
283 
284 		fd = open(infilename, O_RDONLY|O_BINARY, 0);
285 		if (fd < 0) {
286 			TIFFError(infilename, "Cannot open input file");
287 			return -1;
288 		}
289 
290 		read(fd, file_hdr.bType, 2);
291 		if(file_hdr.bType[0] != 'B' || file_hdr.bType[1] != 'M') {
292 			TIFFError(infilename, "File is not BMP");
293 			goto bad;
294 		}
295 
296 /* -------------------------------------------------------------------- */
297 /*      Read the BMPFileHeader. We need iOffBits value only             */
298 /* -------------------------------------------------------------------- */
299 		lseek(fd, 10, SEEK_SET);
300 		read(fd, &file_hdr.iOffBits, 4);
301 #ifdef WORDS_BIGENDIAN
302 		TIFFSwabLong(&file_hdr.iOffBits);
303 #endif
304 		fstat(fd, &instat);
305 		file_hdr.iSize = instat.st_size;
306 
307 /* -------------------------------------------------------------------- */
308 /*      Read the BMPInfoHeader.                                         */
309 /* -------------------------------------------------------------------- */
310 
311 		lseek(fd, BFH_SIZE, SEEK_SET);
312 		read(fd, &info_hdr.iSize, 4);
313 #ifdef WORDS_BIGENDIAN
314 		TIFFSwabLong(&info_hdr.iSize);
315 #endif
316 
317 		if (info_hdr.iSize == BIH_WIN4SIZE)
318 			bmp_type = BMPT_WIN4;
319 		else if (info_hdr.iSize == BIH_OS21SIZE)
320 			bmp_type = BMPT_OS21;
321 		else if (info_hdr.iSize == BIH_OS22SIZE
322 			 || info_hdr.iSize == 16)
323 			bmp_type = BMPT_OS22;
324 		else
325 			bmp_type = BMPT_WIN5;
326 
327 		if (bmp_type == BMPT_WIN4
328 		    || bmp_type == BMPT_WIN5
329 		    || bmp_type == BMPT_OS22) {
330 			read(fd, &info_hdr.iWidth, 4);
331 			read(fd, &info_hdr.iHeight, 4);
332 			read(fd, &info_hdr.iPlanes, 2);
333 			read(fd, &info_hdr.iBitCount, 2);
334 			read(fd, &info_hdr.iCompression, 4);
335 			read(fd, &info_hdr.iSizeImage, 4);
336 			read(fd, &info_hdr.iXPelsPerMeter, 4);
337 			read(fd, &info_hdr.iYPelsPerMeter, 4);
338 			read(fd, &info_hdr.iClrUsed, 4);
339 			read(fd, &info_hdr.iClrImportant, 4);
340 #ifdef WORDS_BIGENDIAN
341 			TIFFSwabLong((uint32*) &info_hdr.iWidth);
342 			TIFFSwabLong((uint32*) &info_hdr.iHeight);
343 			TIFFSwabShort((uint16*) &info_hdr.iPlanes);
344 			TIFFSwabShort((uint16*) &info_hdr.iBitCount);
345 			TIFFSwabLong((uint32*) &info_hdr.iCompression);
346 			TIFFSwabLong((uint32*) &info_hdr.iSizeImage);
347 			TIFFSwabLong((uint32*) &info_hdr.iXPelsPerMeter);
348 			TIFFSwabLong((uint32*) &info_hdr.iYPelsPerMeter);
349 			TIFFSwabLong((uint32*) &info_hdr.iClrUsed);
350 			TIFFSwabLong((uint32*) &info_hdr.iClrImportant);
351 #endif
352 			n_clr_elems = 4;
353 		}
354 
355 		if (bmp_type == BMPT_OS22) {
356 			/*
357 			 * FIXME: different info in different documents
358 			 * regarding this!
359 			 */
360 			 n_clr_elems = 3;
361 		}
362 
363 		if (bmp_type == BMPT_OS21) {
364 			int16  iShort;
365 
366 			read(fd, &iShort, 2);
367 #ifdef WORDS_BIGENDIAN
368 			TIFFSwabShort((uint16*) &iShort);
369 #endif
370 			info_hdr.iWidth = iShort;
371 			read(fd, &iShort, 2);
372 #ifdef WORDS_BIGENDIAN
373 			TIFFSwabShort((uint16*) &iShort);
374 #endif
375 			info_hdr.iHeight = iShort;
376 			read(fd, &iShort, 2);
377 #ifdef WORDS_BIGENDIAN
378 			TIFFSwabShort((uint16*) &iShort);
379 #endif
380 			info_hdr.iPlanes = iShort;
381 			read(fd, &iShort, 2);
382 #ifdef WORDS_BIGENDIAN
383 			TIFFSwabShort((uint16*) &iShort);
384 #endif
385 			info_hdr.iBitCount = iShort;
386 			info_hdr.iCompression = BMPC_RGB;
387 			n_clr_elems = 3;
388 		}
389 
390 		if (info_hdr.iBitCount != 1  && info_hdr.iBitCount != 4  &&
391 		    info_hdr.iBitCount != 8  && info_hdr.iBitCount != 16 &&
392 		    info_hdr.iBitCount != 24 && info_hdr.iBitCount != 32) {
393 		    TIFFError(infilename,
394 			      "Cannot process BMP file with bit count %d",
395 			      info_hdr.iBitCount);
396 		    close(fd);
397 		    return 0;
398 		}
399 
400 		width = info_hdr.iWidth;
401 		length = (info_hdr.iHeight > 0) ? info_hdr.iHeight : -info_hdr.iHeight;
402 
403 		switch (info_hdr.iBitCount)
404 		{
405 			case 1:
406 			case 4:
407 			case 8:
408 				nbands = 1;
409 				depth = info_hdr.iBitCount;
410 				photometric = PHOTOMETRIC_PALETTE;
411 				/* Allocate memory for colour table and read it. */
412 				if (info_hdr.iClrUsed)
413 				    clr_tbl_size =
414 					    ((uint32)(1<<depth)<info_hdr.iClrUsed)
415 					    ? (uint32) (1 << depth)
416 					    : info_hdr.iClrUsed;
417 				else
418 				    clr_tbl_size = 1 << depth;
419 				clr_tbl = (unsigned char *)
420 					_TIFFmalloc(n_clr_elems * clr_tbl_size);
421 				if (!clr_tbl) {
422 					TIFFError(infilename,
423 					"Can't allocate space for color table");
424 					goto bad;
425 				}
426 
427 				lseek(fd, BFH_SIZE + info_hdr.iSize, SEEK_SET);
428 				read(fd, clr_tbl, n_clr_elems * clr_tbl_size);
429 
430 				red_tbl = (unsigned short*)
431 					_TIFFmalloc(1<<depth * sizeof(unsigned short));
432 				if (!red_tbl) {
433 					TIFFError(infilename,
434 				"Can't allocate space for red component table");
435 					_TIFFfree(clr_tbl);
436 					goto bad1;
437 				}
438 				green_tbl = (unsigned short*)
439 					_TIFFmalloc(1<<depth * sizeof(unsigned short));
440 				if (!green_tbl) {
441 					TIFFError(infilename,
442 				"Can't allocate space for green component table");
443 					_TIFFfree(clr_tbl);
444 					goto bad2;
445 				}
446 				blue_tbl = (unsigned short*)
447 					_TIFFmalloc(1<<depth * sizeof(unsigned short));
448 				if (!blue_tbl) {
449 					TIFFError(infilename,
450 				"Can't allocate space for blue component table");
451 					_TIFFfree(clr_tbl);
452 					goto bad3;
453 				}
454 
455 				for(clr = 0; clr < clr_tbl_size; clr++) {
456 				    red_tbl[clr] = 257*clr_tbl[clr*n_clr_elems+2];
457 				    green_tbl[clr] = 257*clr_tbl[clr*n_clr_elems+1];
458 				    blue_tbl[clr] = 257*clr_tbl[clr*n_clr_elems];
459 				}
460 
461 				_TIFFfree(clr_tbl);
462 				break;
463 			case 16:
464 			case 24:
465 				nbands = 3;
466 				depth = info_hdr.iBitCount / nbands;
467 				photometric = PHOTOMETRIC_RGB;
468 				break;
469 			case 32:
470 				nbands = 3;
471 				depth = 8;
472 				photometric = PHOTOMETRIC_RGB;
473 				break;
474 			default:
475 				break;
476 		}
477 
478 /* -------------------------------------------------------------------- */
479 /*  Create output file.                                                 */
480 /* -------------------------------------------------------------------- */
481 
482 		TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
483 		TIFFSetField(out, TIFFTAG_IMAGELENGTH, length);
484 		TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
485 		TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, nbands);
486 		TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, depth);
487 		TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
488 		TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
489 		TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
490 			     TIFFDefaultStripSize(out, rowsperstrip));
491 
492 		if (red_tbl && green_tbl && blue_tbl) {
493 			TIFFSetField(out, TIFFTAG_COLORMAP,
494 				     red_tbl, green_tbl, blue_tbl);
495 		}
496 
497 		if (compression == (uint16) -1)
498 			compression = COMPRESSION_PACKBITS;
499 		TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
500 		switch (compression) {
501 		case COMPRESSION_JPEG:
502 			if (photometric == PHOTOMETRIC_RGB
503 			    && jpegcolormode == JPEGCOLORMODE_RGB)
504 				photometric = PHOTOMETRIC_YCBCR;
505 			TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
506 			TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
507 			break;
508 		case COMPRESSION_LZW:
509 		case COMPRESSION_DEFLATE:
510 			if (predictor != 0)
511 				TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
512 			break;
513 		}
514 
515 /* -------------------------------------------------------------------- */
516 /*  Read uncompressed image data.                                       */
517 /* -------------------------------------------------------------------- */
518 
519 		if (info_hdr.iCompression == BMPC_RGB) {
520 			uint32 offset, size;
521 			char *scanbuf;
522 
523 			/* XXX: Avoid integer overflow. We can calculate size
524 			 * in one step using
525 			 *
526 			 *  size = ((width * info_hdr.iBitCount + 31) & ~31) / 8
527 			 *
528 			 * formulae, but we should check for overflow
529 			 * conditions during calculation.
530 			 */
531 			size = width * info_hdr.iBitCount + 31;
532 			if (!width || !info_hdr.iBitCount
533 			    || (size - 31) / info_hdr.iBitCount != width ) {
534 				TIFFError(infilename,
535 					  "Wrong image parameters; can't "
536 					  "allocate space for scanline buffer");
537 				goto bad3;
538 			}
539 			size = (size & ~31) / 8;
540 
541 			scanbuf = (char *) _TIFFmalloc(size);
542 			if (!scanbuf) {
543 				TIFFError(infilename,
544 				"Can't allocate space for scanline buffer");
545 				goto bad3;
546 			}
547 
548 			for (row = 0; row < length; row++) {
549 				if (info_hdr.iHeight > 0)
550 					offset = file_hdr.iOffBits+(length-row-1)*size;
551 				else
552 					offset = file_hdr.iOffBits + row * size;
553 				if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
554 					TIFFError(infilename,
555 						  "scanline %lu: Seek error",
556 						  (unsigned long) row);
557 					break;
558 				}
559 
560 				if (read(fd, scanbuf, size) < 0) {
561 					TIFFError(infilename,
562 						  "scanline %lu: Read error",
563 						  (unsigned long) row);
564 					break;
565 				}
566 
567 				rearrangePixels(scanbuf, width, info_hdr.iBitCount);
568 
569 				if (TIFFWriteScanline(out, scanbuf, row, 0)<0) {
570 					TIFFError(infilename,
571 						  "scanline %lu: Write error",
572 						  (unsigned long) row);
573 					break;
574 				}
575 			}
576 
577 			_TIFFfree(scanbuf);
578 
579 /* -------------------------------------------------------------------- */
580 /*  Read compressed image data.                                         */
581 /* -------------------------------------------------------------------- */
582 
583 		} else if ( info_hdr.iCompression == BMPC_RLE8
584 			    || info_hdr.iCompression == BMPC_RLE4 ) {
585 			uint32		i, j, k, runlength;
586 			uint32		compr_size, uncompr_size;
587 			unsigned char   *comprbuf;
588 			unsigned char   *uncomprbuf;
589 
590 			compr_size = file_hdr.iSize - file_hdr.iOffBits;
591 			uncompr_size = width * length;
592 			comprbuf = (unsigned char *) _TIFFmalloc( compr_size );
593 			if (!comprbuf) {
594 				TIFFError(infilename,
595 			"Can't allocate space for compressed scanline buffer");
596 				goto bad3;
597 			}
598 			uncomprbuf = (unsigned char *)_TIFFmalloc(uncompr_size);
599 			if (!uncomprbuf) {
600 				TIFFError(infilename,
601 			"Can't allocate space for uncompressed scanline buffer");
602 				goto bad3;
603 			}
604 
605 			lseek(fd, file_hdr.iOffBits, SEEK_SET);
606 			read(fd, comprbuf, compr_size);
607 			i = 0;
608 			j = 0;
609 			if (info_hdr.iBitCount == 8) {		/* RLE8 */
610 			    while(j < uncompr_size && i < compr_size) {
611 				if ( comprbuf[i] ) {
612 				    runlength = comprbuf[i++];
613 				    while( runlength > 0
614 					   && j < uncompr_size
615 					   && i < compr_size ) {
616 					uncomprbuf[j++] = comprbuf[i];
617 					runlength--;
618 				    }
619 				    i++;
620 				} else {
621 				    i++;
622 				    if (comprbuf[i] == 0) /* Next scanline */
623 					i++;
624 				    else if (comprbuf[i] == 1) /* End of image */
625 					break;
626 				    else if (comprbuf[i] == 2) { /* Move to... */
627 					i++;
628 					if (i < compr_size - 1) {
629 					    j+=comprbuf[i]+comprbuf[i+1]*width;
630 					    i += 2;
631 					}
632 					else
633 					    break;
634 				    } else {            /* Absolute mode */
635 					runlength = comprbuf[i++];
636 					for (k = 0; k < runlength && j < uncompr_size && i < compr_size; k++)
637 					    uncomprbuf[j++] = comprbuf[i++];
638 					if ( k & 0x01 )
639 					    i++;
640 				    }
641 				}
642 			    }
643 			}
644 			else {				    /* RLE4 */
645 			    while( j < uncompr_size && i < compr_size ) {
646 				if ( comprbuf[i] ) {
647 				    runlength = comprbuf[i++];
648 				    while( runlength > 0 && j < uncompr_size && i < compr_size ) {
649 					if ( runlength & 0x01 )
650 					    uncomprbuf[j++] = (comprbuf[i] & 0xF0) >> 4;
651 					else
652 					    uncomprbuf[j++] = comprbuf[i] & 0x0F;
653 					runlength--;
654 				    }
655 				    i++;
656 				} else {
657 				    i++;
658 				    if (comprbuf[i] == 0) /* Next scanline */
659 					i++;
660 				    else if (comprbuf[i] == 1) /* End of image */
661 					break;
662 				    else if (comprbuf[i] == 2) { /* Move to... */
663 					i++;
664 					if (i < compr_size - 1) {
665 					    j+=comprbuf[i]+comprbuf[i+1]*width;
666 					    i += 2;
667 					}
668 					else
669 					    break;
670 				    } else {            /* Absolute mode */
671 					runlength = comprbuf[i++];
672 					for (k = 0; k < runlength && j < uncompr_size && i < compr_size; k++) {
673 					    if (k & 0x01)
674 						uncomprbuf[j++] = comprbuf[i++] & 0x0F;
675 					    else
676 						uncomprbuf[j++] = (comprbuf[i] & 0xF0) >> 4;
677 					}
678 					if (k & 0x01)
679 					    i++;
680 				    }
681 				}
682 			    }
683 			}
684 
685 			_TIFFfree(comprbuf);
686 
687 			for (row = 0; row < length; row++) {
688 				if (TIFFWriteScanline(out,
689 					uncomprbuf + (length - row - 1) * width,
690 					row, 0) < 0) {
691 					TIFFError(infilename,
692 						"scanline %lu: Write error.\n",
693 						  (unsigned long) row);
694 				}
695 			}
696 
697 			_TIFFfree(uncomprbuf);
698 		}
699 		TIFFWriteDirectory(out);
700 		if (blue_tbl) {
701 		  _TIFFfree(blue_tbl);
702 		  blue_tbl=NULL;
703 		}
704 		if (green_tbl) {
705 		  _TIFFfree(green_tbl);
706 		  green_tbl=NULL;
707 		}
708 		if (red_tbl) {
709 		  _TIFFfree(red_tbl);
710 		  red_tbl=NULL;
711 		}
712 	}
713 
714 bad3:
715 	if (blue_tbl)
716 		_TIFFfree(blue_tbl);
717 bad2:
718 	if (green_tbl)
719 		_TIFFfree(green_tbl);
720 bad1:
721 	if (red_tbl)
722 		_TIFFfree(red_tbl);
723 bad:
724         close(fd);
725 
726 	if (out)
727 		TIFFClose(out);
728         return 0;
729 }
730 
731 /*
732  * Image data in BMP file stored in BGR (or ABGR) format. We should rearrange
733  * pixels to RGB (RGBA) format.
734  */
735 static void
rearrangePixels(char * buf,uint32 width,uint32 bit_count)736 rearrangePixels(char *buf, uint32 width, uint32 bit_count)
737 {
738 	char tmp;
739 	uint32 i;
740 
741         switch(bit_count) {
742 		case 16:    /* FIXME: need a sample file */
743                         break;
744                 case 24:
745 			for (i = 0; i < width; i++, buf += 3) {
746 				tmp = *buf;
747 				*buf = *(buf + 2);
748 				*(buf + 2) = tmp;
749 			}
750                         break;
751                 case 32:
752 			{
753 				char	*buf1 = buf;
754 
755 				for (i = 0; i < width; i++, buf += 4) {
756 					tmp = *buf;
757 					*buf1++ = *(buf + 2);
758 					*buf1++ = *(buf + 1);
759 					*buf1++ = tmp;
760 				}
761 			}
762                         break;
763                 default:
764                         break;
765         }
766 }
767 
768 static int
processCompressOptions(char * opt)769 processCompressOptions(char* opt)
770 {
771 	if (strcmp(opt, "none") == 0)
772 		compression = COMPRESSION_NONE;
773 	else if (strcmp(opt, "packbits") == 0)
774 		compression = COMPRESSION_PACKBITS;
775 	else if (strncmp(opt, "jpeg", 4) == 0) {
776 		char* cp = strchr(opt, ':');
777 
778                 compression = COMPRESSION_JPEG;
779                 while( cp )
780                 {
781                     if (isdigit((int)cp[1]))
782 			quality = atoi(cp+1);
783                     else if (cp[1] == 'r' )
784 			jpegcolormode = JPEGCOLORMODE_RAW;
785                     else
786                         usage();
787 
788                     cp = strchr(cp+1,':');
789                 }
790 	} else if (strncmp(opt, "lzw", 3) == 0) {
791 		char* cp = strchr(opt, ':');
792 		if (cp)
793 			predictor = atoi(cp+1);
794 		compression = COMPRESSION_LZW;
795 	} else if (strncmp(opt, "zip", 3) == 0) {
796 		char* cp = strchr(opt, ':');
797 		if (cp)
798 			predictor = atoi(cp+1);
799 		compression = COMPRESSION_DEFLATE;
800 	} else
801 		return (0);
802 	return (1);
803 }
804 
805 static char* stuff[] = {
806 "bmp2tiff --- convert Windows BMP files to TIFF",
807 "usage: bmp2tiff [options] input.bmp [input2.bmp ...] output.tif",
808 "where options are:",
809 " -r #		make each strip have no more than # rows",
810 "",
811 " -c lzw[:opts]	compress output with Lempel-Ziv & Welch encoding",
812 " -c zip[:opts]	compress output with deflate encoding",
813 " -c jpeg[:opts]compress output with JPEG encoding",
814 " -c packbits	compress output with packbits encoding",
815 " -c none	use no compression algorithm on output",
816 "",
817 "JPEG options:",
818 " #		set compression quality level (0-100, default 75)",
819 " r		output color image as RGB rather than YCbCr",
820 "For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality",
821 "",
822 "LZW and deflate options:",
823 " #		set predictor value",
824 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
825 " -o out.tif	write output to out.tif",
826 " -h		this help message",
827 NULL
828 };
829 
830 static void
usage(void)831 usage(void)
832 {
833 	char buf[BUFSIZ];
834 	int i;
835 
836 	setbuf(stderr, buf);
837         fprintf(stderr, "%s\n\n", TIFFGetVersion());
838 	for (i = 0; stuff[i] != NULL; i++)
839 		fprintf(stderr, "%s\n", stuff[i]);
840 	exit(-1);
841 }
842 
843 /* vim: set ts=8 sts=8 sw=8 noet: */
844