From e31354c76d93fe17ad252e8bdf3cc3a56ddf6f57 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Tue, 8 Jun 2004 15:54:12 +0000 Subject: [PATCH] bmp2tiff utility added. --- tools/Makefile.am | 3 + tools/Makefile.in | 74 +++-- tools/Makefile.vc | 6 +- tools/bmp2tiff.c | 728 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 776 insertions(+), 35 deletions(-) create mode 100644 tools/bmp2tiff.c diff --git a/tools/Makefile.am b/tools/Makefile.am index 57248b42..8f7442c3 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -35,6 +35,7 @@ BIN_TIFFGT = endif bin_PROGRAMS = \ + bmp2tiff \ fax2ps \ fax2tiff \ gif2tiff \ @@ -59,6 +60,8 @@ bin_PROGRAMS = \ $(BIN_TIFFGT) EXTRA_PROGRAMS = $(BIN_TIFFGT) sgi2tiff sgisv ycbcr +bmp2tiff_SOURCES = bmp2tiff.c +bmp2tiff_LDADD = $(LIBTIFF) $(LIBPORT) fax2ps_SOURCES = fax2ps.c fax2ps_LDADD = $(LIBTIFF) $(LIBPORT) fax2tiff_SOURCES = fax2tiff.c diff --git a/tools/Makefile.in b/tools/Makefile.in index c34d6642..d50d0387 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -39,7 +39,7 @@ # Process this file with automake to produce Makefile.in. -SOURCES = $(fax2ps_SOURCES) $(fax2tiff_SOURCES) $(gif2tiff_SOURCES) $(pal2rgb_SOURCES) $(ppm2tiff_SOURCES) $(ras2tiff_SOURCES) $(raw2tiff_SOURCES) $(rgb2ycbcr_SOURCES) sgi2tiff.c sgisv.c $(thumbnail_SOURCES) $(tiff2bw_SOURCES) $(tiff2pdf_SOURCES) $(tiff2ps_SOURCES) $(tiff2rgba_SOURCES) $(tiffcmp_SOURCES) $(tiffcp_SOURCES) $(tiffdither_SOURCES) $(tiffdump_SOURCES) $(tiffgt_SOURCES) $(tiffinfo_SOURCES) $(tiffmedian_SOURCES) $(tiffset_SOURCES) $(tiffsplit_SOURCES) ycbcr.c +SOURCES = $(bmp2tiff_SOURCES) $(fax2ps_SOURCES) $(fax2tiff_SOURCES) $(gif2tiff_SOURCES) $(pal2rgb_SOURCES) $(ppm2tiff_SOURCES) $(ras2tiff_SOURCES) $(raw2tiff_SOURCES) $(rgb2ycbcr_SOURCES) sgi2tiff.c sgisv.c $(thumbnail_SOURCES) $(tiff2bw_SOURCES) $(tiff2pdf_SOURCES) $(tiff2ps_SOURCES) $(tiff2rgba_SOURCES) $(tiffcmp_SOURCES) $(tiffcp_SOURCES) $(tiffdither_SOURCES) $(tiffdump_SOURCES) $(tiffgt_SOURCES) $(tiffinfo_SOURCES) $(tiffmedian_SOURCES) $(tiffset_SOURCES) $(tiffsplit_SOURCES) ycbcr.c srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -62,14 +62,14 @@ NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ -bin_PROGRAMS = fax2ps$(EXEEXT) fax2tiff$(EXEEXT) gif2tiff$(EXEEXT) \ - pal2rgb$(EXEEXT) ppm2tiff$(EXEEXT) ras2tiff$(EXEEXT) \ - raw2tiff$(EXEEXT) rgb2ycbcr$(EXEEXT) thumbnail$(EXEEXT) \ - tiff2bw$(EXEEXT) tiff2pdf$(EXEEXT) tiff2ps$(EXEEXT) \ - tiff2rgba$(EXEEXT) tiffcmp$(EXEEXT) tiffcp$(EXEEXT) \ - tiffdither$(EXEEXT) tiffdump$(EXEEXT) tiffinfo$(EXEEXT) \ - tiffmedian$(EXEEXT) tiffset$(EXEEXT) tiffsplit$(EXEEXT) \ - $(am__EXEEXT_1) +bin_PROGRAMS = bmp2tiff$(EXEEXT) fax2ps$(EXEEXT) fax2tiff$(EXEEXT) \ + gif2tiff$(EXEEXT) pal2rgb$(EXEEXT) ppm2tiff$(EXEEXT) \ + ras2tiff$(EXEEXT) raw2tiff$(EXEEXT) rgb2ycbcr$(EXEEXT) \ + thumbnail$(EXEEXT) tiff2bw$(EXEEXT) tiff2pdf$(EXEEXT) \ + tiff2ps$(EXEEXT) tiff2rgba$(EXEEXT) tiffcmp$(EXEEXT) \ + tiffcp$(EXEEXT) tiffdither$(EXEEXT) tiffdump$(EXEEXT) \ + tiffinfo$(EXEEXT) tiffmedian$(EXEEXT) tiffset$(EXEEXT) \ + tiffsplit$(EXEEXT) $(am__EXEEXT_1) EXTRA_PROGRAMS = $(am__EXEEXT_1) sgi2tiff$(EXEEXT) sgisv$(EXEEXT) \ ycbcr$(EXEEXT) subdir = tools @@ -86,9 +86,12 @@ CONFIG_CLEAN_FILES = am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) +am_bmp2tiff_OBJECTS = bmp2tiff.$(OBJEXT) +bmp2tiff_OBJECTS = $(am_bmp2tiff_OBJECTS) +am__DEPENDENCIES_1 = +bmp2tiff_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_fax2ps_OBJECTS = fax2ps.$(OBJEXT) fax2ps_OBJECTS = $(am_fax2ps_OBJECTS) -am__DEPENDENCIES_1 = fax2ps_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_fax2tiff_OBJECTS = fax2tiff.$(OBJEXT) fax2tiff_OBJECTS = $(am_fax2tiff_OBJECTS) @@ -165,19 +168,19 @@ ycbcr_LDADD = $(LDADD) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/libtiff depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/fax2ps.Po ./$(DEPDIR)/fax2tiff.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/gif2tiff.Po ./$(DEPDIR)/pal2rgb.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ppm2tiff.Po ./$(DEPDIR)/ras2tiff.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/raw2tiff.Po ./$(DEPDIR)/rgb2ycbcr.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/sgi2tiff.Po ./$(DEPDIR)/sgisv.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/thumbnail.Po ./$(DEPDIR)/tiff2bw.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/tiff2pdf.Po ./$(DEPDIR)/tiff2ps.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/tiff2rgba.Po ./$(DEPDIR)/tiffcmp.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/tiffcp.Po ./$(DEPDIR)/tiffdither.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/tiffdump.Po ./$(DEPDIR)/tiffgt.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/tiffinfo.Po ./$(DEPDIR)/tiffmedian.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/tiffset.Po ./$(DEPDIR)/tiffsplit.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ycbcr.Po +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/bmp2tiff.Po ./$(DEPDIR)/fax2ps.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/fax2tiff.Po ./$(DEPDIR)/gif2tiff.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pal2rgb.Po ./$(DEPDIR)/ppm2tiff.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/ras2tiff.Po ./$(DEPDIR)/raw2tiff.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/rgb2ycbcr.Po ./$(DEPDIR)/sgi2tiff.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/sgisv.Po ./$(DEPDIR)/thumbnail.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/tiff2bw.Po ./$(DEPDIR)/tiff2pdf.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/tiff2ps.Po ./$(DEPDIR)/tiff2rgba.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/tiffcmp.Po ./$(DEPDIR)/tiffcp.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/tiffdither.Po ./$(DEPDIR)/tiffdump.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/tiffgt.Po ./$(DEPDIR)/tiffinfo.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/tiffmedian.Po ./$(DEPDIR)/tiffset.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/tiffsplit.Po ./$(DEPDIR)/ycbcr.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \ @@ -186,15 +189,7 @@ LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \ CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(fax2ps_SOURCES) $(fax2tiff_SOURCES) $(gif2tiff_SOURCES) \ - $(pal2rgb_SOURCES) $(ppm2tiff_SOURCES) $(ras2tiff_SOURCES) \ - $(raw2tiff_SOURCES) $(rgb2ycbcr_SOURCES) sgi2tiff.c sgisv.c \ - $(thumbnail_SOURCES) $(tiff2bw_SOURCES) $(tiff2pdf_SOURCES) \ - $(tiff2ps_SOURCES) $(tiff2rgba_SOURCES) $(tiffcmp_SOURCES) \ - $(tiffcp_SOURCES) $(tiffdither_SOURCES) $(tiffdump_SOURCES) \ - $(tiffgt_SOURCES) $(tiffinfo_SOURCES) $(tiffmedian_SOURCES) \ - $(tiffset_SOURCES) $(tiffsplit_SOURCES) ycbcr.c -DIST_SOURCES = $(fax2ps_SOURCES) $(fax2tiff_SOURCES) \ +SOURCES = $(bmp2tiff_SOURCES) $(fax2ps_SOURCES) $(fax2tiff_SOURCES) \ $(gif2tiff_SOURCES) $(pal2rgb_SOURCES) $(ppm2tiff_SOURCES) \ $(ras2tiff_SOURCES) $(raw2tiff_SOURCES) $(rgb2ycbcr_SOURCES) \ sgi2tiff.c sgisv.c $(thumbnail_SOURCES) $(tiff2bw_SOURCES) \ @@ -203,6 +198,15 @@ DIST_SOURCES = $(fax2ps_SOURCES) $(fax2tiff_SOURCES) \ $(tiffdump_SOURCES) $(tiffgt_SOURCES) $(tiffinfo_SOURCES) \ $(tiffmedian_SOURCES) $(tiffset_SOURCES) $(tiffsplit_SOURCES) \ ycbcr.c +DIST_SOURCES = $(bmp2tiff_SOURCES) $(fax2ps_SOURCES) \ + $(fax2tiff_SOURCES) $(gif2tiff_SOURCES) $(pal2rgb_SOURCES) \ + $(ppm2tiff_SOURCES) $(ras2tiff_SOURCES) $(raw2tiff_SOURCES) \ + $(rgb2ycbcr_SOURCES) sgi2tiff.c sgisv.c $(thumbnail_SOURCES) \ + $(tiff2bw_SOURCES) $(tiff2pdf_SOURCES) $(tiff2ps_SOURCES) \ + $(tiff2rgba_SOURCES) $(tiffcmp_SOURCES) $(tiffcp_SOURCES) \ + $(tiffdither_SOURCES) $(tiffdump_SOURCES) $(tiffgt_SOURCES) \ + $(tiffinfo_SOURCES) $(tiffmedian_SOURCES) $(tiffset_SOURCES) \ + $(tiffsplit_SOURCES) ycbcr.c ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -321,6 +325,8 @@ LIBTIFF = -L$(top_builddir)/libtiff -ltiff EXTRA_DIST = Makefile.vc @HAVE_OPENGL_FALSE@BIN_TIFFGT = @HAVE_OPENGL_TRUE@BIN_TIFFGT = tiffgt +bmp2tiff_SOURCES = bmp2tiff.c +bmp2tiff_LDADD = $(LIBTIFF) $(LIBPORT) fax2ps_SOURCES = fax2ps.c fax2ps_LDADD = $(LIBTIFF) $(LIBPORT) fax2tiff_SOURCES = fax2tiff.c @@ -427,6 +433,9 @@ clean-binPROGRAMS: echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done +bmp2tiff$(EXEEXT): $(bmp2tiff_OBJECTS) $(bmp2tiff_DEPENDENCIES) + @rm -f bmp2tiff$(EXEEXT) + $(LINK) $(bmp2tiff_LDFLAGS) $(bmp2tiff_OBJECTS) $(bmp2tiff_LDADD) $(LIBS) fax2ps$(EXEEXT): $(fax2ps_OBJECTS) $(fax2ps_DEPENDENCIES) @rm -f fax2ps$(EXEEXT) $(LINK) $(fax2ps_LDFLAGS) $(fax2ps_OBJECTS) $(fax2ps_LDADD) $(LIBS) @@ -509,6 +518,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bmp2tiff.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fax2ps.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fax2tiff.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gif2tiff.Po@am__quote@ diff --git a/tools/Makefile.vc b/tools/Makefile.vc index 776b8f7e..41d067d3 100644 --- a/tools/Makefile.vc +++ b/tools/Makefile.vc @@ -1,4 +1,4 @@ -# $Id: Makefile.vc,v 1.8 2004-06-06 17:58:29 dron Exp $ +# $Id: Makefile.vc,v 1.9 2004-06-08 15:54:12 dron Exp $ # # Copyright (C) 2004, Andrey Kiselev # @@ -28,8 +28,8 @@ !INCLUDE ..\nmake.opt -TARGETS = tiffcp.exe tiffinfo.exe tiffdump.exe fax2tiff.exe \ - fax2ps.exe gif2tiff.exe pal2rgb.exe ppm2tiff.exe \ +TARGETS = bmp2tiff.exe tiffcp.exe tiffinfo.exe tiffdump.exe \ + fax2tiff.exe fax2ps.exe gif2tiff.exe pal2rgb.exe ppm2tiff.exe \ rgb2ycbcr.exe thumbnail.exe ras2tiff.exe raw2tiff.exe \ tiff2bw.exe tiff2rgba.exe tiff2pdf.exe tiff2ps.exe \ tiffcmp.exe tiffdither.exe tiffmedian.exe tiffsplit.exe diff --git a/tools/bmp2tiff.c b/tools/bmp2tiff.c new file mode 100644 index 00000000..2c4905e1 --- /dev/null +++ b/tools/bmp2tiff.c @@ -0,0 +1,728 @@ +/* $Id: bmp2tiff.c,v 1.1 2004-06-08 15:54:12 dron Exp $ + * + * Project: libtiff tools + * Purpose: Convert Windows BMP files in TIFF. + * Author: Andrey Kiselev, dron@remotesensing.org + * + ****************************************************************************** + * Copyright (c) 2004, Andrey Kiselev + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "tiffio.h" + +enum BMPType +{ + BMPT_WIN4, /* BMP used in Windows 3.0/NT 3.51/95 */ + BMPT_WIN5, /* BMP used in Windows NT 4.0/98/Me/2000/XP */ + BMPT_OS21, /* BMP used in OS/2 PM 1.x */ + BMPT_OS22 /* BMP used in OS/2 PM 2.x */ +}; + +/* + * Bitmap file consists of a BMPFileHeader structure followed by a + * BMPInfoHeader structure. An array of BMPColorEntry structures (also called + * a colour table) follows the bitmap information header structure. The colour + * table is followed by a second array of indexes into the colour table (the + * actual bitmap data). Data may be comressed, for 4-bpp and 8-bpp used RLE + * compression. + * + * +---------------------+ + * | BMPFileHeader | + * +---------------------+ + * | BMPInfoHeader | + * +---------------------+ + * | BMPColorEntry array | + * +---------------------+ + * | Colour-index array | + * +---------------------+ + * + * All numbers stored in Intel order with least significant byte first. + */ + +enum BMPComprMethod +{ + BMPC_RGB = 0L, /* Uncompressed */ + BMPC_RLE8 = 1L, /* RLE for 8 bpp images */ + BMPC_RLE4 = 2L, /* RLE for 4 bpp images */ + BMPC_BITFIELDS = 3L, /* Bitmap is not compressed and the colour table + * consists of three DWORD color masks that specify + * the red, green, and blue components of each + * pixel. This is valid when used with + * 16- and 32-bpp bitmaps. */ + BMPC_JPEG = 4L, /* Indicates that the image is a JPEG image. */ + BMPC_PNG = 5L /* Indicates that the image is a PNG image. */ +}; + +enum BMPLCSType /* Type of logical color space. */ +{ + BMPLT_CALIBRATED_RGB = 0, /* This value indicates that endpoints and + * gamma values are given in the appropriate + * fields. */ + BMPLT_DEVICE_RGB = 1, + BMPLT_DEVICE_CMYK = 2 +}; + +typedef struct +{ + int32 iCIEX; + int32 iCIEY; + int32 iCIEZ; +} BMPCIEXYZ; + +typedef struct /* This structure contains the x, y, and z */ +{ /* coordinates of the three colors that */ + /* correspond */ + BMPCIEXYZ iCIERed; /* to the red, green, and blue endpoints for */ + BMPCIEXYZ iCIEGreen; /* a specified logical color space. */ + BMPCIEXYZ iCIEBlue; +} BMPCIEXYZTriple; + +typedef struct +{ + char bType[2]; /* Signature "BM" */ + uint32 iSize; /* Size in bytes of the bitmap file. Should + * always be ignored while reading because + * of error in Windows 3.0 SDK's description + * of this field */ + uint16 iReserved1; /* Reserved, set as 0 */ + uint16 iReserved2; /* Reserved, set as 0 */ + uint32 iOffBits; /* Offset of the image from file start in bytes */ +} BMPFileHeader; + +/* File header size in bytes: */ +const int BFH_SIZE = 14; + +typedef struct +{ + uint32 iSize; /* Size of BMPInfoHeader structure in bytes. + * Should be used to determine start of the + * colour table */ + int32 iWidth; /* Image width */ + int32 iHeight; /* Image height. If positive, image has bottom + * left origin, if negative --- top left. */ + int16 iPlanes; /* Number of image planes (must be set to 1) */ + int16 iBitCount; /* Number of bits per pixel (1, 4, 8, 16, 24 + * or 32). If 0 then the number of bits per + * pixel is specified or is implied by the + * JPEG or PNG format. */ + uint32 iCompression; /* Compression method */ + uint32 iSizeImage; /* Size of uncomressed image in bytes. May + * be 0 for BMPC_RGB bitmaps. If iCompression + * is BI_JPEG or BI_PNG, iSizeImage indicates + * the size of the JPEG or PNG image buffer. */ + int32 iXPelsPerMeter; /* X resolution, pixels per meter (0 if not used) */ + int32 iYPelsPerMeter; /* Y resolution, pixels per meter (0 if not used) */ + int32 iClrUsed; /* Size of colour table. If 0, iBitCount should + * be used to calculate this value + * (1< 0) ? info_hdr.iHeight : -info_hdr.iHeight; + + switch (info_hdr.iBitCount) + { + case 1: + case 4: + case 8: + nbands = 1; + depth = info_hdr.iBitCount; + photometric = PHOTOMETRIC_PALETTE; + /* Allocate memory for colour table and read it. */ + if (info_hdr.iClrUsed) + clr_tbl_size = (1 << depth < info_hdr.iClrUsed) ? + 1 << depth : info_hdr.iClrUsed; + else + clr_tbl_size = 1 << depth; + clr_tbl = (unsigned char *) + _TIFFmalloc(n_clr_elems * clr_tbl_size); + + fseek(in, BFH_SIZE + info_hdr.iSize, SEEK_SET); + fread(clr_tbl, n_clr_elems, clr_tbl_size, in); + + red_tbl = (unsigned short*) + _TIFFmalloc(1< 0) + offset = file_hdr.iOffBits + (length - row - 1) * size; + else + offset = file_hdr.iOffBits + row * size; + if (fseek(in, offset, SEEK_SET) == -1) { + fprintf(stderr, + "%s: %s: scanline %lu: Seek error.\n", + argv[0], argv[optind], + (unsigned long) row); + } + + if (fread(scanbuf, size, 1, in) != 1) { + fprintf(stderr, + "%s: %s: scanline %lu: Read error.\n", + argv[0], argv[optind], + (unsigned long) row); + } + + rearrangePixels(scanbuf, width, info_hdr.iBitCount); + + if (TIFFWriteScanline(out, scanbuf, row, 0) < 0) { + fprintf(stderr, + "%s: %s: scanline %lu: Write error.\n", + argv[0], outfilename, + (unsigned long) row); + } + } + + _TIFFfree(scanbuf); + +/* -------------------------------------------------------------------- */ +/* Read compressed image data. */ +/* -------------------------------------------------------------------- */ + + } else if ( info_hdr.iCompression == BMPC_RLE8 + || info_hdr.iCompression == BMPC_RLE4 ) { + uint32 i, j, k, runlength; + uint32 compr_size, uncompr_size; + unsigned char *comprbuf; + unsigned char *uncomprbuf; + + compr_size = file_hdr.iSize - file_hdr.iOffBits; + uncompr_size = width * length; + comprbuf = (unsigned char *) _TIFFmalloc( compr_size ); + uncomprbuf = (unsigned char *) _TIFFmalloc( uncompr_size ); + + fseek(in, file_hdr.iOffBits, SEEK_SET); + fread(comprbuf, 1, compr_size, in); + i = 0; + j = 0; + if (info_hdr.iBitCount == 8) { /* RLE8 */ + while( j < uncompr_size && i < compr_size ) { + if ( comprbuf[i] ) { + runlength = comprbuf[i++]; + while( runlength > 0 + && j < uncompr_size + && i < compr_size ) { + uncomprbuf[j++] = comprbuf[i]; + runlength--; + } + i++; + } else { + i++; + if ( comprbuf[i] == 0 ) /* Next scanline */ + i++; + else if ( comprbuf[i] == 1 ) /* End of image */ + break; + else if ( comprbuf[i] == 2 ) { /* Move to... */ + i++; + if ( i < compr_size - 1 ) { + j += comprbuf[i] + comprbuf[i+1] * width; + i += 2; + } + else + break; + } else { /* Absolute mode */ + runlength = comprbuf[i++]; + for ( k = 0; k < runlength && j < uncompr_size && i < compr_size; k++ ) + uncomprbuf[j++] = comprbuf[i++]; + if ( k & 0x01 ) + i++; + } + } + } + } + else { /* RLE4 */ + while( j < uncompr_size && i < compr_size ) { + if ( comprbuf[i] ) { + runlength = comprbuf[i++]; + while( runlength > 0 && j < uncompr_size && i < compr_size ) { + if ( runlength & 0x01 ) + uncomprbuf[j++] = (comprbuf[i] & 0xF0) >> 4; + else + uncomprbuf[j++] = comprbuf[i] & 0x0F; + runlength--; + } + i++; + } else { + i++; + if ( comprbuf[i] == 0 ) /* Next scanline */ + i++; + else if ( comprbuf[i] == 1 ) /* End of image */ + break; + else if ( comprbuf[i] == 2 ) { /* Move to... */ + i++; + if ( i < compr_size - 1 ) { + j += comprbuf[i] + comprbuf[i+1] * width; + i += 2; + } + else + break; + } else { /* Absolute mode */ + runlength = comprbuf[i++]; + for ( k = 0; k < runlength && j < uncompr_size && i < compr_size; k++) { + if ( k & 0x01 ) + uncomprbuf[j++] = comprbuf[i++] & 0x0F; + else + uncomprbuf[j++] = (comprbuf[i] & 0xF0) >> 4; + } + if ( k & 0x01 ) + i++; + } + } + } + } + + _TIFFfree(comprbuf); + + for (row = 0; row < length; row++) { + if (TIFFWriteScanline(out, uncomprbuf + (length - row - 1) * width, row, 0) < 0) { + fprintf(stderr, + "%s: %s: scanline %lu: Write error.\n", + argv[0], outfilename, + (unsigned long) row); + } + } + + _TIFFfree(uncomprbuf); + } + + if (red_tbl && green_tbl && blue_tbl) { + _TIFFfree(red_tbl); + _TIFFfree(green_tbl); + _TIFFfree(blue_tbl); + } + + fclose(in); + TIFFClose(out); + return 0; +} + +/* + * Image data in BMP file stored in BGR (or ABGR) format. We should rearrange + * pixels to RGB (RGBA) format. + */ +static void +rearrangePixels(char *buf, uint32 width, uint32 bit_count) +{ + char tmp; + int i; + + switch(bit_count) { + case 16: /* FIXME: need a sample file */ + break; + case 24: + for (i = 0; i < width; i++, buf += 3) { + tmp = *buf; + *buf = *(buf + 2); + *(buf + 2) = tmp; + } + break; + case 32: + { + char *buf1 = buf; + + for (i = 0; i < width; i++, buf += 4) { + tmp = *buf; + *buf1++ = *(buf + 2); + *buf1++ = *(buf + 1); + *buf1++ = tmp; + } + } + break; + default: + break; + } +} + +static int +processCompressOptions(char* opt) +{ + if (strcmp(opt, "none") == 0) + compression = COMPRESSION_NONE; + else if (strcmp(opt, "packbits") == 0) + compression = COMPRESSION_PACKBITS; + else if (strncmp(opt, "jpeg", 4) == 0) { + char* cp = strchr(opt, ':'); + if (cp && isdigit(cp[1])) + quality = atoi(cp+1); + if (cp && strchr(cp, 'r')) + jpegcolormode = JPEGCOLORMODE_RAW; + compression = COMPRESSION_JPEG; + } else if (strncmp(opt, "lzw", 3) == 0) { + char* cp = strchr(opt, ':'); + if (cp) + predictor = atoi(cp+1); + compression = COMPRESSION_LZW; + } else if (strncmp(opt, "zip", 3) == 0) { + char* cp = strchr(opt, ':'); + if (cp) + predictor = atoi(cp+1); + compression = COMPRESSION_DEFLATE; + } else + return (0); + return (1); +} + +static char* stuff[] = { +"bmp2tiff --- tool for converting Windows BMP files in TIFF", +"usage: bmp2tiff [options] input.bmp output.tif", +"where options are:", +" -r # make each strip have no more than # rows", +"", +" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding", +" (no longer supported by default due to Unisys patent enforcement)", +" -c zip[:opts] compress output with deflate encoding", +" -c jpeg[:opts]compress output with JPEG encoding", +" -c packbits compress output with packbits encoding", +" -c none use no compression algorithm on output", +"", +"JPEG options:", +" # set compression quality level (0-100, default 75)", +" r output color image as RGB rather than YCbCr", +"For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality", +"", +"LZW and deflate options:", +" # set predictor value", +"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing", +" -o out.tif write output to out.tif", +" -h this help message", +NULL +}; + +static void +usage(void) +{ + char buf[BUFSIZ]; + int i; + + setbuf(stderr, buf); + fprintf(stderr, "%s\n\n", TIFFGetVersion()); + for (i = 0; stuff[i] != NULL; i++) + fprintf(stderr, "%s\n", stuff[i]); + exit(-1); +} +