1/* $Id: bmp2tiff.c,v 1.20.2.1 2010-06-08 18:50:43 bfriesen 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 61enum 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 90enum 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 104enum 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 113typedef struct 114{ 115 int32 iCIEX; 116 int32 iCIEY; 117 int32 iCIEZ; 118} BMPCIEXYZ; 119 120typedef 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 128typedef 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: */ 141const int BFH_SIZE = 14; 142 143typedef 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 */ 197const unsigned int BIH_WIN4SIZE = 40; /* for BMPT_WIN4 */ 198const unsigned int BIH_WIN5SIZE = 57; /* for BMPT_WIN5 */ 199const unsigned int BIH_OS21SIZE = 12; /* for BMPT_OS21 */ 200const 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 */ 206typedef struct 207{ 208 char bBlue; 209 char bGreen; 210 char bRed; 211 char bReserved; /* Must be 0 */ 212} BMPColorEntry; 213 214static uint16 compression = (uint16) -1; 215static int jpegcolormode = JPEGCOLORMODE_RGB; 216static int quality = 75; /* JPEG quality */ 217static uint16 predictor = 0; 218 219static void usage(void); 220static int processCompressOptions(char*); 221static void rearrangePixels(char *, uint32, uint32); 222 223int 224main(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 714bad3: 715 if (blue_tbl) 716 _TIFFfree(blue_tbl); 717bad2: 718 if (green_tbl) 719 _TIFFfree(green_tbl); 720bad1: 721 if (red_tbl) 722 _TIFFfree(red_tbl); 723bad: 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 */ 735static void 736rearrangePixels(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 768static int 769processCompressOptions(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 805static 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", 827NULL 828}; 829 830static void 831usage(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/* 845 * Local Variables: 846 * mode: c 847 * c-basic-offset: 8 848 * fill-column: 78 849 * End: 850 */ 851