16-bit-per-sample tiff files

This commit is contained in:
David Rose 2006-02-17 23:33:17 +00:00
parent 544e8dbc90
commit 995ce8b11a
3 changed files with 156 additions and 35 deletions

View File

@ -268,7 +268,8 @@ BMPwriterow(
unsigned long cx, unsigned long cx,
unsigned short bpp, unsigned short bpp,
int indexed, int indexed,
colorhash_table cht) colorhash_table cht,
xelval maxval)
{ {
BITSTREAM b; BITSTREAM b;
unsigned nbyte = 0; unsigned nbyte = 0;
@ -299,9 +300,9 @@ BMPwriterow(
for (x = 0; x < cx; x++, row++) for (x = 0; x < cx; x++, row++)
{ {
PutByte(fp, PPM_GETB(*row)); PutByte(fp, PPM_GETB(*row) * 255 / maxval);
PutByte(fp, PPM_GETG(*row)); PutByte(fp, PPM_GETG(*row) * 255 / maxval);
PutByte(fp, PPM_GETR(*row)); PutByte(fp, PPM_GETR(*row) * 255 / maxval);
nbyte += 3; nbyte += 3;
} }
} }
@ -329,7 +330,8 @@ BMPwritebits(
unsigned short cBitCount, unsigned short cBitCount,
pixel **pixels, pixel **pixels,
int indexed, int indexed,
colorhash_table cht) colorhash_table cht,
xelval maxval)
{ {
int nbyte = 0; int nbyte = 0;
long y; long y;
@ -347,7 +349,8 @@ BMPwritebits(
for (y = (long)cy - 1; y >= 0; y--) for (y = (long)cy - 1; y >= 0; y--)
{ {
int rc; int rc;
rc = BMPwriterow(fp, pixels[y], cx, cBitCount, indexed, cht); rc = BMPwriterow(fp, pixels[y], cx, cBitCount, indexed, cht,
maxval);
if(rc == -1) if(rc == -1)
{ {
@ -460,7 +463,7 @@ BMPEncode(
pm_error(er_internal, "BMPEncode"); pm_error(er_internal, "BMPEncode");
} }
nbyte += BMPwritebits(fp, x, y, bpp, pixels, true, cht); nbyte += BMPwritebits(fp, x, y, bpp, pixels, true, cht, 255);
if(nbyte != BMPlenfile(classv, bpp, x, y)) if(nbyte != BMPlenfile(classv, bpp, x, y))
{ {
pm_error(er_internal, "BMPEncode"); pm_error(er_internal, "BMPEncode");
@ -476,7 +479,8 @@ BMPEncode24(
int classv, int classv,
int x, int x,
int y, int y,
pixel **pixels) pixel **pixels,
xelval maxval)
{ {
unsigned long nbyte = 0; unsigned long nbyte = 0;
int bpp = 24; int bpp = 24;
@ -493,7 +497,8 @@ BMPEncode24(
pm_error(er_internal, "BMPEncode24"); pm_error(er_internal, "BMPEncode24");
} }
nbyte += BMPwritebits(fp, x, y, bpp, pixels, false, colorhash_table()); nbyte += BMPwritebits(fp, x, y, bpp, pixels, false, colorhash_table(),
maxval);
if(nbyte != BMPlenfile(classv, bpp, x, y)) if(nbyte != BMPlenfile(classv, bpp, x, y))
{ {
pm_error(er_internal, "BMPEncode24"); pm_error(er_internal, "BMPEncode24");
@ -582,7 +587,7 @@ write_data(xel *array, xelval *) {
chv = ppm_computecolorhist(pixels, _x_size, _y_size, MAXCOLORS, &colors); chv = ppm_computecolorhist(pixels, _x_size, _y_size, MAXCOLORS, &colors);
if (bmp_bpp > 8) { if (bmp_bpp > 8) {
// Quietly generate a 24-bit image. // Quietly generate a 24-bit image.
BMPEncode24(_file, classv, _x_size, _y_size, pixels); BMPEncode24(_file, classv, _x_size, _y_size, pixels, _maxval);
} else if (chv == (colorhist_vector) 0) { } else if (chv == (colorhist_vector) 0) {
if (bmp_bpp != 0) { if (bmp_bpp != 0) {
@ -591,7 +596,7 @@ write_data(xel *array, xelval *) {
<< "too many colors for " << bmp_bpp << "-bit image.\n"; << "too many colors for " << bmp_bpp << "-bit image.\n";
} }
BMPEncode24(_file, classv, _x_size, _y_size, pixels); BMPEncode24(_file, classv, _x_size, _y_size, pixels, _maxval);
} else { } else {
pnmimage_bmp_cat.debug() pnmimage_bmp_cat.debug()

View File

@ -582,17 +582,6 @@ supports_read_row() const {
return true; return true;
} }
#define NEXTSAMPLE \
{ \
if ( bitsleft == 0 ) \
{ \
++inP; \
bitsleft = 8; \
} \
bitsleft -= bps; \
sample = ( *inP >> bitsleft ) & _maxval; \
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTIFF::Reader::read_row // Function: PNMFileTypeTIFF::Reader::read_row
// Access: Public, Virtual // Access: Public, Virtual
@ -608,7 +597,9 @@ read_row(xel *row_data, xelval *alpha_data) {
return false; return false;
} }
unsigned char *buf = (unsigned char*) alloca((size_t)TIFFScanlineSize(tif)); size_t scanline_size = (size_t)TIFFScanlineSize(tif);
unsigned char *buf = (unsigned char*) alloca(scanline_size);
int col; int col;
xelval gray, sample; xelval gray, sample;
xelval r, g, b; xelval r, g, b;
@ -619,19 +610,42 @@ read_row(xel *row_data, xelval *alpha_data) {
return false; return false;
} }
unsigned char *inP = buf; unsigned char *buf_ptr = buf;
unsigned s; unsigned s;
int bitsleft = 8; int bits_left = 8;
// Get a pointer to a function that extracts the next bps-bit sample
// from the bitarray. There are a handful of different functions,
// which are optimized for different values of bps.
xelval (PNMFileTypeTIFF::Reader::*next_sample)(unsigned char *&buf_ptr, int &bits_left) const;
if (bps < 8) {
next_sample = &PNMFileTypeTIFF::Reader::next_sample_lt_8;
} else if (bps == 8) {
next_sample = &PNMFileTypeTIFF::Reader::next_sample_8;
} else if (bps == 16) {
next_sample = &PNMFileTypeTIFF::Reader::next_sample_16;
} else if (bps == 32) {
// Actually, it's not likely that a 32-bit sample will fit within
// a xelval. Deal with this when we come to it.
next_sample = &PNMFileTypeTIFF::Reader::next_sample_32;
} else {
next_sample = &PNMFileTypeTIFF::Reader::next_sample_general;
}
switch ( photomet ) { switch ( photomet ) {
case PHOTOMETRIC_MINISBLACK: case PHOTOMETRIC_MINISBLACK:
for ( col = 0; col < _x_size; ++col ) for ( col = 0; col < _x_size; ++col )
{ {
NEXTSAMPLE; sample = (this->*next_sample)(buf_ptr, bits_left);
gray = sample; gray = sample;
for (s = 1; s < spp; s++) { for (s = 1; s < spp; s++) {
NEXTSAMPLE; sample = (this->*next_sample)(buf_ptr, bits_left);
if (s == unassoc_alpha_sample) { if (s == unassoc_alpha_sample) {
alpha_data[col] = sample; alpha_data[col] = sample;
@ -649,10 +663,10 @@ read_row(xel *row_data, xelval *alpha_data) {
case PHOTOMETRIC_MINISWHITE: case PHOTOMETRIC_MINISWHITE:
for ( col = 0; col < _x_size; ++col ) for ( col = 0; col < _x_size; ++col )
{ {
NEXTSAMPLE; sample = (this->*next_sample)(buf_ptr, bits_left);
gray = _maxval - sample; gray = _maxval - sample;
for (s = 1; s < spp; s++) { for (s = 1; s < spp; s++) {
NEXTSAMPLE; sample = (this->*next_sample)(buf_ptr, bits_left);
sample = _maxval - sample; sample = _maxval - sample;
if (s == unassoc_alpha_sample) { if (s == unassoc_alpha_sample) {
@ -673,11 +687,11 @@ read_row(xel *row_data, xelval *alpha_data) {
case PHOTOMETRIC_PALETTE: case PHOTOMETRIC_PALETTE:
for ( col = 0; col < _x_size; ++col ) for ( col = 0; col < _x_size; ++col )
{ {
NEXTSAMPLE; sample = (this->*next_sample)(buf_ptr, bits_left);
row_data[col] = colormap[sample]; row_data[col] = colormap[sample];
for (s = 1; s < spp; s++) { for (s = 1; s < spp; s++) {
NEXTSAMPLE; sample = (this->*next_sample)(buf_ptr, bits_left);
if (s == unassoc_alpha_sample) { if (s == unassoc_alpha_sample) {
alpha_data[col] = sample; alpha_data[col] = sample;
@ -699,15 +713,15 @@ read_row(xel *row_data, xelval *alpha_data) {
case PHOTOMETRIC_RGB: case PHOTOMETRIC_RGB:
for ( col = 0; col < _x_size; ++col ) { for ( col = 0; col < _x_size; ++col ) {
NEXTSAMPLE; sample = (this->*next_sample)(buf_ptr, bits_left);
r = sample; r = sample;
NEXTSAMPLE; sample = (this->*next_sample)(buf_ptr, bits_left);
g = sample; g = sample;
NEXTSAMPLE; sample = (this->*next_sample)(buf_ptr, bits_left);
b = sample; b = sample;
for (s = 3; s < spp; s++) { for (s = 3; s < spp; s++) {
NEXTSAMPLE; sample = (this->*next_sample)(buf_ptr, bits_left);
if (s == unassoc_alpha_sample) { if (s == unassoc_alpha_sample) {
alpha_data[col] = sample; alpha_data[col] = sample;
@ -731,10 +745,106 @@ read_row(xel *row_data, xelval *alpha_data) {
return false; return false;
} }
nassertr(buf_ptr <= buf + scanline_size, false);
current_row++; current_row++;
return true; return true;
} }
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTIFF::Reader::next_sample_lt_8
// Access: Private
// Description: Returns the next color sample from the row, when it
// is known that bps < 8.
////////////////////////////////////////////////////////////////////
xelval PNMFileTypeTIFF::Reader::
next_sample_lt_8(unsigned char *&buf_ptr, int &bits_left) const {
if (bits_left == 0) {
++buf_ptr;
bits_left = 8;
}
bits_left -= bps;
return (*buf_ptr >> bits_left) & _maxval;
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTIFF::Reader::next_sample_8
// Access: Private
// Description: Returns the next color sample from the row, when it
// is known that bps == 8.
////////////////////////////////////////////////////////////////////
xelval PNMFileTypeTIFF::Reader::
next_sample_8(unsigned char *&buf_ptr, int &bits_left) const {
return *buf_ptr++;
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTIFF::Reader::next_sample_16
// Access: Private
// Description: Returns the next color sample from the row, when it
// is known that bps == 16.
////////////////////////////////////////////////////////////////////
xelval PNMFileTypeTIFF::Reader::
next_sample_16(unsigned char *&buf_ptr, int &bits_left) const {
// The TIFF library has already byte-swapped the values if
// necessary. Thus, we only need to treat it as an array of shorts.
unsigned short result = *(unsigned short *)buf_ptr;
buf_ptr += 2;
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTIFF::Reader::next_sample_32
// Access: Private
// Description: Returns the next color sample from the row, when it
// is known that bps == 32.
////////////////////////////////////////////////////////////////////
xelval PNMFileTypeTIFF::Reader::
next_sample_32(unsigned char *&buf_ptr, int &bits_left) const {
// The TIFF library has already byte-swapped the values if
// necessary. Thus, we only need to treat it as an array of longs.
unsigned long result = *(unsigned long *)buf_ptr;
buf_ptr += 2;
return (xelval)result;
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTIFF::Reader::next_sample_general
// Access: Private
// Description: Returns the next color sample from the row, in
// general. This unpacks an arbitrary string of bits
// from the sequence.
////////////////////////////////////////////////////////////////////
xelval PNMFileTypeTIFF::Reader::
next_sample_general(unsigned char *&buf_ptr, int &bits_left) const {
unsigned int result = 0;
int bits_needed = bps;
while (bits_needed > 0) {
nassertr(bits_left >= 0, 0);
if (bits_left == 0) {
++buf_ptr;
bits_left = 8;
}
if (bits_needed <= bits_left) {
bits_left -= bits_needed;
unsigned int mask = (1 << bits_needed) - 1;
result |= ((*buf_ptr) >> bits_left) & mask;
bits_needed = 0;
} else {
bits_needed -= bits_left;
unsigned int mask = (1 << bits_left) - 1;
result |= ((*buf_ptr) & mask) << bits_needed;
bits_left = 0;
}
}
return result;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTIFF::Writer::Constructor // Function: PNMFileTypeTIFF::Writer::Constructor

View File

@ -63,6 +63,12 @@ public:
virtual bool read_row(xel *array, xelval *alpha); virtual bool read_row(xel *array, xelval *alpha);
private: private:
xelval next_sample_lt_8(unsigned char *&buf_ptr, int &bits_left) const;
xelval next_sample_8(unsigned char *&buf_ptr, int &bits_left) const;
xelval next_sample_16(unsigned char *&buf_ptr, int &bits_left) const;
xelval next_sample_32(unsigned char *&buf_ptr, int &bits_left) const;
xelval next_sample_general(unsigned char *&buf_ptr, int &bits_left) const;
unsigned short photomet; unsigned short photomet;
unsigned short bps, spp; unsigned short bps, spp;
unsigned short unassoc_alpha_sample, assoc_alpha_sample; unsigned short unassoc_alpha_sample, assoc_alpha_sample;