Added ability to create multipage TIFFs from the list of input files as per

bug: http://bugzilla.remotesensing.org/show_bug.cgi?id=1077
This commit is contained in:
Andrey Kiselev 2006-02-15 13:12:30 +00:00
parent b936f969d0
commit d4438d6fd4
2 changed files with 422 additions and 392 deletions

View File

@ -1,4 +1,4 @@
.\" $Id: bmp2tiff.1,v 1.4 2005-11-02 11:07:19 dron Exp $ .\" $Id: bmp2tiff.1,v 1.5 2006-02-15 13:12:30 dron Exp $
.\" .\"
.\" Copyright (c) 2004, Andrey Kiselev <dron@remotesensing.org> .\" Copyright (c) 2004, Andrey Kiselev <dron@remotesensing.org>
.\" .\"
@ -32,13 +32,15 @@ file from a Microsoft Windows Device Independent Bitmap image file
[ [
.I options .I options
] ]
.I input.bmp .I input.bmp [input2.bmp ...]
.I output.tiff .I output.tiff
.SH DESCRIPTION .SH DESCRIPTION
.I bmp2tiff .I bmp2tiff
converts a Microsoft Windows Device Independent Bitmap image file to converts a Microsoft Windows Device Independent Bitmap image file to
.SM TIFF. .SM TIFF.
By default, the If several input BMP files are being specified the multipage
.SM TIFF
output file will be created. By default, the
.SM TIFF .SM TIFF
image is created with data samples packed (\c image is created with data samples packed (\c
.IR PlanarConfiguration =1), .IR PlanarConfiguration =1),

View File

@ -1,4 +1,4 @@
/* $Id: bmp2tiff.c,v 1.18 2006-01-11 17:03:43 fwarmerdam Exp $ /* $Id: bmp2tiff.c,v 1.19 2006-02-15 13:12:54 dron Exp $
* *
* Project: libtiff tools * Project: libtiff tools
* Purpose: Convert Windows BMP files in TIFF. * Purpose: Convert Windows BMP files in TIFF.
@ -228,7 +228,7 @@ main(int argc, char* argv[])
uint16 depth = 8; /* bits per pixel in input image */ uint16 depth = 8; /* bits per pixel in input image */
uint32 rowsperstrip = (uint32) -1; uint32 rowsperstrip = (uint32) -1;
uint16 photometric = PHOTOMETRIC_MINISBLACK; uint16 photometric = PHOTOMETRIC_MINISBLACK;
int fd; int fd = 0;
struct stat instat; struct stat instat;
char *outfilename = NULL, *infilename = NULL; char *outfilename = NULL, *infilename = NULL;
TIFF *out = NULL; TIFF *out = NULL;
@ -267,201 +267,8 @@ main(int argc, char* argv[])
if (argc - optind < 2) if (argc - optind < 2)
usage(); usage();
infilename = argv[optind];
fd = open(infilename, O_RDONLY|O_BINARY, 0);
if (fd < 0) {
TIFFError(infilename, "Cannot open input file");
return -1;
}
read(fd, file_hdr.bType, 2);
if(file_hdr.bType[0] != 'B' || file_hdr.bType[1] != 'M') {
TIFFError(infilename, "File is not BMP");
goto bad;
}
/* -------------------------------------------------------------------- */
/* Read the BMPFileHeader. We need iOffBits value only */
/* -------------------------------------------------------------------- */
lseek(fd, 10, SEEK_SET);
read(fd, &file_hdr.iOffBits, 4);
#ifdef WORDS_BIGENDIAN
TIFFSwabLong(&file_hdr.iOffBits);
#endif
fstat(fd, &instat);
file_hdr.iSize = instat.st_size;
/* -------------------------------------------------------------------- */
/* Read the BMPInfoHeader. */
/* -------------------------------------------------------------------- */
lseek(fd, BFH_SIZE, SEEK_SET);
read(fd, &info_hdr.iSize, 4);
#ifdef WORDS_BIGENDIAN
TIFFSwabLong(&info_hdr.iSize);
#endif
if (info_hdr.iSize == BIH_WIN4SIZE)
bmp_type = BMPT_WIN4;
else if (info_hdr.iSize == BIH_OS21SIZE)
bmp_type = BMPT_OS21;
else if (info_hdr.iSize == BIH_OS22SIZE || info_hdr.iSize == 16)
bmp_type = BMPT_OS22;
else
bmp_type = BMPT_WIN5;
if (bmp_type == BMPT_WIN4 || bmp_type == BMPT_WIN5 || bmp_type == BMPT_OS22) {
read(fd, &info_hdr.iWidth, 4);
read(fd, &info_hdr.iHeight, 4);
read(fd, &info_hdr.iPlanes, 2);
read(fd, &info_hdr.iBitCount, 2);
read(fd, &info_hdr.iCompression, 4);
read(fd, &info_hdr.iSizeImage, 4);
read(fd, &info_hdr.iXPelsPerMeter, 4);
read(fd, &info_hdr.iYPelsPerMeter, 4);
read(fd, &info_hdr.iClrUsed, 4);
read(fd, &info_hdr.iClrImportant, 4);
#ifdef WORDS_BIGENDIAN
TIFFSwabLong((uint32*) &info_hdr.iWidth);
TIFFSwabLong((uint32*) &info_hdr.iHeight);
TIFFSwabShort((uint16*) &info_hdr.iPlanes);
TIFFSwabShort((uint16*) &info_hdr.iBitCount);
TIFFSwabLong((uint32*) &info_hdr.iCompression);
TIFFSwabLong((uint32*) &info_hdr.iSizeImage);
TIFFSwabLong((uint32*) &info_hdr.iXPelsPerMeter);
TIFFSwabLong((uint32*) &info_hdr.iYPelsPerMeter);
TIFFSwabLong((uint32*) &info_hdr.iClrUsed);
TIFFSwabLong((uint32*) &info_hdr.iClrImportant);
#endif
n_clr_elems = 4;
}
if (bmp_type == BMPT_OS22) {
/*
* FIXME: different info in different documents
* regarding this!
*/
n_clr_elems = 3;
}
if (bmp_type == BMPT_OS21) {
int16 iShort;
read(fd, &iShort, 2);
#ifdef WORDS_BIGENDIAN
TIFFSwabShort((uint16*) &iShort);
#endif
info_hdr.iWidth = iShort;
read(fd, &iShort, 2);
#ifdef WORDS_BIGENDIAN
TIFFSwabShort((uint16*) &iShort);
#endif
info_hdr.iHeight = iShort;
read(fd, &iShort, 2);
#ifdef WORDS_BIGENDIAN
TIFFSwabShort((uint16*) &iShort);
#endif
info_hdr.iPlanes = iShort;
read(fd, &iShort, 2);
#ifdef WORDS_BIGENDIAN
TIFFSwabShort((uint16*) &iShort);
#endif
info_hdr.iBitCount = iShort;
info_hdr.iCompression = BMPC_RGB;
n_clr_elems = 3;
}
if (info_hdr.iBitCount != 1 && info_hdr.iBitCount != 4 &&
info_hdr.iBitCount != 8 && info_hdr.iBitCount != 16 &&
info_hdr.iBitCount != 24 && info_hdr.iBitCount != 32) {
TIFFError(infilename, "Cannot process BMP file with bit count %d",
info_hdr.iBitCount);
close(fd);
return 0;
}
width = info_hdr.iWidth;
length = (info_hdr.iHeight > 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 = ((uint32)(1 << depth) < info_hdr.iClrUsed) ?
(uint32) (1 << depth) : info_hdr.iClrUsed;
else
clr_tbl_size = 1 << depth;
clr_tbl = (unsigned char *)
_TIFFmalloc(n_clr_elems * clr_tbl_size);
if (!clr_tbl) {
TIFFError(infilename,
"Can't allocate space for color table");
goto bad;
}
lseek(fd, BFH_SIZE + info_hdr.iSize, SEEK_SET);
read(fd, clr_tbl, n_clr_elems * clr_tbl_size);
red_tbl = (unsigned short*)
_TIFFmalloc(1<<depth * sizeof(unsigned short));
if (!red_tbl) {
TIFFError(infilename,
"Can't allocate space for red component table");
_TIFFfree(clr_tbl);
goto bad1;
}
green_tbl = (unsigned short*)
_TIFFmalloc(1<<depth * sizeof(unsigned short));
if (!green_tbl) {
TIFFError(infilename,
"Can't allocate space for green component table");
_TIFFfree(clr_tbl);
goto bad2;
}
blue_tbl = (unsigned short*)
_TIFFmalloc(1<<depth * sizeof(unsigned short));
if (!blue_tbl) {
TIFFError(infilename,
"Can't allocate space for blue component table");
_TIFFfree(clr_tbl);
goto bad3;
}
for(clr = 0; clr < clr_tbl_size; clr++) {
red_tbl[clr] = 257 * clr_tbl[clr*n_clr_elems+2];
green_tbl[clr] = 257 * clr_tbl[clr*n_clr_elems+1];
blue_tbl[clr] = 257 * clr_tbl[clr*n_clr_elems];
}
_TIFFfree(clr_tbl);
break;
case 16:
case 24:
nbands = 3;
depth = info_hdr.iBitCount / nbands;
photometric = PHOTOMETRIC_RGB;
break;
case 32:
nbands = 3;
depth = 8;
photometric = PHOTOMETRIC_RGB;
break;
default:
break;
}
/* -------------------------------------------------------------------- */
/* Create output file. */
/* -------------------------------------------------------------------- */
if (outfilename == NULL) if (outfilename == NULL)
outfilename = argv[optind+1]; outfilename = argv[argc-1];
out = TIFFOpen(outfilename, "w"); out = TIFFOpen(outfilename, "w");
if (out == NULL) { if (out == NULL) {
TIFFError(infilename, "Cannot open file %s for output", TIFFError(infilename, "Cannot open file %s for output",
@ -469,218 +276,439 @@ main(int argc, char* argv[])
goto bad3; goto bad3;
} }
TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(out, TIFFTAG_IMAGELENGTH, length); while (optind < argc-1) {
TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); infilename = argv[optind];
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, nbands); optind++;
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, depth);
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); fd = open(infilename, O_RDONLY|O_BINARY, 0);
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric); if (fd < 0) {
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFError(infilename, "Cannot open input file");
TIFFDefaultStripSize(out, rowsperstrip)); return -1;
}
if (red_tbl && green_tbl && blue_tbl)
TIFFSetField(out, TIFFTAG_COLORMAP, red_tbl, green_tbl, blue_tbl); read(fd, file_hdr.bType, 2);
if(file_hdr.bType[0] != 'B' || file_hdr.bType[1] != 'M') {
if (compression == (uint16) -1) TIFFError(infilename, "File is not BMP");
compression = COMPRESSION_PACKBITS; goto bad;
TIFFSetField(out, TIFFTAG_COMPRESSION, compression); }
switch (compression) {
case COMPRESSION_JPEG: /* -------------------------------------------------------------------- */
if (photometric == PHOTOMETRIC_RGB /* Read the BMPFileHeader. We need iOffBits value only */
&& jpegcolormode == JPEGCOLORMODE_RGB) /* -------------------------------------------------------------------- */
photometric = PHOTOMETRIC_YCBCR; lseek(fd, 10, SEEK_SET);
TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality); read(fd, &file_hdr.iOffBits, 4);
TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode); #ifdef WORDS_BIGENDIAN
break; TIFFSwabLong(&file_hdr.iOffBits);
case COMPRESSION_LZW: #endif
case COMPRESSION_DEFLATE: fstat(fd, &instat);
if (predictor != 0) file_hdr.iSize = instat.st_size;
TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
break; /* -------------------------------------------------------------------- */
} /* Read the BMPInfoHeader. */
/* -------------------------------------------------------------------- */
lseek(fd, BFH_SIZE, SEEK_SET);
read(fd, &info_hdr.iSize, 4);
#ifdef WORDS_BIGENDIAN
TIFFSwabLong(&info_hdr.iSize);
#endif
if (info_hdr.iSize == BIH_WIN4SIZE)
bmp_type = BMPT_WIN4;
else if (info_hdr.iSize == BIH_OS21SIZE)
bmp_type = BMPT_OS21;
else if (info_hdr.iSize == BIH_OS22SIZE
|| info_hdr.iSize == 16)
bmp_type = BMPT_OS22;
else
bmp_type = BMPT_WIN5;
if (bmp_type == BMPT_WIN4
|| bmp_type == BMPT_WIN5
|| bmp_type == BMPT_OS22) {
read(fd, &info_hdr.iWidth, 4);
read(fd, &info_hdr.iHeight, 4);
read(fd, &info_hdr.iPlanes, 2);
read(fd, &info_hdr.iBitCount, 2);
read(fd, &info_hdr.iCompression, 4);
read(fd, &info_hdr.iSizeImage, 4);
read(fd, &info_hdr.iXPelsPerMeter, 4);
read(fd, &info_hdr.iYPelsPerMeter, 4);
read(fd, &info_hdr.iClrUsed, 4);
read(fd, &info_hdr.iClrImportant, 4);
#ifdef WORDS_BIGENDIAN
TIFFSwabLong((uint32*) &info_hdr.iWidth);
TIFFSwabLong((uint32*) &info_hdr.iHeight);
TIFFSwabShort((uint16*) &info_hdr.iPlanes);
TIFFSwabShort((uint16*) &info_hdr.iBitCount);
TIFFSwabLong((uint32*) &info_hdr.iCompression);
TIFFSwabLong((uint32*) &info_hdr.iSizeImage);
TIFFSwabLong((uint32*) &info_hdr.iXPelsPerMeter);
TIFFSwabLong((uint32*) &info_hdr.iYPelsPerMeter);
TIFFSwabLong((uint32*) &info_hdr.iClrUsed);
TIFFSwabLong((uint32*) &info_hdr.iClrImportant);
#endif
n_clr_elems = 4;
}
if (bmp_type == BMPT_OS22) {
/*
* FIXME: different info in different documents
* regarding this!
*/
n_clr_elems = 3;
}
if (bmp_type == BMPT_OS21) {
int16 iShort;
read(fd, &iShort, 2);
#ifdef WORDS_BIGENDIAN
TIFFSwabShort((uint16*) &iShort);
#endif
info_hdr.iWidth = iShort;
read(fd, &iShort, 2);
#ifdef WORDS_BIGENDIAN
TIFFSwabShort((uint16*) &iShort);
#endif
info_hdr.iHeight = iShort;
read(fd, &iShort, 2);
#ifdef WORDS_BIGENDIAN
TIFFSwabShort((uint16*) &iShort);
#endif
info_hdr.iPlanes = iShort;
read(fd, &iShort, 2);
#ifdef WORDS_BIGENDIAN
TIFFSwabShort((uint16*) &iShort);
#endif
info_hdr.iBitCount = iShort;
info_hdr.iCompression = BMPC_RGB;
n_clr_elems = 3;
}
if (info_hdr.iBitCount != 1 && info_hdr.iBitCount != 4 &&
info_hdr.iBitCount != 8 && info_hdr.iBitCount != 16 &&
info_hdr.iBitCount != 24 && info_hdr.iBitCount != 32) {
TIFFError(infilename,
"Cannot process BMP file with bit count %d",
info_hdr.iBitCount);
close(fd);
return 0;
}
width = info_hdr.iWidth;
length = (info_hdr.iHeight > 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 =
((uint32)(1<<depth)<info_hdr.iClrUsed)
? (uint32) (1 << depth)
: info_hdr.iClrUsed;
else
clr_tbl_size = 1 << depth;
clr_tbl = (unsigned char *)
_TIFFmalloc(n_clr_elems * clr_tbl_size);
if (!clr_tbl) {
TIFFError(infilename,
"Can't allocate space for color table");
goto bad;
}
lseek(fd, BFH_SIZE + info_hdr.iSize, SEEK_SET);
read(fd, clr_tbl, n_clr_elems * clr_tbl_size);
red_tbl = (unsigned short*)
_TIFFmalloc(1<<depth * sizeof(unsigned short));
if (!red_tbl) {
TIFFError(infilename,
"Can't allocate space for red component table");
_TIFFfree(clr_tbl);
goto bad1;
}
green_tbl = (unsigned short*)
_TIFFmalloc(1<<depth * sizeof(unsigned short));
if (!green_tbl) {
TIFFError(infilename,
"Can't allocate space for green component table");
_TIFFfree(clr_tbl);
goto bad2;
}
blue_tbl = (unsigned short*)
_TIFFmalloc(1<<depth * sizeof(unsigned short));
if (!blue_tbl) {
TIFFError(infilename,
"Can't allocate space for blue component table");
_TIFFfree(clr_tbl);
goto bad3;
}
for(clr = 0; clr < clr_tbl_size; clr++) {
red_tbl[clr] = 257*clr_tbl[clr*n_clr_elems+2];
green_tbl[clr] = 257*clr_tbl[clr*n_clr_elems+1];
blue_tbl[clr] = 257*clr_tbl[clr*n_clr_elems];
}
_TIFFfree(clr_tbl);
break;
case 16:
case 24:
nbands = 3;
depth = info_hdr.iBitCount / nbands;
photometric = PHOTOMETRIC_RGB;
break;
case 32:
nbands = 3;
depth = 8;
photometric = PHOTOMETRIC_RGB;
break;
default:
break;
}
/* -------------------------------------------------------------------- */
/* Create output file. */
/* -------------------------------------------------------------------- */
TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(out, TIFFTAG_IMAGELENGTH, length);
TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, nbands);
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, depth);
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
TIFFDefaultStripSize(out, rowsperstrip));
if (red_tbl && green_tbl && blue_tbl) {
TIFFSetField(out, TIFFTAG_COLORMAP,
red_tbl, green_tbl, blue_tbl);
}
if (compression == (uint16) -1)
compression = COMPRESSION_PACKBITS;
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
switch (compression) {
case COMPRESSION_JPEG:
if (photometric == PHOTOMETRIC_RGB
&& jpegcolormode == JPEGCOLORMODE_RGB)
photometric = PHOTOMETRIC_YCBCR;
TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
break;
case COMPRESSION_LZW:
case COMPRESSION_DEFLATE:
if (predictor != 0)
TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
break;
}
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Read uncompressed image data. */ /* Read uncompressed image data. */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
if (info_hdr.iCompression == BMPC_RGB) { if (info_hdr.iCompression == BMPC_RGB) {
uint32 offset, size; uint32 offset, size;
char *scanbuf; char *scanbuf;
/* XXX: Avoid integer overflow. We can calculate size in one /* XXX: Avoid integer overflow. We can calculate size
* step using * in one step using
* *
* size = ((width * info_hdr.iBitCount + 31) & ~31) / 8 * size = ((width * info_hdr.iBitCount + 31) & ~31) / 8
* *
* formulae, but we should check for overflow conditions * formulae, but we should check for overflow
* during calculation. * conditions during calculation.
*/ */
size = width * info_hdr.iBitCount + 31; size = width * info_hdr.iBitCount + 31;
if (!width || !info_hdr.iBitCount if (!width || !info_hdr.iBitCount
|| (size - 31) / info_hdr.iBitCount != width ) { || (size - 31) / info_hdr.iBitCount != width ) {
TIFFError(infilename,
"Wrong image parameters; "
"can't allocate space for scanline buffer");
goto bad3;
}
size = (size & ~31) / 8;
scanbuf = (char *) _TIFFmalloc(size);
if (!scanbuf) {
TIFFError(infilename,
"Can't allocate space for scanline buffer");
goto bad3;
}
for (row = 0; row < length; row++) {
if (info_hdr.iHeight > 0)
offset = file_hdr.iOffBits + (length - row - 1) * size;
else
offset = file_hdr.iOffBits + row * size;
if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
TIFFError(infilename, TIFFError(infilename,
"scanline %lu: Seek error", "Wrong image parameters; can't "
(unsigned long) row); "allocate space for scanline buffer");
break; goto bad3;
} }
size = (size & ~31) / 8;
if (read(fd, scanbuf, size) < 0) { scanbuf = (char *) _TIFFmalloc(size);
if (!scanbuf) {
TIFFError(infilename, TIFFError(infilename,
"scanline %lu: Read error", "Can't allocate space for scanline buffer");
(unsigned long) row); goto bad3;
break; }
}
rearrangePixels(scanbuf, width, info_hdr.iBitCount); for (row = 0; row < length; row++) {
if (info_hdr.iHeight > 0)
offset = file_hdr.iOffBits+(length-row-1)*size;
else
offset = file_hdr.iOffBits + row * size;
if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
TIFFError(infilename,
"scanline %lu: Seek error",
(unsigned long) row);
break;
}
if (TIFFWriteScanline(out, scanbuf, row, 0) < 0) { if (read(fd, scanbuf, size) < 0) {
TIFFError(infilename, TIFFError(infilename,
"scanline %lu: Write error", "scanline %lu: Read error",
(unsigned long) row); (unsigned long) row);
break; break;
} }
}
_TIFFfree(scanbuf); rearrangePixels(scanbuf, width, info_hdr.iBitCount);
if (TIFFWriteScanline(out, scanbuf, row, 0)<0) {
TIFFError(infilename,
"scanline %lu: Write error",
(unsigned long) row);
break;
}
}
_TIFFfree(scanbuf);
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Read compressed image data. */ /* Read compressed image data. */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
} else if ( info_hdr.iCompression == BMPC_RLE8 } else if ( info_hdr.iCompression == BMPC_RLE8
|| info_hdr.iCompression == BMPC_RLE4 ) { || info_hdr.iCompression == BMPC_RLE4 ) {
uint32 i, j, k, runlength; uint32 i, j, k, runlength;
uint32 compr_size, uncompr_size; uint32 compr_size, uncompr_size;
unsigned char *comprbuf; unsigned char *comprbuf;
unsigned char *uncomprbuf; unsigned char *uncomprbuf;
compr_size = file_hdr.iSize - file_hdr.iOffBits; compr_size = file_hdr.iSize - file_hdr.iOffBits;
uncompr_size = width * length; uncompr_size = width * length;
comprbuf = (unsigned char *) _TIFFmalloc( compr_size ); comprbuf = (unsigned char *) _TIFFmalloc( compr_size );
if (!comprbuf) { if (!comprbuf) {
TIFFError(infilename,
"Can't allocate space for compressed scanline buffer");
goto bad3;
}
uncomprbuf = (unsigned char *) _TIFFmalloc( uncompr_size );
if (!uncomprbuf) {
TIFFError(infilename,
"Can't allocate space for uncompressed scanline buffer");
goto bad3;
}
lseek(fd, file_hdr.iOffBits, SEEK_SET);
read(fd, comprbuf, compr_size);
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) {
TIFFError(infilename, TIFFError(infilename,
"scanline %lu: Write error.\n", "Can't allocate space for compressed scanline buffer");
(unsigned long) row); goto bad3;
} }
} uncomprbuf = (unsigned char *)_TIFFmalloc(uncompr_size);
if (!uncomprbuf) {
TIFFError(infilename,
"Can't allocate space for uncompressed scanline buffer");
goto bad3;
}
_TIFFfree(uncomprbuf); lseek(fd, file_hdr.iOffBits, SEEK_SET);
read(fd, comprbuf, compr_size);
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) {
TIFFError(infilename,
"scanline %lu: Write error.\n",
(unsigned long) row);
}
}
_TIFFfree(uncomprbuf);
}
TIFFWriteDirectory(out);
if (blue_tbl) {
_TIFFfree(blue_tbl);
blue_tbl=NULL;
}
if (green_tbl) {
_TIFFfree(green_tbl);
green_tbl=NULL;
}
if (red_tbl) {
_TIFFfree(red_tbl);
red_tbl=NULL;
}
} }
bad3: bad3:
@ -776,7 +804,7 @@ processCompressOptions(char* opt)
static char* stuff[] = { static char* stuff[] = {
"bmp2tiff --- convert Windows BMP files to TIFF", "bmp2tiff --- convert Windows BMP files to TIFF",
"usage: bmp2tiff [options] input.bmp output.tif", "usage: bmp2tiff [options] input.bmp [input2.bmp ...] output.tif",
"where options are:", "where options are:",
" -r # make each strip have no more than # rows", " -r # make each strip have no more than # rows",
"", "",