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:
parent
0a9c358574
commit
39749b49af
@ -117,6 +117,7 @@ TiffDetails::~TiffDetails()
|
||||
{
|
||||
delete[] pstripOffsets;
|
||||
delete[] pstripByteCounts;
|
||||
delete[] pcolorMap;
|
||||
|
||||
memset(this, 0, sizeof(TiffDetails));
|
||||
}
|
||||
@ -415,10 +416,6 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
|
||||
compression = COMPRESSION_NONE;
|
||||
else
|
||||
compression = ifd.GetUint(TAG_COMPRESSION);
|
||||
if (compression != COMPRESSION_NONE &&
|
||||
compression != COMPRESSION_HUFFMAN &&
|
||||
compression != COMPRESSION_PACKBITS)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
uint16 imageType = 0, bitsPerPixel = 0;
|
||||
switch (interpretation) {
|
||||
@ -432,12 +429,22 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
|
||||
|
||||
// default value for bits per sample is 1
|
||||
if (!ifd.HasField(TAG_BITS_PER_SAMPLE) ||
|
||||
ifd.GetUint(TAG_BITS_PER_SAMPLE) == 1)
|
||||
ifd.GetUint(TAG_BITS_PER_SAMPLE) == 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);
|
||||
else
|
||||
|
||||
if (compression != COMPRESSION_NONE &&
|
||||
compression != COMPRESSION_PACKBITS)
|
||||
return B_NO_TRANSLATOR;
|
||||
} else
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
imageType = TIFF_BILEVEL;
|
||||
@ -446,32 +453,32 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
|
||||
|
||||
// Palette color images
|
||||
case PHOTO_PALETTE:
|
||||
if (compression != COMPRESSION_NONE &&
|
||||
compression != COMPRESSION_PACKBITS)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
// 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) &&
|
||||
ifd.GetUint(TAG_SAMPLES_PER_PIXEL) != 1)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
// bits per sample must be present and
|
||||
// can only be 4 or 8
|
||||
if (ifd.GetUint(TAG_BITS_PER_SAMPLE) != 4 &&
|
||||
ifd.GetUint(TAG_BITS_PER_SAMPLE) != 8)
|
||||
|
||||
bitsPerPixel = ifd.GetUint(TAG_BITS_PER_SAMPLE);
|
||||
if (bitsPerPixel != 4 && bitsPerPixel != 8)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
// even though other compression types are
|
||||
// supported for other TIFF types,
|
||||
// packbits and uncompressed are the only
|
||||
// compression types supported for palette
|
||||
// images
|
||||
if (compression != COMPRESSION_NONE &&
|
||||
compression != COMPRESSION_PACKBITS)
|
||||
|
||||
// ensure that the color map is the expected length
|
||||
if (ifd.GetCount(TAG_COLOR_MAP) !=
|
||||
(uint32) (3 * (1 << bitsPerPixel)))
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
imageType = TIFF_PALETTE;
|
||||
break;
|
||||
|
||||
case PHOTO_RGB:
|
||||
if (compression != COMPRESSION_NONE &&
|
||||
compression != COMPRESSION_PACKBITS)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
if (ifd.GetUint(TAG_SAMPLES_PER_PIXEL) != 3)
|
||||
return B_NO_TRANSLATOR;
|
||||
if (ifd.GetCount(TAG_BITS_PER_SAMPLE) != 3 ||
|
||||
@ -484,6 +491,10 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
|
||||
break;
|
||||
|
||||
case PHOTO_SEPARATED:
|
||||
if (compression != COMPRESSION_NONE &&
|
||||
compression != COMPRESSION_PACKBITS)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
// CMYK (default ink set)
|
||||
// is the only ink set supported
|
||||
if (ifd.HasField(TAG_INK_SET) &&
|
||||
@ -517,8 +528,8 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
|
||||
ifd.GetCount(TAG_STRIP_BYTE_COUNTS) != stripsPerImage)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
printf("width: %d\nheight: %d\ncompression: %d\ninterpretation: %d\n",
|
||||
width, height, compression, interpretation);
|
||||
printf("width: %d\nheight: %d\ncompression: %d\ninterpretation: %d\nbits per pixel: %d\n",
|
||||
width, height, compression, interpretation, bitsPerPixel);
|
||||
|
||||
// return read in details if output pointer is supplied
|
||||
if (pdetails) {
|
||||
@ -531,10 +542,13 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
|
||||
pdetails->bitsPerPixel = bitsPerPixel;
|
||||
pdetails->imageType = imageType;
|
||||
|
||||
ifd.GetUintArray(TAG_STRIP_OFFSETS,
|
||||
ifd.GetUint32Array(TAG_STRIP_OFFSETS,
|
||||
&pdetails->pstripOffsets);
|
||||
ifd.GetUintArray(TAG_STRIP_BYTE_COUNTS,
|
||||
ifd.GetUint32Array(TAG_STRIP_BYTE_COUNTS,
|
||||
&pdetails->pstripByteCounts);
|
||||
|
||||
if (pdetails->imageType == TIFF_PALETTE)
|
||||
ifd.GetAdjustedColorMap(&pdetails->pcolorMap);
|
||||
}
|
||||
|
||||
} catch (TiffIfdException) {
|
||||
@ -758,6 +772,38 @@ tiff_to_bits(uint8 *ptiff, uint32 tifflen, uint8 *pbits, TiffDetails &details)
|
||||
|
||||
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:
|
||||
while (ptiff < ptiffend) {
|
||||
pbits[2] = ptiff[0];
|
||||
@ -935,6 +981,7 @@ TIFFTranslator::translate_from_tiff(BPositionIO *inSource, ssize_t amtread,
|
||||
outbufferlen = 4 * details.width;
|
||||
switch (details.imageType) {
|
||||
case TIFF_BILEVEL:
|
||||
case TIFF_PALETTE:
|
||||
{
|
||||
uint32 pixelsPerByte = 8 / details.bitsPerPixel;
|
||||
inbufferlen = (details.width / pixelsPerByte) +
|
||||
|
@ -79,6 +79,7 @@ public:
|
||||
uint32 stripsPerImage;
|
||||
uint32 *pstripOffsets;
|
||||
uint32 *pstripByteCounts;
|
||||
uint8 *pcolorMap;
|
||||
uint16 interpretation;
|
||||
uint16 bitsPerPixel;
|
||||
uint16 imageType;
|
||||
|
@ -176,7 +176,43 @@ TiffIfd::GetUint(uint16 tag, uint32 index)
|
||||
}
|
||||
|
||||
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);
|
||||
if (pfield) {
|
||||
|
@ -78,7 +78,8 @@ public:
|
||||
// TiffIfdUnexpectedTypeException(),
|
||||
// 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
|
||||
// the pointer pointed to by pout
|
||||
// and returns the number of uints copied
|
||||
|
Loading…
x
Reference in New Issue
Block a user