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
This commit is contained in:
parent
a3b9d2120f
commit
462cf13ce7
|
@ -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 :
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************/
|
||||
// TIFFTranslator
|
||||
// Written by Michael Wilber, OBOS Translation Kit Team
|
||||
// Write support added by Stephan Aßmus <stippi@yellowbites.com>
|
||||
//
|
||||
// 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#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<int>(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<uint32>(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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
|
|
@ -0,0 +1,446 @@
|
|||
/*****************************************************************************/
|
||||
// TIFFTranslatorSettings
|
||||
// Adopted by Stephan Aßmus, <stippi@yellowbites.com>
|
||||
// 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 <File.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <TranslatorFormats.h>
|
||||
// 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*****************************************************************************/
|
||||
// TIFFTranslatorSettings
|
||||
// Adopted by Stephan Aßmus, <stippi@yellowbites.com>
|
||||
// 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 <Locker.h>
|
||||
#include <Path.h>
|
||||
#include <Message.h>
|
||||
|
||||
#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
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************/
|
||||
// TIFFView
|
||||
// Written by Michael Wilber, OBOS Translation Kit Team
|
||||
// Picking the compression method added by Stephan Aßmus, <stippi@yellowbites.com>
|
||||
//
|
||||
// TIFFView.cpp
|
||||
//
|
||||
|
@ -30,10 +31,35 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "TIFFView.h"
|
||||
#include "TIFFTranslator.h"
|
||||
|
||||
#include <MenuBar.h>
|
||||
#include <MenuField.h>
|
||||
#include <MenuItem.h>
|
||||
#include <PopUpMenu.h>
|
||||
|
||||
#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<int>(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;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************/
|
||||
// TIFFView
|
||||
// Written by Michael Wilber, OBOS Translation Kit Team
|
||||
// Picking the compression method added by Stephan Aßmus, <stippi@yellowbites.com>
|
||||
//
|
||||
// TIFFView.h
|
||||
//
|
||||
|
@ -32,20 +33,35 @@
|
|||
#define TIFFVIEW_H
|
||||
|
||||
#include <View.h>
|
||||
#include <MenuField.h>
|
||||
#include <MenuItem.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue