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

View File

@ -582,17 +582,6 @@ supports_read_row() const {
return true;
}
#define NEXTSAMPLE \
{ \
if ( bitsleft == 0 ) \
{ \
++inP; \
bitsleft = 8; \
} \
bitsleft -= bps; \
sample = ( *inP >> bitsleft ) & _maxval; \
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTIFF::Reader::read_row
// Access: Public, Virtual
@ -608,7 +597,9 @@ read_row(xel *row_data, xelval *alpha_data) {
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;
xelval gray, sample;
xelval r, g, b;
@ -619,19 +610,42 @@ read_row(xel *row_data, xelval *alpha_data) {
return false;
}
unsigned char *inP = buf;
unsigned char *buf_ptr = buf;
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 ) {
case PHOTOMETRIC_MINISBLACK:
for ( col = 0; col < _x_size; ++col )
{
NEXTSAMPLE;
sample = (this->*next_sample)(buf_ptr, bits_left);
gray = sample;
for (s = 1; s < spp; s++) {
NEXTSAMPLE;
sample = (this->*next_sample)(buf_ptr, bits_left);
if (s == unassoc_alpha_sample) {
alpha_data[col] = sample;
@ -649,10 +663,10 @@ read_row(xel *row_data, xelval *alpha_data) {
case PHOTOMETRIC_MINISWHITE:
for ( col = 0; col < _x_size; ++col )
{
NEXTSAMPLE;
sample = (this->*next_sample)(buf_ptr, bits_left);
gray = _maxval - sample;
for (s = 1; s < spp; s++) {
NEXTSAMPLE;
sample = (this->*next_sample)(buf_ptr, bits_left);
sample = _maxval - sample;
if (s == unassoc_alpha_sample) {
@ -673,11 +687,11 @@ read_row(xel *row_data, xelval *alpha_data) {
case PHOTOMETRIC_PALETTE:
for ( col = 0; col < _x_size; ++col )
{
NEXTSAMPLE;
sample = (this->*next_sample)(buf_ptr, bits_left);
row_data[col] = colormap[sample];
for (s = 1; s < spp; s++) {
NEXTSAMPLE;
sample = (this->*next_sample)(buf_ptr, bits_left);
if (s == unassoc_alpha_sample) {
alpha_data[col] = sample;
@ -699,15 +713,15 @@ read_row(xel *row_data, xelval *alpha_data) {
case PHOTOMETRIC_RGB:
for ( col = 0; col < _x_size; ++col ) {
NEXTSAMPLE;
sample = (this->*next_sample)(buf_ptr, bits_left);
r = sample;
NEXTSAMPLE;
sample = (this->*next_sample)(buf_ptr, bits_left);
g = sample;
NEXTSAMPLE;
sample = (this->*next_sample)(buf_ptr, bits_left);
b = sample;
for (s = 3; s < spp; s++) {
NEXTSAMPLE;
sample = (this->*next_sample)(buf_ptr, bits_left);
if (s == unassoc_alpha_sample) {
alpha_data[col] = sample;
@ -731,10 +745,106 @@ read_row(xel *row_data, xelval *alpha_data) {
return false;
}
nassertr(buf_ptr <= buf + scanline_size, false);
current_row++;
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

View File

@ -63,6 +63,12 @@ public:
virtual bool read_row(xel *array, xelval *alpha);
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 bps, spp;
unsigned short unassoc_alpha_sample, assoc_alpha_sample;