From 462cf13ce78d0076b8800b1eceba1325d731af5f Mon Sep 17 00:00:00 2001 From: Matthew Wilber Date: Fri, 16 Jan 2004 02:04:30 +0000 Subject: [PATCH] Added Stephan Assmus' TIFF writing code. Now the TIFFTranslator can write TIFF images with a few different compression options. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6100 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../translators/libtifftranslator/Jamfile | 8 +- .../libtifftranslator/TIFFTranslator.cpp | 661 ++++++++++++++++-- .../libtifftranslator/TIFFTranslator.h | 14 + .../TIFFTranslatorSettings.cpp | 446 ++++++++++++ .../TIFFTranslatorSettings.h | 91 +++ .../libtifftranslator/TIFFView.cpp | 110 ++- .../translators/libtifftranslator/TIFFView.h | 24 +- .../translators/libtifftranslator/tiffconf.h | 4 +- 8 files changed, 1294 insertions(+), 64 deletions(-) create mode 100644 src/add-ons/translators/libtifftranslator/TIFFTranslatorSettings.cpp create mode 100644 src/add-ons/translators/libtifftranslator/TIFFTranslatorSettings.h diff --git a/src/add-ons/translators/libtifftranslator/Jamfile b/src/add-ons/translators/libtifftranslator/Jamfile index 95ea1289b8..c8c49e37fe 100644 --- a/src/add-ons/translators/libtifftranslator/Jamfile +++ b/src/add-ons/translators/libtifftranslator/Jamfile @@ -1,6 +1,9 @@ SubDir OBOS_TOP src add-ons translators libtifftranslator ; +UseLibraryHeaders zlib ; + Translator TIFFTranslator : + # libtiff tif_aux.c tif_close.c tif_codec.c @@ -34,12 +37,15 @@ Translator TIFFTranslator : tif_warning.c tif_write.c tif_zip.c + + # TIFFTranslator + TIFFTranslatorSettings.cpp TIFFMain.cpp TIFFTranslator.cpp TIFFView.cpp TIFFWindow.cpp ; -LinkSharedOSLibs TIFFTranslator : be translation ; +LinkSharedOSLibs TIFFTranslator : be translation libz.a ; Package openbeos-translationkit-cvs : TIFFTranslator : diff --git a/src/add-ons/translators/libtifftranslator/TIFFTranslator.cpp b/src/add-ons/translators/libtifftranslator/TIFFTranslator.cpp index ada66fc8ef..8f421aad61 100644 --- a/src/add-ons/translators/libtifftranslator/TIFFTranslator.cpp +++ b/src/add-ons/translators/libtifftranslator/TIFFTranslator.cpp @@ -1,6 +1,7 @@ /*****************************************************************************/ // TIFFTranslator // Written by Michael Wilber, OBOS Translation Kit Team +// Write support added by Stephan Aßmus // // TIFFTranslator.cpp // @@ -28,11 +29,21 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. /*****************************************************************************/ +// +// How this works: +// +// libtiff has a special version of TIFFOpen() that gets passed custom +// functions for reading writing etc. and a handle. This handle in our case +// is a BPositionIO object, which libtiff passes on to the functions for reading +// writing etc. So when operations are performed on the TIFF* handle that is +// returned by TIFFOpen(), libtiff uses the special reading writing etc +// functions so that all stream io happens on the BPositionIO object. #include #include #include "tiffio.h" #include "TIFFTranslator.h" +#include "TIFFTranslatorSettings.h" #include "TIFFView.h" // The input formats that this translator supports. @@ -64,6 +75,14 @@ translation_format gOutputFormats[] = { BBT_OUT_CAPABILITY, "image/x-be-bitmap", "Be Bitmap Format (TIFFTranslator)" + }, + { + B_TIFF_FORMAT, + B_TRANSLATOR_BITMAP, + TIFF_OUT_QUALITY, + TIFF_OUT_CAPABILITY, + "image/tiff", + "TIFF image" } }; @@ -177,8 +196,12 @@ tiff_unmap_file_proc(thandle_t stream, tdata_t base, toff_t size) // Returns: // --------------------------------------------------------------- TIFFTranslator::TIFFTranslator() - : BTranslator() + : BTranslator(), + fSettings(new TIFFTranslatorSettings()) { + fSettings->LoadSettings(); + // load settings from the TIFF Translator settings file + strcpy(fName, "TIFF Images"); sprintf(fInfo, "TIFF image translator v%d.%d.%d %s", static_cast(TIFF_TRANSLATOR_VERSION >> 8), @@ -201,6 +224,7 @@ TIFFTranslator::TIFFTranslator() // --------------------------------------------------------------- TIFFTranslator::~TIFFTranslator() { + fSettings->Release(); } // --------------------------------------------------------------- @@ -541,25 +565,10 @@ TIFFTranslator::Identify(BPositionIO *inSource, uint8 ch[4]; if (inSource->Read(ch, 4) != 4) return B_NO_TRANSLATOR; - // 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; - } - bheaderonly = bdataonly = false; - // only allow writing of the entire image - // (fix for buggy programs that lie about what they actually need) + if (ioExtension && fSettings->LoadSettings(ioExtension) < B_OK) + return B_BAD_VALUE; // reason could be invalid settings, + // like header only and data only set at the same time uint32 n32ch; memcpy(&n32ch, ch, sizeof(uint32)); @@ -582,12 +591,569 @@ TIFFTranslator::Identify(BPositionIO *inSource, } } +// How this works: +// Following are a couple of functions, +// +// convert_buffer_* to convert a buffer in place to the TIFF native format +// +// convert_buffers_* to convert from one buffer to another to the TIFF +// native format, additionally compensating for padding bytes +// I don't know if libTIFF can be set up to respect padding bytes, +// otherwise this whole thing could be simplified a bit. +// +// Additionally, there are two functions convert_buffer() and convert_buffers() that take +// a color_space as one of the arguments and pick the correct worker functions from there. +// This way I don't write any code more than once, for easier debugging and maintainance. + + +// convert_buffer_bgra_rgba +inline void +convert_buffer_bgra_rgba(uint8* buffer, + uint32 rows, uint32 width, uint32 bytesPerRow) +{ + for (uint32 y = 0; y < rows; y++) { + uint8* handle = buffer; + for (uint32 x = 0; x < width; x++) { + uint8 temp = handle[0]; + handle[0] = handle[2]; + handle[2] = temp; + handle += 4; + } + buffer += bytesPerRow; + } +} + +// convert_buffer_argb_rgba +inline void +convert_buffer_argb_rgba(uint8* buffer, + uint32 rows, uint32 width, uint32 bytesPerRow) +{ + for (uint32 y = 0; y < rows; y++) { + uint8* handle = buffer; + for (uint32 x = 0; x < width; x++) { + uint8 temp = handle[0]; + handle[0] = handle[1]; + handle[1] = handle[2]; + handle[2] = handle[3]; + handle[3] = temp; + handle += 4; + } + buffer += bytesPerRow; + } +} + +// convert_buffers_bgra_rgba +inline void +convert_buffers_bgra_rgba(uint8* inBuffer, uint8* outBuffer, + uint32 rows, uint32 width, uint32 bytesPerRow) +{ + for (uint32 y = 0; y < rows; y++) { + uint8* inHandle = inBuffer; + uint8* outHandle = outBuffer; + for (uint32 x = 0; x < width; x++) { + outHandle[0] = inHandle[2]; + outHandle[1] = inHandle[1]; + outHandle[2] = inHandle[0]; + outHandle[3] = inHandle[3]; + inHandle += 4; + outHandle += 4; + } + inBuffer += bytesPerRow; + outBuffer += width * 4; + } +} + +// convert_buffers_argb_rgba +inline void +convert_buffers_argb_rgba(uint8* inBuffer, uint8* outBuffer, + uint32 rows, uint32 width, uint32 bytesPerRow) +{ + for (uint32 y = 0; y < rows; y++) { + uint8* inHandle = inBuffer; + uint8* outHandle = outBuffer; + for (uint32 x = 0; x < width; x++) { + outHandle[0] = inHandle[1]; + outHandle[1] = inHandle[2]; + outHandle[2] = inHandle[3]; + outHandle[3] = inHandle[0]; + inHandle += 4; + outHandle += 4; + } + inBuffer += bytesPerRow; + outBuffer += width * 4; + } +} + +// convert_buffers_bgrX_rgb +inline void +convert_buffers_bgrX_rgb(uint8* inBuffer, uint8* outBuffer, + uint32 rows, uint32 width, uint32 bytesPerRow, uint32 samplesPerPixel) +{ + for (uint32 y = 0; y < rows; y++) { + uint8* inHandle = inBuffer; + uint8* outHandle = outBuffer; + for (uint32 x = 0; x < width; x++) { + // the usage of temp is just in case inBuffer == outBuffer + // (see convert_buffer() for B_RGB24) + uint8 temp = inHandle[0]; + outHandle[0] = inHandle[2]; + outHandle[1] = inHandle[1]; + outHandle[2] = temp; + inHandle += samplesPerPixel; + outHandle += 3; + } + inBuffer += bytesPerRow; + outBuffer += width * 3; + } +} + +// convert_buffers_rgbX_rgb +inline void +convert_buffers_rgbX_rgb(uint8* inBuffer, uint8* outBuffer, + uint32 rows, uint32 width, uint32 bytesPerRow, uint32 samplesPerPixel) +{ + for (uint32 y = 0; y < rows; y++) { + uint8* inHandle = inBuffer; + uint8* outHandle = outBuffer; + for (uint32 x = 0; x < width; x++) { + outHandle[0] = inHandle[0]; + outHandle[1] = inHandle[1]; + outHandle[2] = inHandle[2]; + inHandle += samplesPerPixel; + outHandle += 3; + } + inBuffer += bytesPerRow; + outBuffer += width * 3; + } +} + + +// convert_buffers_cmap +inline void +convert_buffers_cmap(uint8* inBuffer, uint8* outBuffer, + uint32 rows, uint32 width, uint32 bytesPerRow) +{ + // compensate for bytesPerRow != width (padding bytes) + // this function will not be called if bytesPerRow == width, btw + for (uint32 y = 0; y < rows; y++) { + _TIFFmemcpy(outBuffer, inBuffer, width); + inBuffer += bytesPerRow; + outBuffer += width; + } +} + +// convert_buffer +inline void +convert_buffer(color_space format, + uint8* buffer, uint32 rows, uint32 width, uint32 bytesPerRow) +{ + switch (format) { + case B_RGBA32: + convert_buffer_bgra_rgba(buffer, rows, width, bytesPerRow); + break; + case B_RGBA32_BIG: + convert_buffer_argb_rgba(buffer, rows, width, bytesPerRow); + break; +// case B_RGB32: +// case B_RGB32_BIG: +// these two cannot be encountered, since inBufferSize != bytesPerStrip +// (we're stripping the unused "alpha" channel 32->24 bits) + case B_RGB24: + convert_buffers_bgrX_rgb(buffer, buffer, rows, width, bytesPerRow, 3); + break; +// case B_RGB24_BIG: + // buffer already has the correct format + break; +// case B_CMAP8: +// case B_GRAY8: + // buffer already has the correct format + break; + default: + break; + } +} + +// convert_buffers +inline void +convert_buffers(color_space format, + uint8* inBuffer, uint8* outBuffer, + uint32 rows, uint32 width, uint32 bytesPerRow) +{ + switch (format) { + case B_RGBA32: + convert_buffers_bgra_rgba(inBuffer, outBuffer, rows, width, bytesPerRow); + break; + case B_RGBA32_BIG: + convert_buffers_argb_rgba(inBuffer, outBuffer, rows, width, bytesPerRow); + break; + case B_RGB32: + convert_buffers_bgrX_rgb(inBuffer, outBuffer, rows, width, bytesPerRow, 4); + break; + case B_RGB32_BIG: + convert_buffers_rgbX_rgb(inBuffer, outBuffer, rows, width, bytesPerRow, 4); + break; + case B_RGB24: + convert_buffers_bgrX_rgb(inBuffer, outBuffer, rows, width, bytesPerRow, 3); + break; + case B_RGB24_BIG: + convert_buffers_rgbX_rgb(inBuffer, outBuffer, rows, width, bytesPerRow, 3); + break; + case B_CMAP8: + case B_GRAY8: + convert_buffers_cmap(inBuffer, outBuffer, rows, width, bytesPerRow); + break; + default: + break; + } +} + +// Sets up any additional TIFF fields for the color spaces it supports, +// determines if it needs one or two buffers to carry out any conversions, +// uses the various convert routines above to do the actual conversion, +// writes complete strips of data plus one strip of remaining data. +// +// write_tif_stream +status_t +write_tif_stream(TIFF* tif, BPositionIO* inSource, color_space format, + uint32 width, uint32 height, uint32 bytesPerRow, + uint32 rowsPerStrip, uint32 dataSize) +{ + uint32 bytesPerStrip = 0; + + // set up the TIFF fields about what channels we write + switch (format) { + case B_RGBA32: + case B_RGBA32_BIG: + uint16 extraSamples[1]; + extraSamples[0] = EXTRASAMPLE_UNASSALPHA; + TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, extraSamples); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 4); + // going to write rgb + alpha channels + bytesPerStrip = width * 4 * rowsPerStrip; + break; + case B_RGB32: + case B_RGB32_BIG: + case B_RGB24: + case B_RGB24_BIG: + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3); + // going to write just the rgb channels + bytesPerStrip = width * 3 * rowsPerStrip; + break; + case B_CMAP8: + case B_GRAY8: + bytesPerStrip = width * rowsPerStrip; + break; + default: + return B_BAD_VALUE; + } + + uint32 remaining = dataSize; + status_t ret = B_OK; + // Write the information to the stream + uint32 inBufferSize = bytesPerRow * rowsPerStrip; + // allocate intermediate input buffer + uint8* inBuffer = (uint8*)_TIFFmalloc(inBufferSize); + ssize_t read, written = B_ERROR; + // bytesPerStrip is the size of the buffer that libtiff expects to write per strip + // it might be different to the size of the input buffer, + // if that one contains padding bytes at the end of each row + if (inBufferSize != bytesPerStrip) { + // allocate a second buffer + // (two buffers are needed since padding bytes have to be compensated for) + uint8* outBuffer = (uint8*)_TIFFmalloc(bytesPerStrip); + if (inBuffer && outBuffer) { +//printf("using two buffers\n"); + read = inSource->Read(inBuffer, inBufferSize); + uint32 stripIndex = 0; + while (read == (ssize_t)inBufferSize) { +//printf("writing bytes: %ld (strip: %ld)\n", read, stripIndex); + // convert the buffers (channel order) and compensate + // for bytesPerRow != samplesPerRow (padding bytes) + convert_buffers(format, inBuffer, outBuffer, + rowsPerStrip, width, bytesPerRow); + // let libtiff write the encoded strip to the BPositionIO + written = TIFFWriteEncodedStrip(tif, stripIndex, outBuffer, bytesPerStrip); + stripIndex++; + if (written < B_OK) + break; + remaining -= inBufferSize; + read = inSource->Read(inBuffer, min_c(inBufferSize, remaining)); + } + // write the rest of the remaining rows + if (read < (ssize_t)inBufferSize && read > 0) { +//printf("writing remaining bytes: %ld\n", read); + // convert the buffers (channel order) and compensate + // for bytesPerRow != samplesPerRow (padding bytes) + convert_buffers(format, inBuffer, outBuffer, + read / bytesPerRow, width, bytesPerRow); + // let libtiff write the encoded strip to the BPositionIO + written = TIFFWriteEncodedStrip(tif, stripIndex, outBuffer, read); + remaining -= read; + } + } else + ret = B_NO_MEMORY; + // clean up output buffer + if (outBuffer) + _TIFFfree(outBuffer); + } else { +//printf("using one buffer\n"); + // the input buffer is all we need, we convert it in place + if (inBuffer) { + read = inSource->Read(inBuffer, inBufferSize); + uint32 stripIndex = 0; + while (read == (ssize_t)inBufferSize) { +//printf("writing bytes: %ld (strip: %ld)\n", read, stripIndex); + // convert the buffer (channel order) + convert_buffer(format, inBuffer, + rowsPerStrip, width, bytesPerRow); + // let libtiff write the encoded strip to the BPositionIO + written = TIFFWriteEncodedStrip(tif, stripIndex, inBuffer, bytesPerStrip); + stripIndex++; + if (written < 0) + break; + remaining -= inBufferSize; + read = inSource->Read(inBuffer, min_c(inBufferSize, remaining)); + } + // write the rest of the remaining rows + if (read < (ssize_t)inBufferSize && read > 0) { +//printf("writing remaining bytes: %ld (strip: %ld)\n", read, stripIndex); + // convert the buffers (channel order) and compensate + // for bytesPerRow != samplesPerRow (padding bytes) + convert_buffer(format, inBuffer, + read / bytesPerRow, width, bytesPerRow); + // let libtiff write the encoded strip to the BPositionIO + written = TIFFWriteEncodedStrip(tif, stripIndex, inBuffer, read); + remaining -= read; + } + } else + ret = B_NO_MEMORY; + } + // clean up input buffer + if (inBuffer) + _TIFFfree(inBuffer); + // see if there was an error reading or writing the streams + if (remaining > 0) + // "written" may contain a more specific error + ret = written < 0 ? written : B_ERROR; + else + ret = B_OK; + + return ret; +} + +// translate_from_bits +status_t +translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read, + BMessage *ioExtension, uint32 outType, BPositionIO *outDestination, + TIFFTranslatorSettings &settings) +{ + TranslatorBitmap bitsHeader; + + bool bheaderonly = false, bdataonly = false; + // Always write out the entire image. Some programs + // fail when given "headerOnly", even though they requested it. + // These settings are not applicable when outputting TIFFs + uint32 compression = settings.SetGetCompression(); + + status_t result; + result = identify_bits_header(inSource, NULL, amtread, read, &bitsHeader); + if (result != B_OK) + return result; + + // Translate B_TRANSLATOR_BITMAP to B_TRANSLATOR_BITMAP, easy enough :) + if (outType == B_TRANSLATOR_BITMAP) { + // write out bitsHeader (only if configured to) + if (bheaderonly || (!bheaderonly && !bdataonly)) { + if (swap_data(B_UINT32_TYPE, &bitsHeader, + sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK) + return B_ERROR; + if (outDestination->Write(&bitsHeader, + sizeof(TranslatorBitmap)) != sizeof(TranslatorBitmap)) + return B_ERROR; + } + + // write out the data (only if configured to) + if (bdataonly || (!bheaderonly && !bdataonly)) { + uint32 size = 4096; + uint8* buf = new uint8[size]; + uint32 remaining = B_BENDIAN_TO_HOST_INT32(bitsHeader.dataSize); + ssize_t rd, writ = B_ERROR; + rd = inSource->Read(buf, size); + while (rd > 0) { + writ = outDestination->Write(buf, rd); + if (writ < 0) + break; + remaining -= static_cast(writ); + rd = inSource->Read(buf, min_c(size, remaining)); + } + delete[] buf; + + if (remaining > 0) + // writ may contain a more specific error + return writ < 0 ? writ : B_ERROR; + else + return B_OK; + } else + return B_OK; + + // Translate B_TRANSLATOR_BITMAP to B_TIFF_FORMAT + } else if (outType == B_TIFF_FORMAT) { + // Set up TIFF header + + // get TIFF handle + TIFF* tif = TIFFClientOpen("TIFFTranslator", "w", outDestination, + tiff_read_proc, tiff_write_proc, tiff_seek_proc, tiff_close_proc, + tiff_size_proc, tiff_map_file_proc, tiff_unmap_file_proc); + if (!tif) + return B_NO_TRANSLATOR; + + // common fields which are independent of the bitmap format + uint32 width = bitsHeader.bounds.IntegerWidth() + 1; + uint32 height = bitsHeader.bounds.IntegerHeight() + 1; + uint32 dataSize = bitsHeader.dataSize; + uint32 bytesPerRow = bitsHeader.rowBytes; + + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); +/*const char* compressionString = NULL; +switch (compression) { + case COMPRESSION_NONE: + compressionString = "None"; + break; + case COMPRESSION_PACKBITS: + compressionString = "RLE"; + break; + case COMPRESSION_DEFLATE: + compressionString = "Deflate"; + break; + case COMPRESSION_LZW: + compressionString = "LZW"; + break; + case COMPRESSION_JPEG: + compressionString = "JPEG"; + break; + case COMPRESSION_JP2000: + compressionString = "JPEG2000"; + break; +} +if (compressionString) +printf("using compression: %s\n", compressionString); +else +printf("using unkown compression (%ld).\n", compression); +*/ + TIFFSetField(tif, TIFFTAG_COMPRESSION, compression); + + // TODO: some extra fields that should also get some special attention + TIFFSetField(tif, TIFFTAG_XRESOLUTION, 150.0); + TIFFSetField(tif, TIFFTAG_YRESOLUTION, 150.0); + TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); + + // we are going to write XX row(s) of pixels (lines) per strip + uint32 rowsPerStrip = TIFFDefaultStripSize(tif, 0); +//printf("recommended rows per strip: %ld\n", TIFFDefaultStripSize(tif, 0)); + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsPerStrip); + + status_t ret = B_OK; + // set the rest of the fields according to the bitmap format + switch (bitsHeader.colors) { + + // Output to 32-bit True Color TIFF (8 bits alpha) + case B_RGBA32: + case B_RGB32: + case B_RGB24: + case B_RGBA32_BIG: + case B_RGB32_BIG: + case B_RGB24_BIG: + // set the fields specific to this color space + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); +// TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + // write the tiff stream + ret = write_tif_stream(tif, inSource, bitsHeader.colors, + width, height, bytesPerRow, + rowsPerStrip, dataSize); + break; +/* + case B_CMYA32: + break; + + // Output to 15-bit True Color TIFF + case B_RGB15: + case B_RGB15_BIG: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 5); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + bytesPerStrip = width * 2 * rowsPerStrip; + break; +*/ + // Output to 8-bit Color Mapped TIFF 32 bits per color map entry + case B_CMAP8: { + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + // convert the system palette to 16 bit values for libtiff + const color_map *map = system_colors(); + if (map) { + uint16 red[256]; + uint16 green[256]; + uint16 blue[256]; + for (uint32 i = 0; i < 256; i++) { + // scale 8 bits to 16 bits + red[i] = map->color_list[i].red * 256 + map->color_list[i].red; + green[i] = map->color_list[i].green * 256 + map->color_list[i].green; + blue[i] = map->color_list[i].blue * 256 + map->color_list[i].blue; + } + TIFFSetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue); + // write the tiff stream + ret = write_tif_stream(tif, inSource, bitsHeader.colors, + width, height, bytesPerRow, + rowsPerStrip, dataSize); + } else + ret = B_ERROR; + break; + } + // Output to 8-bit Black and White TIFF + case B_GRAY8: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + ret = write_tif_stream(tif, inSource, bitsHeader.colors, + width, height, bytesPerRow, + rowsPerStrip, dataSize); + break; + +/* // Output to 1-bit Black and White TIFF + case B_GRAY1: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 1); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 8); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + bytesPerStrip = ((width + 7) / 8) * rowsPerStrip; + break; +*/ + default: + ret = B_NO_TRANSLATOR; + } + // Close the handle + TIFFClose(tif); + return ret; + + } else + return B_NO_TRANSLATOR; +} + +// translate_from_tiff status_t translate_from_tiff(BPositionIO *inSource, BMessage *ioExtension, - uint32 outType, BPositionIO *outDestination, bool bheaderonly, - bool bdataonly) + uint32 outType, BPositionIO *outDestination, + TIFFTranslatorSettings &settings) { status_t result = B_NO_TRANSLATOR; + + bool bheaderonly = false, bdataonly = false; + // Always write out the entire image. Some programs + // fail when given "headerOnly", even though they requested it. + // These settings are not applicable when outputting TIFFs // variables needing cleanup TIFF *ptif = NULL; @@ -739,44 +1305,26 @@ TIFFTranslator::Translate(BPositionIO *inSource, return B_NO_TRANSLATOR; // 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; - } - bheaderonly = bdataonly = false; - // only allow writing of the entire image - // (fix for buggy programs that lie about what they actually need) + if (ioExtension && fSettings->LoadSettings(ioExtension) < B_OK) + return B_BAD_VALUE; uint32 n32ch; memcpy(&n32ch, ch, sizeof(uint32)); if (n32ch == nbits) { // B_TRANSLATOR_BITMAP type - inSource->Seek(0, SEEK_SET); - - const size_t kbufsize = 2048; - uint8 buffer[kbufsize]; - ssize_t ret = inSource->Read(buffer, kbufsize); - while (ret > 0) { - outDestination->Write(buffer, ret); - ret = inSource->Read(buffer, kbufsize); - } - - return B_OK; - + return translate_from_bits(inSource, 4, ch, ioExtension, outType, + outDestination, *fSettings); } else // Might be TIFF image return translate_from_tiff(inSource, ioExtension, outType, - outDestination, bheaderonly, bdataonly); + outDestination, *fSettings); +} + +// returns the current translator settings into ioExtension +status_t +TIFFTranslator::GetConfigurationMessage(BMessage *ioExtension) +{ + return fSettings->GetConfigurationMessage(ioExtension); } // --------------------------------------------------------------- @@ -808,9 +1356,12 @@ TIFFTranslator::MakeConfigurationView(BMessage *ioExtension, BView **outView, { if (!outView || !outExtent) return B_BAD_VALUE; + if (ioExtension && fSettings->LoadSettings(ioExtension) < B_OK) + return B_BAD_VALUE; TIFFView *view = new TIFFView(BRect(0, 0, 225, 175), - "TIFFTranslator Settings", B_FOLLOW_ALL, B_WILL_DRAW); + "TIFFTranslator Settings", B_FOLLOW_ALL, B_WILL_DRAW, + AcquireSettings()); if (!view) return B_NO_MEMORY; @@ -820,4 +1371,10 @@ TIFFTranslator::MakeConfigurationView(BMessage *ioExtension, BView **outView, return B_OK; } +// AcquireSettings +TIFFTranslatorSettings * +TIFFTranslator::AcquireSettings() +{ + return fSettings->Acquire(); +} diff --git a/src/add-ons/translators/libtifftranslator/TIFFTranslator.h b/src/add-ons/translators/libtifftranslator/TIFFTranslator.h index 2ba9115ba3..79449812b8 100644 --- a/src/add-ons/translators/libtifftranslator/TIFFTranslator.h +++ b/src/add-ons/translators/libtifftranslator/TIFFTranslator.h @@ -50,12 +50,17 @@ #define TIFF_IN_QUALITY 0.5 #define TIFF_IN_CAPABILITY 0.6 +#define TIFF_OUT_QUALITY 0.8 + // high out quality because this code outputs fully standard TIFFs +#define TIFF_OUT_CAPABILITY 0.4 + // medium out capability because not many TIFF features are supported #define BBT_IN_QUALITY 0.4 #define BBT_IN_CAPABILITY 0.6 #define BBT_OUT_QUALITY 0.4 #define BBT_OUT_CAPABILITY 0.6 +class TIFFTranslatorSettings; class TIFFTranslator : public BTranslator { public: @@ -92,12 +97,19 @@ public: // this function is the whole point of the Translation Kit, // it translates the data in inSource to outDestination // using the format outType + + virtual status_t GetConfigurationMessage(BMessage *ioExtension); + // write the current state of the translator into + // the supplied BMessage object + virtual status_t MakeConfigurationView(BMessage *ioExtension, BView **outView, BRect *outExtent); // creates and returns the view for displaying information // about this translator + TIFFTranslatorSettings *AcquireSettings(); + protected: virtual ~TIFFTranslator(); // this is protected because the object is deleted by the @@ -105,6 +117,8 @@ protected: // the user private: + TIFFTranslatorSettings *fSettings; + char fName[30]; char fInfo[100]; }; diff --git a/src/add-ons/translators/libtifftranslator/TIFFTranslatorSettings.cpp b/src/add-ons/translators/libtifftranslator/TIFFTranslatorSettings.cpp new file mode 100644 index 0000000000..eb45cc761e --- /dev/null +++ b/src/add-ons/translators/libtifftranslator/TIFFTranslatorSettings.cpp @@ -0,0 +1,446 @@ +/*****************************************************************************/ +// TIFFTranslatorSettings +// Adopted by Stephan Aßmus, +// from TGATranslatorSettings written by +// Michael Wilber, OBOS Translation Kit Team +// +// TIFFTranslatorSettings.cpp +// +// This class manages (saves/loads/locks/unlocks) the settings +// for the TIFFTranslator. +// +// +// 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 "tiff.h" + +#include +#include +#include + // for B_TRANSLATOR_EXT_* +#include "TIFFTranslatorSettings.h" + +// --------------------------------------------------------------- +// Constructor +// +// Sets the default settings, location for the settings file +// and sets the reference count to 1 +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +TIFFTranslatorSettings::TIFFTranslatorSettings() + : fLock("TIFF Settings Lock") +{ + if (find_directory(B_USER_SETTINGS_DIRECTORY, &fSettingsPath) < B_OK) + fSettingsPath.SetTo("/tmp"); + fSettingsPath.Append(TIFF_SETTINGS_FILENAME); + + fRefCount = 1; + + // Default Settings + // (Used when loading from the settings file or from + // a BMessage fails) + fSettingsMSG.AddBool(B_TRANSLATOR_EXT_HEADER_ONLY, false); + fSettingsMSG.AddBool(B_TRANSLATOR_EXT_DATA_ONLY, false); + fSettingsMSG.AddInt32(TIFF_SETTING_COMPRESSION, COMPRESSION_LZW); + // compression is set to LZW by default +} + +// --------------------------------------------------------------- +// Acquire +// +// Returns a pointer to the TIFFTranslatorSettings and increments +// the reference count. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: pointer to this TIFFTranslatorSettings object +// --------------------------------------------------------------- +TIFFTranslatorSettings * +TIFFTranslatorSettings::Acquire() +{ + TIFFTranslatorSettings *psettings = NULL; + + if (fLock.Lock()) { + fRefCount++; + psettings = this; + fLock.Unlock(); + } + + return psettings; +} + +// --------------------------------------------------------------- +// Release +// +// Decrements the reference count and deletes the +// TIFFTranslatorSettings if the reference count is zero. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: pointer to this TIFFTranslatorSettings object if +// the reference count is greater than zero, returns NULL +// if the reference count is zero and the TIFFTranslatorSettings +// object has been deleted +// --------------------------------------------------------------- +TIFFTranslatorSettings * +TIFFTranslatorSettings::Release() +{ + TIFFTranslatorSettings *psettings = NULL; + + if (fLock.Lock()) { + fRefCount--; + if (fRefCount > 0) { + psettings = this; + fLock.Unlock(); + } else + delete this; + // delete this object and + // release locks + } + + return psettings; +} + +// --------------------------------------------------------------- +// Destructor +// +// Does nothing! +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +TIFFTranslatorSettings::~TIFFTranslatorSettings() +{ +} + +// --------------------------------------------------------------- +// LoadSettings +// +// Loads the settings by reading them from the default +// settings file. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: B_OK if there were no errors or an error code from +// BFile::SetTo() or BMessage::Unflatten() if there were errors +// --------------------------------------------------------------- +status_t +TIFFTranslatorSettings::LoadSettings() +{ + status_t result = B_ERROR; + + if (fLock.Lock()) { + + BFile settingsFile; + result = settingsFile.SetTo(fSettingsPath.Path(), B_READ_ONLY); + if (result >= B_OK) { + BMessage msg; + result = msg.Unflatten(&settingsFile); + if (result >= B_OK) + result = LoadSettings(&msg); + } + + fLock.Unlock(); + } + + return result; +} + +// --------------------------------------------------------------- +// LoadSettings +// +// Loads the settings from a BMessage passed to the function. +// +// Preconditions: +// +// Parameters: pmsg pointer to BMessage that contains the +// settings +// +// Postconditions: +// +// Returns: B_BAD_VALUE if pmsg is NULL or invalid options +// have been found, B_OK if there were no +// errors or an error code from BMessage::FindBool() or +// BMessage::ReplaceBool() if there were other errors +// --------------------------------------------------------------- +status_t +TIFFTranslatorSettings::LoadSettings(BMessage *pmsg) +{ + status_t result = B_BAD_VALUE; + + if (pmsg) { + // Make certain that no TIFF settings + // are missing from the file + bool bheaderOnly, bdataOnly; + uint32 compression; + + result = B_ERROR; + + if (fLock.Lock()) { + + result = pmsg->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &bheaderOnly); + if (result < B_OK) + bheaderOnly = SetGetHeaderOnly(); + result = pmsg->FindBool(B_TRANSLATOR_EXT_DATA_ONLY, &bdataOnly); + if (result < B_OK) + bdataOnly = SetGetDataOnly(); + result = pmsg->FindInt32(TIFF_SETTING_COMPRESSION, (int32*)&compression); + if (result < B_OK) + compression = SetGetCompression(); + + if (bheaderOnly && bdataOnly) + // "write header only" and "write data only" + // are mutually exclusive + result = B_BAD_VALUE; + else { + result = B_OK; + + result = fSettingsMSG.ReplaceBool( + B_TRANSLATOR_EXT_HEADER_ONLY, bheaderOnly); + if (result >= B_OK) + result = fSettingsMSG.ReplaceBool( + B_TRANSLATOR_EXT_DATA_ONLY, bdataOnly); + if (result >= B_OK) + result = fSettingsMSG.ReplaceInt32(TIFF_SETTING_COMPRESSION, + compression); + } + fLock.Unlock(); + } + } + + return result; +} + +// --------------------------------------------------------------- +// SaveSettings +// +// Saves the settings as a flattened BMessage to the default +// settings file +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: B_OK if no errors or an error code from BFile::SetTo() +// or BMessage::Flatten() if there were errors +// --------------------------------------------------------------- +status_t +TIFFTranslatorSettings::SaveSettings() +{ + status_t result = B_ERROR; + + if (fLock.Lock()) { + + BFile settingsFile; + result = settingsFile.SetTo(fSettingsPath.Path(), + B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); + if (result >= B_OK) + result = fSettingsMSG.Flatten(&settingsFile); + + fLock.Unlock(); + } + + return result; +} + +// --------------------------------------------------------------- +// GetConfigurationMessage +// +// Saves the current settings to the BMessage passed to the +// function +// +// Preconditions: +// +// Parameters: pmsg pointer to BMessage where the settings +// will be stored +// +// Postconditions: +// +// Returns: B_OK if there were no errors or an error code from +// BMessage::RemoveName() or BMessage::AddBool() if there were +// errors +// --------------------------------------------------------------- +status_t +TIFFTranslatorSettings::GetConfigurationMessage(BMessage *pmsg) +{ + status_t result = B_BAD_VALUE; + + if (pmsg) { + const char *kNames[] = { + B_TRANSLATOR_EXT_HEADER_ONLY, + B_TRANSLATOR_EXT_DATA_ONLY, + TIFF_SETTING_COMPRESSION + }; + const int32 klen = sizeof(kNames) / sizeof(const char *); + int32 i; + for (i = 0; i < klen; i++) { + result = pmsg->RemoveName(kNames[i]); + if (result < B_OK && result != B_NAME_NOT_FOUND) + break; + } + if (i == klen && fLock.Lock()) { + result = B_OK; + + result = pmsg->AddBool(B_TRANSLATOR_EXT_HEADER_ONLY, + SetGetHeaderOnly()); + if (result >= B_OK) + result = pmsg->AddBool(B_TRANSLATOR_EXT_DATA_ONLY, + SetGetDataOnly()); + if (result >= B_OK) + result = pmsg->AddInt32(TIFF_SETTING_COMPRESSION, SetGetCompression()); + + fLock.Unlock(); + } + } + + return result; +} + +// --------------------------------------------------------------- +// SetGetHeaderOnly +// +// Sets the state of the HeaderOnly setting (if pbHeaderOnly +// is not NULL) and returns the previous value of the +// HeaderOnly setting. +// +// If the HeaderOnly setting is true, only the header of +// the image will be output; the data will not be output. +// +// Preconditions: +// +// Parameters: pbHeaderOnly pointer to a bool specifying +// the new value of the +// HeaderOnly setting +// +// Postconditions: +// +// Returns: the prior value of the HeaderOnly setting +// --------------------------------------------------------------- +bool +TIFFTranslatorSettings::SetGetHeaderOnly(bool *pbHeaderOnly) +{ + bool bprevValue; + + if (fLock.Lock()) { + fSettingsMSG.FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &bprevValue); + if (pbHeaderOnly) + fSettingsMSG.ReplaceBool(B_TRANSLATOR_EXT_HEADER_ONLY, *pbHeaderOnly); + fLock.Unlock(); + } + + return bprevValue; +} + +// --------------------------------------------------------------- +// SetGetDataOnly +// +// Sets the state of the DataOnly setting (if pbDataOnly +// is not NULL) and returns the previous value of the +// DataOnly setting. +// +// If the DataOnly setting is true, only the data of +// the image will be output; the header will not be output. +// +// Preconditions: +// +// Parameters: pbDataOnly pointer to a bool specifying +// the new value of the +// DataOnly setting +// +// Postconditions: +// +// Returns: the prior value of the DataOnly setting +// --------------------------------------------------------------- +bool +TIFFTranslatorSettings::SetGetDataOnly(bool *pbDataOnly) +{ + bool bprevValue; + + if (fLock.Lock()) { + fSettingsMSG.FindBool(B_TRANSLATOR_EXT_DATA_ONLY, &bprevValue); + if (pbDataOnly) + fSettingsMSG.ReplaceBool(B_TRANSLATOR_EXT_DATA_ONLY, *pbDataOnly); + fLock.Unlock(); + } + + return bprevValue; +} + +// --------------------------------------------------------------- +// SetGetRLE +// +// Sets the state of the RLE setting (if pbRLE is not NULL) +// and returns the previous value of the RLE setting. +// +// If the RLE setting is true, TIFF images created by the +// TIFFTranslator will be RLE compressed. +// +// Preconditions: +// +// Parameters: pbRLE pointer to bool which specifies +// the new value for the RLE setting +// +// Postconditions: +// +// Returns: the prior value of the RLE setting +// --------------------------------------------------------------- +uint32 +TIFFTranslatorSettings::SetGetCompression(uint32 *pCompression) +{ + uint32 prevValue; + + if (fLock.Lock()) { + fSettingsMSG.FindInt32(TIFF_SETTING_COMPRESSION, (int32*)&prevValue); + if (pCompression) + fSettingsMSG.ReplaceInt32(TIFF_SETTING_COMPRESSION, *pCompression); + fLock.Unlock(); + } + + return prevValue; +} + diff --git a/src/add-ons/translators/libtifftranslator/TIFFTranslatorSettings.h b/src/add-ons/translators/libtifftranslator/TIFFTranslatorSettings.h new file mode 100644 index 0000000000..348d67f9fd --- /dev/null +++ b/src/add-ons/translators/libtifftranslator/TIFFTranslatorSettings.h @@ -0,0 +1,91 @@ +/*****************************************************************************/ +// TIFFTranslatorSettings +// Adopted by Stephan Aßmus, +// from TGATranslatorSettings written by +// Michael Wilber, OBOS Translation Kit Team +// +// TIFFTranslatorSettings.h +// +// This class manages (saves/loads/locks/unlocks) the settings +// for the TIFFTranslator. +// +// +// 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 TIFF_TRANSLATOR_SETTINGS_H +#define TIFF_TRANSLATOR_SETTINGS_H + +#include +#include +#include + +#define TIFF_SETTINGS_FILENAME "TIFFTranslator_Settings" + +// TIFF Translator Settings +#define TIFF_SETTING_COMPRESSION "tga /compression" + +class TIFFTranslatorSettings { +public: + TIFFTranslatorSettings(); + + TIFFTranslatorSettings *Acquire(); + // increments the reference count, returns this + TIFFTranslatorSettings *Release(); + // decrements the reference count, deletes this + // when count reaches zero, returns this when + // ref count is greater than zero, NULL when + // ref count is zero + + status_t LoadSettings(); + status_t LoadSettings(BMessage *pmsg); + status_t SaveSettings(); + status_t GetConfigurationMessage(BMessage *pmsg); + + bool SetGetHeaderOnly(bool *pbHeaderOnly = NULL); + // sets / gets HeaderOnly setting + // specifies if only the image header should be + // outputted + bool SetGetDataOnly(bool *pbDataOnly = NULL); + // sets / gets DataOnly setting + // specifiees if only the image data should be + // outputted + uint32 SetGetCompression(uint32 *pCompression = NULL); + // sets / gets Compression setting + // specifies what compression will be used + // when the TIFFTranslator creates TIFF images + +private: + ~TIFFTranslatorSettings(); + // private so that Release() must be used + // to delete the object + + BLocker fLock; + int32 fRefCount; + BPath fSettingsPath; + // where the settings file will be loaded from / + // saved to + + BMessage fSettingsMSG; + // the actual settings +}; + +#endif // #ifndef TIFF_TRANSLATOR_SETTTINGS_H diff --git a/src/add-ons/translators/libtifftranslator/TIFFView.cpp b/src/add-ons/translators/libtifftranslator/TIFFView.cpp index 798d465d38..92d8d3d99b 100644 --- a/src/add-ons/translators/libtifftranslator/TIFFView.cpp +++ b/src/add-ons/translators/libtifftranslator/TIFFView.cpp @@ -1,6 +1,7 @@ /*****************************************************************************/ // TIFFView // Written by Michael Wilber, OBOS Translation Kit Team +// Picking the compression method added by Stephan Aßmus, // // TIFFView.cpp // @@ -30,10 +31,35 @@ #include #include -#include "TIFFView.h" -#include "TIFFTranslator.h" + +#include +#include +#include +#include + +#include "tiff.h" #include "tiffvers.h" +#include "TIFFTranslator.h" +#include "TIFFTranslatorSettings.h" + +#include "TIFFView.h" + +// add_menu_item +void +add_menu_item(BMenu* menu, + uint32 compression, + const char* label, + uint32 currentCompression) +{ + // COMPRESSION_NONE + BMessage* message = new BMessage(TIFFView::MSG_COMPRESSION_CHANGED); + message->AddInt32("value", compression); + BMenuItem* item = new BMenuItem(label, message); + item->SetMarked(currentCompression == compression); + menu->AddItem(item); +} + // --------------------------------------------------------------- // Constructor // @@ -48,10 +74,31 @@ // Returns: // --------------------------------------------------------------- TIFFView::TIFFView(const BRect &frame, const char *name, - uint32 resize, uint32 flags) - : BView(frame, name, resize, flags) + uint32 resize, uint32 flags, TIFFTranslatorSettings* settings) + : BView(frame, name, resize, flags), + fSettings(settings) { - SetViewColor(220,220,220,0); + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + BPopUpMenu* menu = new BPopUpMenu("pick compression"); + + uint32 currentCompression = fSettings->SetGetCompression(); + // create the menu items with the various compression methods + add_menu_item(menu, COMPRESSION_NONE, "None", currentCompression); + menu->AddSeparatorItem(); + add_menu_item(menu, COMPRESSION_PACKBITS, "RLE (Packbits)", currentCompression); + add_menu_item(menu, COMPRESSION_DEFLATE, "ZIP (Deflate)", currentCompression); + add_menu_item(menu, COMPRESSION_LZW, "LZW", currentCompression); + +// TODO: the disabled compression modes are not configured in libTIFF +// menu->AddSeparatorItem(); +// add_menu_item(menu, COMPRESSION_JPEG, "JPEG", currentCompression); +// TODO ? - strip encoding is not implemented in libTIFF for this compression +// add_menu_item(menu, COMPRESSION_JP2000, "JPEG2000", currentCompression); + + fCompressionMF = new BMenuField(BRect(20, 50, 215, 70), "compression", + "Use Compression:", menu, true); + AddChild(fCompressionMF); } // --------------------------------------------------------------- @@ -69,8 +116,59 @@ TIFFView::TIFFView(const BRect &frame, const char *name, // --------------------------------------------------------------- TIFFView::~TIFFView() { + fSettings->Release(); } +// --------------------------------------------------------------- +// MessageReceived +// +// Handles state changes of the Compression menu field +// +// Preconditions: +// +// Parameters: area, not used +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +void +TIFFView::MessageReceived(BMessage* message) +{ + switch (message->what) { + case MSG_COMPRESSION_CHANGED: { + uint32 value; + if (message->FindInt32("value", (int32*)&value) >= B_OK) { + fSettings->SetGetCompression(&value); + fSettings->SaveSettings(); + } + break; + } + default: + BView::MessageReceived(message); + } +} + +// --------------------------------------------------------------- +// AllAttached +// +// sets the target for the controls controlling the configuration +// +// Preconditions: +// +// Parameters: area, not used +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +void +TIFFView::AllAttached() +{ + fCompressionMF->Menu()->SetTargetForItems(this); +} + + // --------------------------------------------------------------- // Draw // @@ -110,7 +208,7 @@ TIFFView::Draw(BRect area) static_cast(TIFF_TRANSLATOR_VERSION & 0xf), __DATE__); DrawString(detail, BPoint(xbold, yplain + ybold)); - int32 lineno = 4; + int32 lineno = 6; DrawString("TIFF Library:", BPoint(xbold, yplain * lineno + ybold)); lineno += 2; diff --git a/src/add-ons/translators/libtifftranslator/TIFFView.h b/src/add-ons/translators/libtifftranslator/TIFFView.h index eea4f32ac3..cac8b618c4 100644 --- a/src/add-ons/translators/libtifftranslator/TIFFView.h +++ b/src/add-ons/translators/libtifftranslator/TIFFView.h @@ -1,6 +1,7 @@ /*****************************************************************************/ // TIFFView // Written by Michael Wilber, OBOS Translation Kit Team +// Picking the compression method added by Stephan Aßmus, // // TIFFView.h // @@ -32,20 +33,35 @@ #define TIFFVIEW_H #include -#include -#include + +class BMenuField; +class TIFFTranslatorSettings; class TIFFView : public BView { public: TIFFView(const BRect &frame, const char *name, uint32 resize, - uint32 flags); + uint32 flags, TIFFTranslatorSettings* psettings); // sets up the view ~TIFFView(); - // does nothing + // releases the TIFFTranslator settings + + virtual void AllAttached(); + virtual void MessageReceived(BMessage *message); virtual void Draw(BRect area); // draws information about the TIFFTranslator + + enum { + MSG_COMPRESSION_CHANGED = 'cmch', + }; + +private: + BMenuField* fCompressionMF; + + TIFFTranslatorSettings* fSettings; + // the actual settings for the translator, + // shared with the translator }; #endif // #ifndef TIFFVIEW_H diff --git a/src/add-ons/translators/libtifftranslator/tiffconf.h b/src/add-ons/translators/libtifftranslator/tiffconf.h index 38a5a1bb88..a86c7b5d52 100644 --- a/src/add-ons/translators/libtifftranslator/tiffconf.h +++ b/src/add-ons/translators/libtifftranslator/tiffconf.h @@ -1,4 +1,4 @@ -/* $Header: /tmp/bonefish/open-beos/current/src/add-ons/translators/libtifftranslator/tiffconf.h,v 1.3 2004/01/03 15:22:08 mwilber Exp $ */ +/* $Header: /tmp/bonefish/open-beos/current/src/add-ons/translators/libtifftranslator/tiffconf.h,v 1.4 2004/01/16 02:04:30 mwilber Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -96,6 +96,8 @@ #define THUNDER_SUPPORT #define NEXT_SUPPORT #define LOGLUV_SUPPORT +//#define JPEG_SUPPORT +#define ZIP_SUPPORT #endif /* COMPRESSION_SUPPORT */ /*