3  * Project:  libtiff tools 
   4  * Purpose:  Convert Windows BMP files in TIFF. 
   5  * Author:   Andrey Kiselev, dron@ak4719.spb.edu 
   7  ****************************************************************************** 
   8  * Copyright (c) 2004, Andrey Kiselev <dron@ak4719.spb.edu> 
  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. 
  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.   
  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  
  30 #include "tif_config.h" 
  36 #include <sys/types.h> 
  48 # include <sys/types.h> 
  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 */ 
  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 
  77  * +---------------------+ 
  79  * +---------------------+ 
  81  * +---------------------+ 
  82  * | BMPColorEntry array | 
  83  * +---------------------+ 
  84  * | Colour-index array  | 
  85  * +---------------------+ 
  87  * All numbers stored in Intel order with least significant byte first. 
  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. */ 
 104 enum BMPLCSType                 
/* Type of logical color space. */ 
 106     BMPLT_CALIBRATED_RGB 
= 0,   /* This value indicates that endpoints and 
 107                                  * gamma values are given in the appropriate 
 109     BMPLT_DEVICE_RGB 
= 1, 
 110     BMPLT_DEVICE_CMYK 
= 2 
 120 typedef struct                  /* This structure contains the x, y, and z */ 
 121 {                               /* coordinates of the three colors that */ 
 123     BMPCIEXYZ   iCIERed
;        /* to the red, green, and blue endpoints for */ 
 124     BMPCIEXYZ   iCIEGreen
;      /* a specified logical color space. */ 
 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 
 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 */ 
 140 /* File header size in bytes: */ 
 141 const int       BFH_SIZE 
= 14; 
 145     uint32      iSize
;          /* Size of BMPInfoHeader structure in bytes. 
 146                                  * Should be used to determine start of the 
 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 */ 
 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: 
 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. */ 
 195  * Info header size in bytes: 
 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 */ 
 203  * We will use plain byte array instead of this structure, but declaration 
 204  * provided for reference 
 211     char       bReserved
;      /* Must be 0 */ 
 214 static  uint16 compression 
= (uint16
) -1; 
 215 static  int jpegcolormode 
= JPEGCOLORMODE_RGB
; 
 216 static  int quality 
= 75;               /* JPEG quality */ 
 217 static  uint16 predictor 
= 0; 
 219 static void usage(void); 
 220 static int processCompressOptions(char*); 
 221 static void rearrangePixels(char *, uint32
, uint32
); 
 224 main(int argc
, char* argv
[]) 
 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
; 
 233         char    *outfilename 
= NULL
, *infilename 
= NULL
; 
 236         BMPFileHeader file_hdr
; 
 237         BMPInfoHeader info_hdr
; 
 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
; 
 248         while ((c 
= getopt(argc
, argv
, "c:r:o:h")) != -1) { 
 250                 case 'c':               /* compression scheme */ 
 251                         if (!processCompressOptions(optarg
)) 
 254                 case 'r':               /* rows/strip */ 
 255                         rowsperstrip 
= atoi(optarg
); 
 258                         outfilename 
= optarg
; 
 267         if (argc 
- optind 
< 2) 
 270         if (outfilename 
== NULL
) 
 271                 outfilename 
= argv
[argc
-1]; 
 272         out 
= TIFFOpen(outfilename
, "w"); 
 274                 TIFFError(infilename
, "Cannot open file %s for output", 
 280         while (optind 
< argc
-1) { 
 281                 infilename 
= argv
[optind
]; 
 284                 fd 
= open(infilename
, O_RDONLY
|O_BINARY
, 0); 
 286                         TIFFError(infilename
, "Cannot open input file"); 
 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"); 
 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
); 
 305                 file_hdr
.iSize 
= instat
.st_size
; 
 307 /* -------------------------------------------------------------------- */ 
 308 /*      Read the BMPInfoHeader.                                         */ 
 309 /* -------------------------------------------------------------------- */ 
 311                 lseek(fd
, BFH_SIZE
, SEEK_SET
); 
 312                 read(fd
, &info_hdr
.iSize
, 4); 
 313 #ifdef WORDS_BIGENDIAN 
 314                 TIFFSwabLong(&info_hdr
.iSize
); 
 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
; 
 325                         bmp_type 
= BMPT_WIN5
; 
 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
); 
 355                 if (bmp_type 
== BMPT_OS22
) { 
 357                          * FIXME: different info in different documents 
 363                 if (bmp_type 
== BMPT_OS21
) { 
 366                         read(fd
, &iShort
, 2); 
 367 #ifdef WORDS_BIGENDIAN 
 368                         TIFFSwabShort((uint16
*) &iShort
); 
 370                         info_hdr
.iWidth 
= iShort
; 
 371                         read(fd
, &iShort
, 2); 
 372 #ifdef WORDS_BIGENDIAN 
 373                         TIFFSwabShort((uint16
*) &iShort
); 
 375                         info_hdr
.iHeight 
= iShort
; 
 376                         read(fd
, &iShort
, 2); 
 377 #ifdef WORDS_BIGENDIAN 
 378                         TIFFSwabShort((uint16
*) &iShort
); 
 380                         info_hdr
.iPlanes 
= iShort
; 
 381                         read(fd
, &iShort
, 2); 
 382 #ifdef WORDS_BIGENDIAN 
 383                         TIFFSwabShort((uint16
*) &iShort
); 
 385                         info_hdr
.iBitCount 
= iShort
; 
 386                         info_hdr
.iCompression 
= BMPC_RGB
; 
 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", 
 400                 width 
= info_hdr
.iWidth
; 
 401                 length 
= (info_hdr
.iHeight 
> 0) ? info_hdr
.iHeight 
: -info_hdr
.iHeight
; 
 403                 switch (info_hdr
.iBitCount
) 
 409                                 depth 
= info_hdr
.iBitCount
; 
 410                                 photometric 
= PHOTOMETRIC_PALETTE
; 
 411                                 /* Allocate memory for colour table and read it. */ 
 412                                 if (info_hdr
.iClrUsed
) 
 414                                             ((uint32
)(1<<depth
)<info_hdr
.iClrUsed
) 
 415                                             ? (uint32
) (1 << depth
) 
 418                                     clr_tbl_size 
= 1 << depth
; 
 419                                 clr_tbl 
= (unsigned char *) 
 420                                         _TIFFmalloc(n_clr_elems 
* clr_tbl_size
); 
 422                                         TIFFError(infilename
, 
 423                                         "Can't allocate space for color table"); 
 427                                 lseek(fd
, BFH_SIZE 
+ info_hdr
.iSize
, SEEK_SET
); 
 428                                 read(fd
, clr_tbl
, n_clr_elems 
* clr_tbl_size
); 
 430                                 red_tbl 
= (unsigned short*) 
 431                                         _TIFFmalloc(1<<depth 
* sizeof(unsigned short)); 
 433                                         TIFFError(infilename
, 
 434                                 "Can't allocate space for red component table"); 
 438                                 green_tbl 
= (unsigned short*) 
 439                                         _TIFFmalloc(1<<depth 
* sizeof(unsigned short)); 
 441                                         TIFFError(infilename
, 
 442                                 "Can't allocate space for green component table"); 
 446                                 blue_tbl 
= (unsigned short*) 
 447                                         _TIFFmalloc(1<<depth 
* sizeof(unsigned short)); 
 449                                         TIFFError(infilename
, 
 450                                 "Can't allocate space for blue component table"); 
 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
]; 
 466                                 depth 
= info_hdr
.iBitCount 
/ nbands
; 
 467                                 photometric 
= PHOTOMETRIC_RGB
; 
 472                                 photometric 
= PHOTOMETRIC_RGB
; 
 478 /* -------------------------------------------------------------------- */ 
 479 /*  Create output file.                                                 */ 
 480 /* -------------------------------------------------------------------- */ 
 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
)); 
 492                 if (red_tbl 
&& green_tbl 
&& blue_tbl
) { 
 493                         TIFFSetField(out
, TIFFTAG_COLORMAP
, 
 494                                      red_tbl
, green_tbl
, blue_tbl
); 
 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
); 
 508                 case COMPRESSION_LZW
: 
 509                 case COMPRESSION_DEFLATE
: 
 511                                 TIFFSetField(out
, TIFFTAG_PREDICTOR
, predictor
); 
 515 /* -------------------------------------------------------------------- */ 
 516 /*  Read uncompressed image data.                                       */ 
 517 /* -------------------------------------------------------------------- */ 
 519                 if (info_hdr
.iCompression 
== BMPC_RGB
) { 
 523                         /* XXX: Avoid integer overflow. We can calculate size 
 526                          *  size = ((width * info_hdr.iBitCount + 31) & ~31) / 8 
 528                          * formulae, but we should check for overflow 
 529                          * conditions during calculation. 
 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"); 
 539                         size 
= (size 
& ~31) / 8; 
 541                         scanbuf 
= (char *) _TIFFmalloc(size
); 
 543                                 TIFFError(infilename
, 
 544                                 "Can't allocate space for scanline buffer"); 
 548                         for (row 
= 0; row 
< length
; row
++) { 
 549                                 if (info_hdr
.iHeight 
> 0) 
 550                                         offset 
= file_hdr
.iOffBits
+(length
-row
-1)*size
; 
 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
); 
 560                                 if (read(fd
, scanbuf
, size
) < 0) { 
 561                                         TIFFError(infilename
, 
 562                                                   "scanline %lu: Read error", 
 563                                                   (unsigned long) row
); 
 567                                 rearrangePixels(scanbuf
, width
, info_hdr
.iBitCount
); 
 569                                 if (TIFFWriteScanline(out
, scanbuf
, row
, 0)<0) { 
 570                                         TIFFError(infilename
, 
 571                                                   "scanline %lu: Write error", 
 572                                                   (unsigned long) row
); 
 579 /* -------------------------------------------------------------------- */ 
 580 /*  Read compressed image data.                                         */ 
 581 /* -------------------------------------------------------------------- */ 
 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
; 
 590                         compr_size 
= file_hdr
.iSize 
- file_hdr
.iOffBits
; 
 591                         uncompr_size 
= width 
* length
; 
 592                         comprbuf 
= (unsigned char *) _TIFFmalloc( compr_size 
); 
 594                                 TIFFError(infilename
, 
 595                         "Can't allocate space for compressed scanline buffer"); 
 598                         uncomprbuf 
= (unsigned char *)_TIFFmalloc(uncompr_size
); 
 600                                 TIFFError(infilename
, 
 601                         "Can't allocate space for uncompressed scanline buffer"); 
 605                         lseek(fd
, file_hdr
.iOffBits
, SEEK_SET
); 
 606                         read(fd
, comprbuf
, compr_size
); 
 609                         if (info_hdr
.iBitCount 
== 8) {          /* RLE8 */ 
 610                             while(j 
< uncompr_size 
&& i 
< compr_size
) { 
 612                                     runlength 
= comprbuf
[i
++]; 
 615                                            && i 
< compr_size 
) { 
 616                                         uncomprbuf
[j
++] = comprbuf
[i
]; 
 622                                     if (comprbuf
[i
] == 0) /* Next scanline */ 
 624                                     else if (comprbuf
[i
] == 1) /* End of image */ 
 626                                     else if (comprbuf
[i
] == 2) { /* Move to... */ 
 628                                         if (i 
< compr_size 
- 1) { 
 629                                             j
+=comprbuf
[i
]+comprbuf
[i
+1]*width
; 
 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
++]; 
 645                             while( j 
< uncompr_size 
&& i 
< compr_size 
) { 
 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; 
 652                                             uncomprbuf
[j
++] = comprbuf
[i
] & 0x0F; 
 658                                     if (comprbuf
[i
] == 0) /* Next scanline */ 
 660                                     else if (comprbuf
[i
] == 1) /* End of image */ 
 662                                     else if (comprbuf
[i
] == 2) { /* Move to... */ 
 664                                         if (i 
< compr_size 
- 1) { 
 665                                             j
+=comprbuf
[i
]+comprbuf
[i
+1]*width
; 
 670                                     } else {            /* Absolute mode */ 
 671                                         runlength 
= comprbuf
[i
++]; 
 672                                         for (k 
= 0; k 
< runlength 
&& j 
< uncompr_size 
&& i 
< compr_size
; k
++) { 
 674                                                 uncomprbuf
[j
++] = comprbuf
[i
++] & 0x0F; 
 676                                                 uncomprbuf
[j
++] = (comprbuf
[i
] & 0xF0) >> 4; 
 687                         for (row 
= 0; row 
< length
; row
++) { 
 688                                 if (TIFFWriteScanline(out
, 
 689                                         uncomprbuf 
+ (length 
- row 
- 1) * width
, 
 691                                         TIFFError(infilename
, 
 692                                                 "scanline %lu: Write error.\n", 
 693                                                   (unsigned long) row
); 
 697                         _TIFFfree(uncomprbuf
); 
 699                 TIFFWriteDirectory(out
); 
 705                   _TIFFfree(green_tbl
); 
 719                 _TIFFfree(green_tbl
); 
 732  * Image data in BMP file stored in BGR (or ABGR) format. We should rearrange 
 733  * pixels to RGB (RGBA) format. 
 736 rearrangePixels(char *buf
, uint32 width
, uint32 bit_count
) 
 742                 case 16:    /* FIXME: need a sample file */ 
 745                         for (i 
= 0; i 
< width
; i
++, buf 
+= 3) { 
 755                                 for (i 
= 0; i 
< width
; i
++, buf 
+= 4) { 
 757                                         *buf1
++ = *(buf 
+ 2); 
 758                                         *buf1
++ = *(buf 
+ 1); 
 769 processCompressOptions(char* opt
) 
 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
, ':'); 
 778                 compression 
= COMPRESSION_JPEG
; 
 781                     if (isdigit((int)cp
[1])) 
 782                         quality 
= atoi(cp
+1); 
 783                     else if (cp
[1] == 'r' ) 
 784                         jpegcolormode 
= JPEGCOLORMODE_RAW
; 
 788                     cp 
= strchr(cp
+1,':'); 
 790         } else if (strncmp(opt
, "lzw", 3) == 0) { 
 791                 char* cp 
= strchr(opt
, ':'); 
 793                         predictor 
= atoi(cp
+1); 
 794                 compression 
= COMPRESSION_LZW
; 
 795         } else if (strncmp(opt
, "zip", 3) == 0) { 
 796                 char* cp 
= strchr(opt
, ':'); 
 798                         predictor 
= atoi(cp
+1); 
 799                 compression 
= COMPRESSION_DEFLATE
; 
 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", 
 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", 
 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", 
 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", 
 837         fprintf(stderr
, "%s\n\n", TIFFGetVersion()); 
 838         for (i 
= 0; stuff
[i
] != NULL
; i
++) 
 839                 fprintf(stderr
, "%s\n", stuff
[i
]); 
 843 /* vim: set ts=8 sts=8 sw=8 noet: */