added support for reading uncompressed, packbits encoded, 4, 8-bit palette based TIFF images

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3099 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Matthew Wilber
2003-04-23 03:11:05 +00:00
parent 0a9c358574
commit 39749b49af
4 changed files with 114 additions and 29 deletions
@@ -117,6 +117,7 @@ TiffDetails::~TiffDetails()
{ {
delete[] pstripOffsets; delete[] pstripOffsets;
delete[] pstripByteCounts; delete[] pstripByteCounts;
delete[] pcolorMap;
memset(this, 0, sizeof(TiffDetails)); memset(this, 0, sizeof(TiffDetails));
} }
@@ -415,10 +416,6 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
compression = COMPRESSION_NONE; compression = COMPRESSION_NONE;
else else
compression = ifd.GetUint(TAG_COMPRESSION); compression = ifd.GetUint(TAG_COMPRESSION);
if (compression != COMPRESSION_NONE &&
compression != COMPRESSION_HUFFMAN &&
compression != COMPRESSION_PACKBITS)
return B_NO_TRANSLATOR;
uint16 imageType = 0, bitsPerPixel = 0; uint16 imageType = 0, bitsPerPixel = 0;
switch (interpretation) { switch (interpretation) {
@@ -432,12 +429,22 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
// default value for bits per sample is 1 // default value for bits per sample is 1
if (!ifd.HasField(TAG_BITS_PER_SAMPLE) || if (!ifd.HasField(TAG_BITS_PER_SAMPLE) ||
ifd.GetUint(TAG_BITS_PER_SAMPLE) == 1) ifd.GetUint(TAG_BITS_PER_SAMPLE) == 1) {
bitsPerPixel = 1; bitsPerPixel = 1;
else if (ifd.GetUint(TAG_BITS_PER_SAMPLE) == 4 ||
ifd.GetUint(TAG_BITS_PER_SAMPLE) == 8) if (compression != COMPRESSION_NONE &&
compression != COMPRESSION_HUFFMAN &&
compression != COMPRESSION_PACKBITS)
return B_NO_TRANSLATOR;
} else if (ifd.GetUint(TAG_BITS_PER_SAMPLE) == 4 ||
ifd.GetUint(TAG_BITS_PER_SAMPLE) == 8) {
bitsPerPixel = ifd.GetUint(TAG_BITS_PER_SAMPLE); bitsPerPixel = ifd.GetUint(TAG_BITS_PER_SAMPLE);
else
if (compression != COMPRESSION_NONE &&
compression != COMPRESSION_PACKBITS)
return B_NO_TRANSLATOR;
} else
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
imageType = TIFF_BILEVEL; imageType = TIFF_BILEVEL;
@@ -446,32 +453,32 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
// Palette color images // Palette color images
case PHOTO_PALETTE: case PHOTO_PALETTE:
if (compression != COMPRESSION_NONE &&
compression != COMPRESSION_PACKBITS)
return B_NO_TRANSLATOR;
// default value for samples per pixel is 1 // default value for samples per pixel is 1
// if samples per pixel is other than 1,
// it is not valid for this image type
if (ifd.HasField(TAG_SAMPLES_PER_PIXEL) && if (ifd.HasField(TAG_SAMPLES_PER_PIXEL) &&
ifd.GetUint(TAG_SAMPLES_PER_PIXEL) != 1) ifd.GetUint(TAG_SAMPLES_PER_PIXEL) != 1)
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
// bits per sample must be present and bitsPerPixel = ifd.GetUint(TAG_BITS_PER_SAMPLE);
// can only be 4 or 8 if (bitsPerPixel != 4 && bitsPerPixel != 8)
if (ifd.GetUint(TAG_BITS_PER_SAMPLE) != 4 &&
ifd.GetUint(TAG_BITS_PER_SAMPLE) != 8)
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
// even though other compression types are // ensure that the color map is the expected length
// supported for other TIFF types, if (ifd.GetCount(TAG_COLOR_MAP) !=
// packbits and uncompressed are the only (uint32) (3 * (1 << bitsPerPixel)))
// compression types supported for palette
// images
if (compression != COMPRESSION_NONE &&
compression != COMPRESSION_PACKBITS)
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
imageType = TIFF_PALETTE; imageType = TIFF_PALETTE;
break; break;
case PHOTO_RGB: case PHOTO_RGB:
if (compression != COMPRESSION_NONE &&
compression != COMPRESSION_PACKBITS)
return B_NO_TRANSLATOR;
if (ifd.GetUint(TAG_SAMPLES_PER_PIXEL) != 3) if (ifd.GetUint(TAG_SAMPLES_PER_PIXEL) != 3)
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
if (ifd.GetCount(TAG_BITS_PER_SAMPLE) != 3 || if (ifd.GetCount(TAG_BITS_PER_SAMPLE) != 3 ||
@@ -484,6 +491,10 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
break; break;
case PHOTO_SEPARATED: case PHOTO_SEPARATED:
if (compression != COMPRESSION_NONE &&
compression != COMPRESSION_PACKBITS)
return B_NO_TRANSLATOR;
// CMYK (default ink set) // CMYK (default ink set)
// is the only ink set supported // is the only ink set supported
if (ifd.HasField(TAG_INK_SET) && if (ifd.HasField(TAG_INK_SET) &&
@@ -517,8 +528,8 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
ifd.GetCount(TAG_STRIP_BYTE_COUNTS) != stripsPerImage) ifd.GetCount(TAG_STRIP_BYTE_COUNTS) != stripsPerImage)
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
printf("width: %d\nheight: %d\ncompression: %d\ninterpretation: %d\n", printf("width: %d\nheight: %d\ncompression: %d\ninterpretation: %d\nbits per pixel: %d\n",
width, height, compression, interpretation); width, height, compression, interpretation, bitsPerPixel);
// return read in details if output pointer is supplied // return read in details if output pointer is supplied
if (pdetails) { if (pdetails) {
@@ -531,10 +542,13 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
pdetails->bitsPerPixel = bitsPerPixel; pdetails->bitsPerPixel = bitsPerPixel;
pdetails->imageType = imageType; pdetails->imageType = imageType;
ifd.GetUintArray(TAG_STRIP_OFFSETS, ifd.GetUint32Array(TAG_STRIP_OFFSETS,
&pdetails->pstripOffsets); &pdetails->pstripOffsets);
ifd.GetUintArray(TAG_STRIP_BYTE_COUNTS, ifd.GetUint32Array(TAG_STRIP_BYTE_COUNTS,
&pdetails->pstripByteCounts); &pdetails->pstripByteCounts);
if (pdetails->imageType == TIFF_PALETTE)
ifd.GetAdjustedColorMap(&pdetails->pcolorMap);
} }
} catch (TiffIfdException) { } catch (TiffIfdException) {
@@ -758,6 +772,38 @@ tiff_to_bits(uint8 *ptiff, uint32 tifflen, uint8 *pbits, TiffDetails &details)
break; break;
case TIFF_PALETTE:
{
// NOTE: All of the entries in the color map were
// divided by 256 before they were copied to pcolorMap.
//
// The first 3rd of the color map is made of the Red values,
// the second 3rd of the color map is made of the Green values,
// and the last 3rd of the color map is made of the Blue values.
if (details.bitsPerPixel == 8) {
for (uint32 i = 0; i < details.width; i++) {
pbits[2] = details.pcolorMap[ptiff[i]];
pbits[1] = details.pcolorMap[256 + ptiff[i]];
pbits[0] = details.pcolorMap[512 + ptiff[i]];
pbits += 4;
}
} else if (details.bitsPerPixel == 4) {
const uint8 mask = 0x0f;
for (uint32 i = 0; i < details.width; i++) {
uint8 indices = (ptiff + (i / 2))[0];
uint8 index = (indices >> (4 * (1 - (i % 2)))) & mask;
pbits[2] = details.pcolorMap[index];
pbits[1] = details.pcolorMap[16 + index];
pbits[0] = details.pcolorMap[32 + index];
pbits += 4;
}
}
break;
}
case TIFF_RGB: case TIFF_RGB:
while (ptiff < ptiffend) { while (ptiff < ptiffend) {
pbits[2] = ptiff[0]; pbits[2] = ptiff[0];
@@ -935,6 +981,7 @@ TIFFTranslator::translate_from_tiff(BPositionIO *inSource, ssize_t amtread,
outbufferlen = 4 * details.width; outbufferlen = 4 * details.width;
switch (details.imageType) { switch (details.imageType) {
case TIFF_BILEVEL: case TIFF_BILEVEL:
case TIFF_PALETTE:
{ {
uint32 pixelsPerByte = 8 / details.bitsPerPixel; uint32 pixelsPerByte = 8 / details.bitsPerPixel;
inbufferlen = (details.width / pixelsPerByte) + inbufferlen = (details.width / pixelsPerByte) +
@@ -79,6 +79,7 @@ public:
uint32 stripsPerImage; uint32 stripsPerImage;
uint32 *pstripOffsets; uint32 *pstripOffsets;
uint32 *pstripByteCounts; uint32 *pstripByteCounts;
uint8 *pcolorMap;
uint16 interpretation; uint16 interpretation;
uint16 bitsPerPixel; uint16 bitsPerPixel;
uint16 imageType; uint16 imageType;
@@ -176,7 +176,43 @@ TiffIfd::GetUint(uint16 tag, uint32 index)
} }
uint32 uint32
TiffIfd::GetUintArray(uint16 tag, uint32 **pout) TiffIfd::GetAdjustedColorMap(uint8 **pout)
{
TiffField *pfield = GetField(TAG_COLOR_MAP);
if (pfield) {
TiffUintField *puintField = NULL;
puintField = dynamic_cast<TiffUintField *>(pfield);
if (puintField) {
uint32 count = puintField->GetCount();
(*pout) = new uint8[count];
uint8 *puints = (*pout);
if (!puints)
throw TiffIfdNoMemoryException();
for (uint32 i = 0; i < count; i++) {
uint32 num;
status_t ret = puintField->GetUint(num, i + 1);
if (ret == B_BAD_INDEX)
throw TiffIfdBadIndexException();
else if (ret == B_BAD_TYPE)
throw TiffIfdUnexpectedTypeException();
puints[i] = num / 256;
}
return count;
} else
throw TiffIfdUnexpectedTypeException();
}
throw TiffIfdFieldNotFoundException();
}
uint32
TiffIfd::GetUint32Array(uint16 tag, uint32 **pout)
{ {
TiffField *pfield = GetField(tag); TiffField *pfield = GetField(tag);
if (pfield) { if (pfield) {
@@ -78,7 +78,8 @@ public:
// TiffIfdUnexpectedTypeException(), // TiffIfdUnexpectedTypeException(),
// TiffIfdBadIndexException() // TiffIfdBadIndexException()
uint32 GetUintArray(uint16 tag, uint32 **pout); uint32 GetAdjustedColorMap(uint8 **pout);
uint32 GetUint32Array(uint16 tag, uint32 **pout);
// copies all of the uints from tag to // copies all of the uints from tag to
// the pointer pointed to by pout // the pointer pointed to by pout
// and returns the number of uints copied // and returns the number of uints copied