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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user