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