diff --git a/src/add-ons/translators/tifftranslator/Jamfile b/src/add-ons/translators/tifftranslator/Jamfile index 6ba8bb9338..0ca619c60e 100755 --- a/src/add-ons/translators/tifftranslator/Jamfile +++ b/src/add-ons/translators/tifftranslator/Jamfile @@ -1,6 +1,7 @@ SubDir OBOS_TOP src add-ons translators tifftranslator ; Translator TIFFTranslator : + StreamBuffer.cpp TiffField.cpp TiffUintField.cpp TiffUnknownField.cpp diff --git a/src/add-ons/translators/tifftranslator/StreamBuffer.cpp b/src/add-ons/translators/tifftranslator/StreamBuffer.cpp new file mode 100755 index 0000000000..178b512ba7 --- /dev/null +++ b/src/add-ons/translators/tifftranslator/StreamBuffer.cpp @@ -0,0 +1,223 @@ +/*****************************************************************************/ +// StreamBuffer +// Written by Michael Wilber, OBOS Translation Kit Team +// +// StreamBuffer.cpp +// +// This class is for buffering data from a BPositionIO object in order to +// improve performance for cases when small amounts of data are frequently +// read from a BPositionIO object. +// +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#include +#include +#include "StreamBuffer.h" + +#define min(x,y) (((x) < (y)) ? (x) : (y)) +#define max(x,y) (((x) > (y)) ? (x) : (y)) + +// --------------------------------------------------------------- +// Constructor +// +// Initializes the StreamBuffer to read from pstream, buffering +// nbuffersize bytes of data at a time. Note that if nbuffersize +// is smaller than MIN_BUFFER_SIZE, MIN_BUFFER_SIZE is used +// as the buffer size. +// +// Preconditions: +// +// Parameters: pstream, the stream to be buffered +// +// nbuffersize, number of bytes to be read from +// pstream at a time +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +StreamBuffer::StreamBuffer(BPositionIO *pstream, size_t nbuffersize, + bool binitialread) +{ + fpStream = pstream; + fpBuffer = NULL; + fnBufferSize = 0; + fnLen = 0; + fnPos = 0; + + if (!pstream) + return; + + fnBufferSize = max(nbuffersize, MIN_BUFFER_SIZE); + fpBuffer = new uint8[fnBufferSize]; + if (fpBuffer && binitialread) + ReadStream(); + // Fill the buffer with data so that + // object is prepared for first call to + // Read() +} + +// --------------------------------------------------------------- +// Destructor +// +// Destroys data allocated for this object +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +StreamBuffer::~StreamBuffer() +{ + fnBufferSize = 0; + fnLen = 0; + fnPos = 0; + fpStream = NULL; + + delete[] fpBuffer; + fpBuffer = NULL; +} + +// --------------------------------------------------------------- +// InitCheck +// +// Determines whether the constructor failed or not +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: B_OK if object has been initialized successfully, +// B_ERROR if not +// --------------------------------------------------------------- +status_t StreamBuffer::InitCheck() +{ + if (fpStream && fpBuffer) + return B_OK; + else + return B_ERROR; +} + +// --------------------------------------------------------------- +// Read +// +// Copies up to nbytes of data from the stream into pinto +// +// Preconditions: ReadStream() must be called once before this +// function is called (the constructor does this) +// +// Parameters: pinto, the buffer to be copied to +// +// nbytes, the maximum number of bytes to copy +// +// Postconditions: +// +// Returns: the number of bytes successfully read or an +// error code returned by BPositionIO::Read() +// --------------------------------------------------------------- +ssize_t StreamBuffer::Read(uint8 *pinto, size_t nbytes) +{ + ssize_t result = B_ERROR; + size_t rd1 = 0, rd2 = 0; + + rd1 = min(nbytes, fnLen - fnPos); + memcpy(pinto, fpBuffer + fnPos, rd1); + fnPos += rd1; + + if (rd1 < nbytes) { + pinto += rd1; + result = ReadStream(); + if (result > 0) { + rd2 = min(nbytes - rd1, fnLen); + memcpy(pinto, fpBuffer, rd2); + fnPos += rd2; + } else + // return error code or zero + return result; + } + + return rd1 + rd2; +} + +// --------------------------------------------------------------- +// Seek +// +// Seeks the stream to the given position and refreshes the +// read buffer. If the seek operation fails, the read buffer +// will be reset. +// +// Preconditions: fpBuffer must be allocated and fnBufferSize +// must be valid +// +// Parameters: +// +// Postconditions: +// +// Returns: true if the seek was successful, +// false if the seek operation failed +// --------------------------------------------------------------- +bool StreamBuffer::Seek(off_t position) +{ + fnLen = 0; + fnPos = 0; + + if (fpStream->Seek(position, SEEK_SET) == position) { + ReadStream(); + return true; + } + + return false; +} + +// --------------------------------------------------------------- +// ReadStream +// +// Fills the stream buffer with data read in from the stream +// +// Preconditions: fpBuffer must be allocated and fnBufferSize +// must be valid +// +// Parameters: +// +// Postconditions: +// +// Returns: the number of bytes successfully read or an +// error code returned by BPositionIO::Read() +// --------------------------------------------------------------- +ssize_t StreamBuffer::ReadStream() +{ + ssize_t rd; + rd = fpStream->Read(fpBuffer, fnBufferSize); + if (rd >= 0) { + fnLen = rd; + fnPos = 0; + } + return rd; +} + + diff --git a/src/add-ons/translators/tifftranslator/StreamBuffer.h b/src/add-ons/translators/tifftranslator/StreamBuffer.h new file mode 100755 index 0000000000..c31b526b06 --- /dev/null +++ b/src/add-ons/translators/tifftranslator/StreamBuffer.h @@ -0,0 +1,70 @@ +/*****************************************************************************/ +// StreamBuffer +// Written by Michael Wilber, OBOS Translation Kit Team +// +// StreamBuffer.h +// +// This class is for buffering data from a BPositionIO object in order to +// improve performance for cases when small amounts of data are frequently +// read from a BPositionIO object. +// +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#ifndef STREAM_BUFFER_H +#define STREAM_BUFFER_H + +#include + +#define MIN_BUFFER_SIZE 512 + +class StreamBuffer { +public: + StreamBuffer(BPositionIO *pstream, size_t nbuffersize, bool binitialread); + ~StreamBuffer(); + + status_t InitCheck(); + // Determines whether the constructor failed or not + + ssize_t Read(uint8 *pinto, size_t nbytes); + // copy nbytes from the stream into pinto + + bool Seek(off_t position); + // seek the stream to the given position + +private: + ssize_t ReadStream(); + // Load the stream buffer from the stream + + BPositionIO *fpStream; + // stream object this object is buffering + uint8 *fpBuffer; + // buffered data from fpStream + size_t fnBufferSize; + // number of bytes of memory allocated for fpBuffer + size_t fnLen; + // number of bytes of actual data in fpBuffer + size_t fnPos; + // current position in the buffer +}; + +#endif \ No newline at end of file diff --git a/src/add-ons/translators/tifftranslator/TIFFTranslator.cpp b/src/add-ons/translators/tifftranslator/TIFFTranslator.cpp index 1e6fe0b50b..f88a7c592e 100755 --- a/src/add-ons/translators/tifftranslator/TIFFTranslator.cpp +++ b/src/add-ons/translators/tifftranslator/TIFFTranslator.cpp @@ -34,6 +34,7 @@ #include "TIFFTranslator.h" #include "TIFFView.h" #include "TiffIfd.h" +#include "StreamBuffer.h" // The input formats that this translator supports. translation_format gInputFormats[] = { @@ -341,7 +342,7 @@ identify_bits_header(BPositionIO *inSource, translator_info *outInfo, outInfo->group = B_TRANSLATOR_BITMAP; outInfo->quality = BBT_IN_QUALITY; outInfo->capability = BBT_IN_CAPABILITY; - strcpy(outInfo->name, "Be Bitmap Format (TGATranslator)"); + strcpy(outInfo->name, "Be Bitmap Format (TIFFTranslator)"); strcpy(outInfo->MIME, "image/x-be-bitmap"); } @@ -362,10 +363,14 @@ identify_bits_header(BPositionIO *inSource, translator_info *outInfo, status_t check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails) { - TiffDetails details; - memset(&details, 0, sizeof(TiffDetails)); + TiffDetails dtls; + memset(&dtls, 0, sizeof(TiffDetails)); - try { + try { + // Extra Samples are not yet supported + if (ifd.HasField(TAG_EXTRA_SAMPLES)) + return B_NO_TRANSLATOR; + // Only the default values are supported for the // following fields. HasField is called so that // if a field is not present, a TiffIfdFieldNotFoundException @@ -387,29 +392,82 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails) return B_NO_TRANSLATOR; // Copy fields useful to TIFFTranslator - details.width = ifd.GetUint(TAG_IMAGE_WIDTH); - details.height = ifd.GetUint(TAG_IMAGE_HEIGHT); - details.compression = ifd.GetUint(TAG_COMPRESSION); - details.interpretation = ifd.GetUint(TAG_PHOTO_INTERPRETATION); + dtls.width = ifd.GetUint(TAG_IMAGE_WIDTH); + dtls.height = ifd.GetUint(TAG_IMAGE_HEIGHT); + dtls.compression = ifd.GetUint(TAG_COMPRESSION); + dtls.interpretation = ifd.GetUint(TAG_PHOTO_INTERPRETATION); + + if (dtls.compression != COMPRESSION_NONE && + dtls.compression != COMPRESSION_PACKBITS) + return B_NO_TRANSLATOR; + + // Currently, only uncompressed + // RGB or CMYK images are supported + if (dtls.interpretation == PHOTO_RGB) { + if (ifd.GetUint(TAG_SAMPLES_PER_PIXEL) != 3) + return B_NO_TRANSLATOR; + if (ifd.GetCount(TAG_BITS_PER_SAMPLE) != 3 || + ifd.GetUint(TAG_BITS_PER_SAMPLE, 1) != 8 || + ifd.GetUint(TAG_BITS_PER_SAMPLE, 2) != 8 || + ifd.GetUint(TAG_BITS_PER_SAMPLE, 3) != 8) + return B_NO_TRANSLATOR; + + dtls.imageType = TIFF_RGB; + + } else if (dtls.interpretation == PHOTO_SEPARATED) { + // CMYK (default ink set) + // is the only ink set supported + if (ifd.HasField(TAG_INK_SET) && + ifd.GetUint(TAG_INK_SET) != INK_SET_CMYK) + return B_NO_TRANSLATOR; + + if (ifd.GetUint(TAG_SAMPLES_PER_PIXEL) != 4) + return B_NO_TRANSLATOR; + if (ifd.GetCount(TAG_BITS_PER_SAMPLE) != 4 || + ifd.GetUint(TAG_BITS_PER_SAMPLE, 1) != 8 || + ifd.GetUint(TAG_BITS_PER_SAMPLE, 2) != 8 || + ifd.GetUint(TAG_BITS_PER_SAMPLE, 3) != 8 || + ifd.GetUint(TAG_BITS_PER_SAMPLE, 4) != 8) + return B_NO_TRANSLATOR; + + dtls.imageType = TIFF_CMYK; + + } else + return B_NO_TRANSLATOR; + + if (!ifd.HasField(TAG_ROWS_PER_STRIP)) + dtls.rowsPerStrip = DEFAULT_ROWS_PER_STRIP; + else + dtls.rowsPerStrip = ifd.GetUint(TAG_ROWS_PER_STRIP); + dtls.stripsPerImage = + (dtls.height + dtls.rowsPerStrip - 1) / dtls.rowsPerStrip; + + if (ifd.GetCount(TAG_STRIP_OFFSETS) != dtls.stripsPerImage || + ifd.GetCount(TAG_STRIP_BYTE_COUNTS) != dtls.stripsPerImage) + return B_NO_TRANSLATOR; printf("width: %d\nheight: %d\ncompression: %d\ninterpretation: %d\n", - details.width, details.height, details.compression, - details.interpretation); - - // Currently, only uncompressed, non-tile RGB - // images are supported - if (details.compression != COMPRESSION_NONE) - return B_NO_TRANSLATOR; - if (details.interpretation != PHOTO_RGB) - return B_NO_TRANSLATOR; + dtls.width, dtls.height, dtls.compression, + dtls.interpretation); // return read in details if output // pointer is supplied - if (pdetails) - memcpy(pdetails, &details, sizeof(TiffDetails)); + if (pdetails) { + ifd.GetUintArray(TAG_STRIP_OFFSETS, &dtls.pstripOffsets); + ifd.GetUintArray(TAG_STRIP_BYTE_COUNTS, &dtls.pstripByteCounts); + + memcpy(pdetails, &dtls, sizeof(TiffDetails)); + } } catch (TiffIfdException) { + printf("-- Caught TiffIfdException --\n"); + + delete[] dtls.pstripOffsets; + dtls.pstripOffsets = NULL; + delete[] dtls.pstripByteCounts; + dtls.pstripByteCounts = NULL; + return B_NO_TRANSLATOR; } @@ -445,14 +503,24 @@ identify_tiff_header(BPositionIO *inSource, translator_info *outInfo, // this particular TIFF image is supported by this translator // Check the required fields - if (initcheck == B_OK) - return check_tiff_fields(ifd, pdetails); + if (initcheck == B_OK) { + if (outInfo) { + outInfo->type = B_TIFF_FORMAT; + outInfo->group = B_TRANSLATOR_BITMAP; + outInfo->quality = TIFF_IN_QUALITY; + outInfo->capability = TIFF_IN_CAPABILITY; + strcpy(outInfo->MIME, "image/tiff"); + strcpy(outInfo->name, "TIFF Image"); + } - if (initcheck != B_OK && initcheck != B_ERROR && initcheck != B_NO_MEMORY) + return check_tiff_fields(ifd, pdetails); + } + + if (initcheck != B_ERROR && initcheck != B_NO_MEMORY) // return B_NO_TRANSLATOR if unexpected data was encountered return B_NO_TRANSLATOR; else - // return B_OK, B_ERROR or B_NO_MEMORY + // return B_ERROR or B_NO_MEMORY return initcheck; } @@ -516,7 +584,6 @@ TIFFTranslator::Identify(BPositionIO *inSource, // Read in the magic number and determine if it // is a supported type uint8 ch[4]; - inSource->Seek(0, SEEK_SET); if (inSource->Read(ch, 4) != 4) return B_NO_TRANSLATOR; @@ -565,6 +632,216 @@ TIFFTranslator::Identify(BPositionIO *inSource, } } +void +tiff_to_bits(uint8 *ptiff, uint32 tifflen, uint8 *pbits, uint16 type) +{ + uint8 *ptiffend = ptiff + tifflen; + + switch (type) { + case TIFF_RGB: + while (ptiff < ptiffend) { + pbits[2] = ptiff[0]; + pbits[1] = ptiff[1]; + pbits[0] = ptiff[2]; + + ptiff += 3; + pbits += 4; + } + break; + + case TIFF_CMYK: + { + while (ptiff < ptiffend) { + int32 comp; + comp = 255 - ptiff[0] - ptiff[3]; + pbits[2] = (comp < 0) ? 0 : comp; + + comp = 255 - ptiff[1] - ptiff[3]; + pbits[1] = (comp < 0) ? 0 : comp; + + comp = 255 - ptiff[2] - ptiff[3]; + pbits[0] = (comp < 0) ? 0 : comp; + + ptiff += 4; + pbits += 4; + } + break; + } + } +} + +// unpack the Packbits compressed data from +// pstreambuf and put it into tiffbuffer +ssize_t +unpack(StreamBuffer *pstreambuf, uint8 *tiffbuffer, uint32 tiffbufferlen) +{ + uint32 tiffwrit = 0, read = 0, len; + while (tiffwrit < tiffbufferlen) { + + uint8 uctrl; + if (pstreambuf->Read(&uctrl, 1) != 1) + return B_ERROR; + read++; + + int32 control; + control = static_cast(uctrl); + + // copy control + 1 bytes literally + if (control >= 0 && control <= 127) { + + len = control + 1; + if (tiffwrit + len > tiffbufferlen) + return B_ERROR; + if (pstreambuf->Read(tiffbuffer + tiffwrit, len) != + static_cast(len)) + return B_ERROR; + read += len; + + tiffwrit += len; + + // copy the next byte (-control) + 1 times + } else if (control >= -127 && control <= -1) { + + uint8 byt; + if (pstreambuf->Read(&byt, 1) != 1) + return B_ERROR; + read++; + + len = (-control) + 1; + if (tiffwrit + len > tiffbufferlen) + return B_ERROR; + memset(tiffbuffer + tiffwrit, byt, len); + + tiffwrit += len; + } + } + + return read; +} + +status_t +translate_from_tiff(BPositionIO *inSource, ssize_t amtread, uint8 *read, + swap_action swp, uint32 outType, BPositionIO *outDestination) +{ + // Can only output to bits for now + if (outType != B_TRANSLATOR_BITMAP) + return B_NO_TRANSLATOR; + + status_t result; + + TiffDetails details; + result = identify_tiff_header(inSource, NULL, + amtread, read, swp, &details); + if (result == B_OK) { + // If the TIFF is supported by this translator + + TranslatorBitmap bitsHeader; + bitsHeader.magic = B_TRANSLATOR_BITMAP; + bitsHeader.bounds.left = 0; + bitsHeader.bounds.top = 0; + bitsHeader.bounds.right = details.width - 1; + bitsHeader.bounds.bottom = details.height - 1; + bitsHeader.rowBytes = 4 * details.width; + bitsHeader.colors = B_RGB32; + bitsHeader.dataSize = bitsHeader.rowBytes * details.height; + + // write out Be's Bitmap header + if (swap_data(B_UINT32_TYPE, &bitsHeader, + sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK) + return B_ERROR; + outDestination->Write(&bitsHeader, sizeof(TranslatorBitmap)); + + uint32 inbufferlen, outbufferlen; + outbufferlen = 4 * details.width; + switch (details.imageType) { + case TIFF_RGB: + inbufferlen = 3 * details.width; + break; + + case TIFF_CMYK: + inbufferlen = 4 * details.width; + break; + + default: + // just to be safe + return B_NO_TRANSLATOR; + } + + uint8 *inbuffer = new uint8[inbufferlen], + *outbuffer = new uint8[outbufferlen]; + if (!inbuffer || !outbuffer) + return B_NO_MEMORY; + // set all channels to 0xff so that I won't have + // to set the alpha byte to 0xff every time + memset(outbuffer, 0xff, outbufferlen); + + // buffer for making reading compressed data + // fast and convenient + StreamBuffer *pstreambuf = NULL; + if (details.compression == COMPRESSION_PACKBITS) { + pstreambuf = new StreamBuffer(inSource, 2048, false); + if (pstreambuf->InitCheck() != B_OK) + return B_NO_MEMORY; + } + + for (uint32 i = 0; i < details.stripsPerImage; i++) { + uint32 read = 0; + + // If Packbits compression, prepare streambuffer + // for reading + if (details.compression == COMPRESSION_PACKBITS && + !pstreambuf->Seek(details.pstripOffsets[i])) + return B_NO_TRANSLATOR; + + // Read / Write one line at a time for each + // line in the strip + while (read < details.pstripByteCounts[i]) { + + ssize_t ret = 0; + if (details.compression == COMPRESSION_NONE) { + ret = inSource->ReadAt(details.pstripOffsets[i] + read, + inbuffer, inbufferlen); + if (ret != static_cast(inbufferlen)) + break; + + } else if (details.compression == COMPRESSION_PACKBITS) { + ret = unpack(pstreambuf, inbuffer, inbufferlen); + if (ret < 1) + break; + } + + read += ret; + tiff_to_bits(inbuffer, inbufferlen, outbuffer, + details.imageType); + outDestination->Write(outbuffer, outbufferlen); + } + // If while loop was broken... + if (read < details.pstripByteCounts[i]) + break; + } + + // Clean up + if (pstreambuf) { + delete pstreambuf; + pstreambuf = NULL; + } + + delete[] inbuffer; + inbuffer = NULL; + delete[] outbuffer; + outbuffer = NULL; + + delete[] details.pstripOffsets; + details.pstripOffsets = NULL; + delete[] details.pstripByteCounts; + details.pstripByteCounts = NULL; + + return B_OK; + + } else + return result; +} + // --------------------------------------------------------------- // Translate // @@ -605,9 +882,67 @@ TIFFTranslator::Translate(BPositionIO *inSource, outType = B_TRANSLATOR_BITMAP; if (outType != B_TRANSLATOR_BITMAP && outType != B_TIFF_FORMAT) return B_NO_TRANSLATOR; + + // Convert the magic numbers to the various byte orders so that + // I won't have to convert the data read in to see whether or not + // it is a supported type + uint32 nbits = B_TRANSLATOR_BITMAP; + if (swap_data(B_UINT32_TYPE, &nbits, sizeof(uint32), + B_SWAP_HOST_TO_BENDIAN) != B_OK) + return B_ERROR; + + // Read in the magic number and determine if it + // is a supported type + uint8 ch[4]; + inSource->Seek(0, SEEK_SET); + if (inSource->Read(ch, 4) != 4) + return B_NO_TRANSLATOR; - return B_NO_TRANSLATOR; - // translator isn't implemented yet + // Read settings from ioExtension + bool bheaderonly = false, bdataonly = false; + if (ioExtension) { + if (ioExtension->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &bheaderonly)) + // if failed, make sure bool is default value + bheaderonly = false; + if (ioExtension->FindBool(B_TRANSLATOR_EXT_DATA_ONLY, &bdataonly)) + // if failed, make sure bool is default value + bdataonly = false; + + if (bheaderonly && bdataonly) + // can't both "only write the header" and "only write the data" + // at the same time + return B_BAD_VALUE; + } + + uint32 n32ch; + memcpy(&n32ch, ch, sizeof(uint32)); + // if B_TRANSLATOR_BITMAP type + if (n32ch == nbits) + return B_NO_TRANSLATOR; + // Not implemented yet + + // Might be TIFF image + else { + // TIFF Byte Order / Magic + const uint8 kleSig[] = { 0x49, 0x49, 0x2a, 0x00 }; + const uint8 kbeSig[] = { 0x4d, 0x4d, 0x00, 0x2a }; + + swap_action swp; + if (memcmp(ch, kleSig, 4) == 0) { + swp = B_SWAP_LENDIAN_TO_HOST; + printf("Byte Order: little endian\n"); + } else if (memcmp(ch, kbeSig, 4) == 0) { + swp = B_SWAP_BENDIAN_TO_HOST; + printf("Byte Order: big endian\n"); + } else { + // If not a TIFF or a Be Bitmap image + printf("Invalid byte order value\n"); + return B_NO_TRANSLATOR; + } + + return translate_from_tiff(inSource, 4, ch, swp, outType, + outDestination); + } } // --------------------------------------------------------------- diff --git a/src/add-ons/translators/tifftranslator/TIFFTranslator.h b/src/add-ons/translators/tifftranslator/TIFFTranslator.h index 4c5b9fed99..3e28d6ce7d 100755 --- a/src/add-ons/translators/tifftranslator/TIFFTranslator.h +++ b/src/add-ons/translators/tifftranslator/TIFFTranslator.h @@ -46,21 +46,31 @@ #define TIFF_IN_QUALITY 0.1 #define TIFF_IN_CAPABILITY 0.1 -#define TIFF_OUT_QUALITY 0.0 -#define TIFF_OUT_CAPABILITY 0.0 +#define TIFF_OUT_QUALITY 0.6 +#define TIFF_OUT_CAPABILITY 0.2 #define BBT_IN_QUALITY 0.4 #define BBT_IN_CAPABILITY 0.6 #define BBT_OUT_QUALITY 0.4 #define BBT_OUT_CAPABILITY 0.6 +enum TIFF_IMAGE_TYPE { + TIFF_RGB = 1, + TIFF_CMYK +}; + // structure for storing only the TIFF fields // that are of interest to the TIFFTranslator struct TiffDetails { uint32 width; uint32 height; uint32 compression; + uint32 rowsPerStrip; + uint32 stripsPerImage; + uint32 *pstripOffsets; + uint32 *pstripByteCounts; uint16 interpretation; + uint16 imageType; }; class TIFFTranslator : public BTranslator { diff --git a/src/add-ons/translators/tifftranslator/TiffField.h b/src/add-ons/translators/tifftranslator/TiffField.h index f24b58b02b..4e1b78d0e4 100755 --- a/src/add-ons/translators/tifftranslator/TiffField.h +++ b/src/add-ons/translators/tifftranslator/TiffField.h @@ -60,15 +60,20 @@ #define PHOTO_RGB 2 #define PHOTO_PALETTE 3 #define PHOTO_MASK 4 + #define PHOTO_SEPARATED 5 #define TAG_FILL_ORDER 266 #define TAG_STRIP_OFFSETS 273 #define TAG_ORIENTATION 274 #define TAG_SAMPLES_PER_PIXEL 277 #define TAG_ROWS_PER_STRIP 278 + #define DEFAULT_ROWS_PER_STRIP 4294967295L #define TAG_STRIP_BYTE_COUNTS 279 #define TAG_PLANAR_CONFIGURATION 284 #define TAG_RESOLUTION_UNIT 296 #define TAG_COLOR_MAP 320 +#define TAG_INK_SET 332 + #define INK_SET_CMYK 1 + #define INK_SET_NOT_CMYK 2 #define TAG_EXTRA_SAMPLES 338 #define TAG_SAMPLE_FORMAT 339 diff --git a/src/add-ons/translators/tifftranslator/TiffIfd.cpp b/src/add-ons/translators/tifftranslator/TiffIfd.cpp index 223d98fafc..c3aa51070c 100755 --- a/src/add-ons/translators/tifftranslator/TiffIfd.cpp +++ b/src/add-ons/translators/tifftranslator/TiffIfd.cpp @@ -175,6 +175,42 @@ TiffIfd::GetUint(uint16 tag, uint32 index) throw TiffIfdFieldNotFoundException(); } +uint32 +TiffIfd::GetUintArray(uint16 tag, uint32 **pout) +{ + TiffField *pfield = GetField(tag); + if (pfield) { + + TiffUintField *puintField = NULL; + puintField = dynamic_cast(pfield); + if (puintField) { + + uint32 count = puintField->GetCount(); + (*pout) = new uint32[count]; + uint32 *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; + } + + return count; + + } else + throw TiffIfdUnexpectedTypeException(); + } + + throw TiffIfdFieldNotFoundException(); +} + TiffField * TiffIfd::GetField(uint16 tag) { diff --git a/src/add-ons/translators/tifftranslator/TiffIfd.h b/src/add-ons/translators/tifftranslator/TiffIfd.h index 345f6ee23f..141a88b466 100755 --- a/src/add-ons/translators/tifftranslator/TiffIfd.h +++ b/src/add-ons/translators/tifftranslator/TiffIfd.h @@ -52,6 +52,10 @@ class TiffIfdBadIndexException : public TiffIfdException { public: TiffIfdBadIndexException() { }; }; +class TiffIfdNoMemoryException : public TiffIfdException { +public: + TiffIfdNoMemoryException() { }; +}; class TiffIfd { public: @@ -73,6 +77,16 @@ public: // throws: TiffIfdFieldNotFoundException(), // TiffIfdUnexpectedTypeException(), // TiffIfdBadIndexException() + + uint32 GetUintArray(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 + // + // throws: TiffIfdFieldNotFoundException(), + // TiffIfdUnexpectedTypeException(), + // TiffIfdBadIndexException() + // TiffIfdNoMemoryException() private: void LoadFields(uint32 offset, BPositionIO &io, swap_action swp);