From f29673f8ae0ce8b4dc60993e83d7f4b759560131 Mon Sep 17 00:00:00 2001 From: Matthew Wilber Date: Mon, 2 Feb 2004 23:55:38 +0000 Subject: [PATCH] Initial check in for Stephan Assmus' SGITranslator git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6472 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/translators/sgitranslator/Jamfile | 16 + .../translators/sgitranslator/SGIImage.cpp | 1049 ++++++++++++++++ .../translators/sgitranslator/SGIImage.h | 138 +++ .../translators/sgitranslator/SGIMain.cpp | 104 ++ .../sgitranslator/SGITranslator.cpp | 1085 +++++++++++++++++ .../translators/sgitranslator/SGITranslator.h | 128 ++ .../sgitranslator/SGITranslatorSettings.cpp | 447 +++++++ .../sgitranslator/SGITranslatorSettings.h | 91 ++ .../translators/sgitranslator/SGIView.cpp | 335 +++++ .../translators/sgitranslator/SGIView.h | 70 ++ .../translators/sgitranslator/SGIWindow.cpp | 71 ++ .../translators/sgitranslator/SGIWindow.h | 50 + 12 files changed, 3584 insertions(+) create mode 100644 src/add-ons/translators/sgitranslator/Jamfile create mode 100644 src/add-ons/translators/sgitranslator/SGIImage.cpp create mode 100644 src/add-ons/translators/sgitranslator/SGIImage.h create mode 100644 src/add-ons/translators/sgitranslator/SGIMain.cpp create mode 100644 src/add-ons/translators/sgitranslator/SGITranslator.cpp create mode 100644 src/add-ons/translators/sgitranslator/SGITranslator.h create mode 100644 src/add-ons/translators/sgitranslator/SGITranslatorSettings.cpp create mode 100644 src/add-ons/translators/sgitranslator/SGITranslatorSettings.h create mode 100644 src/add-ons/translators/sgitranslator/SGIView.cpp create mode 100644 src/add-ons/translators/sgitranslator/SGIView.h create mode 100644 src/add-ons/translators/sgitranslator/SGIWindow.cpp create mode 100644 src/add-ons/translators/sgitranslator/SGIWindow.h diff --git a/src/add-ons/translators/sgitranslator/Jamfile b/src/add-ons/translators/sgitranslator/Jamfile new file mode 100644 index 0000000000..09e331364a --- /dev/null +++ b/src/add-ons/translators/sgitranslator/Jamfile @@ -0,0 +1,16 @@ +SubDir OBOS_TOP src add-ons translators sgitranslator ; + +Translator SGITranslator : + SGIImage.cpp + SGIMain.cpp + SGITranslator.cpp + SGITranslatorSettings.cpp + SGIView.cpp + SGIWindow.cpp ; + +LinkSharedOSLibs SGITranslator : be translation ; + +Package openbeos-translationkit-cvs : + SGITranslator : + boot home config add-ons Translators ; + diff --git a/src/add-ons/translators/sgitranslator/SGIImage.cpp b/src/add-ons/translators/sgitranslator/SGIImage.cpp new file mode 100644 index 0000000000..69476399d8 --- /dev/null +++ b/src/add-ons/translators/sgitranslator/SGIImage.cpp @@ -0,0 +1,1049 @@ +/* + * SGI image file format library routines. + * + * Formed into a class SGIImage, adopted to Be API and modified to use + * BPositionIO, optimizations for buffered reading: + * + * Stephan Aßmus, + * + * Original Copyright as follows: + * + * Copyright 1997-1998 Michael Sweet (mike@easysw.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + + +#include +#include +#include + +#include +#include +#include + +#include "SGIImage.h" + +const char kSGICopyright[] = ""B_UTF8_COPYRIGHT" 1997-1998 Michael Sweet "; + +// constructor +SGIImage::SGIImage() + : fStream(NULL), + fMode(0), + fBytesPerChannel(0), + fCompression(0), + fWidth(0), + fHeight(0), + fChannelCount(0), + fFirstRowOffset(0), + fNextRowOffset(0), + fOffsetTable(NULL), + fLengthTable(NULL), + fARLERow(NULL), + fARLEOffset(0), + fARLELength(0) +{ +} + +// destructor +SGIImage::~SGIImage() +{ + Unset(); +} + +// InitCheck +status_t +SGIImage::InitCheck() const +{ + if (fStream) + return B_OK; + return B_NO_INIT; +} + +// SetTo +// open an SGI image file for reading +// +// stream the input stream +status_t +SGIImage::SetTo(BPositionIO* stream) +{ + if (!stream) + return B_BAD_VALUE; + + fStream = stream; + stream->Seek(0, SEEK_SET); + + int16 magic = _ReadShort(); + if (magic != SGI_MAGIC) { + fStream = NULL; + return B_NO_TRANSLATOR; + } + + fMode = SGI_READ; + + fCompression = _ReadChar(); + fBytesPerChannel = _ReadChar(); + _ReadShort(); // Dimensions + fWidth = _ReadShort(); + fHeight = _ReadShort(); + fChannelCount = _ReadShort(); +// _ReadLong(); // Minimum pixel +// _ReadLong(); // Maximum pixel + + if (fCompression) { + // this stream is compressed; read the scanline tables... + + fStream->Seek(512, SEEK_SET); + + fOffsetTable = (int32**)calloc(fChannelCount, sizeof(int32*)); + fOffsetTable[0] = (int32*)calloc(fHeight * fChannelCount, sizeof(int32)); + for (uint32 i = 1; i < fChannelCount; i++) + fOffsetTable[i] = fOffsetTable[0] + i * fHeight; + + for (uint32 i = 0; i < fChannelCount; i++) + for (uint16 j = 0; j < fHeight; j++) + fOffsetTable[i][j] = _ReadLong(); + + fLengthTable = (int32**)calloc(fChannelCount, sizeof(int32*)); + fLengthTable[0] = (int32*)calloc(fHeight * fChannelCount, sizeof(int32)); + + for (int32 i = 1; i < fChannelCount; i ++) + fLengthTable[i] = fLengthTable[0] + i * fHeight; + + for (uint32 i = 0; i < fChannelCount; i++) + for (uint16 j = 0; j < fHeight; j++) + fLengthTable[i][j] = _ReadLong(); + + } + return B_OK; +} + +// SetTo +// open an SGI image file for writing +// +// stream the output stream +// width number of pixels in a row +// height number of rows +// channels number of channels per pixel +// bytesPerChannel number of bytes per channel +// compression compression mode +status_t +SGIImage::SetTo(BPositionIO* stream, + uint16 width, uint16 height, + uint16 channels, uint32 bytesPerChannel, + uint32 compression) +{ + // sanity checks + if (!stream || + width < 1 || height < 1 || channels < 1 || + bytesPerChannel < 1 || bytesPerChannel > 2 || + compression < SGI_COMP_NONE || compression > SGI_COMP_ARLE) + return B_BAD_VALUE; + + fStream = stream; + fMode = SGI_WRITE; + + _WriteShort(SGI_MAGIC); + _WriteChar((fCompression = compression) != 0); + _WriteChar(fBytesPerChannel = bytesPerChannel); + _WriteShort(3); // Dimensions + _WriteShort(fWidth = width); + _WriteShort(fHeight = height); + _WriteShort(fChannelCount = channels); + + if (fBytesPerChannel == 1) { + _WriteLong(0); // Minimum pixel + _WriteLong(255); // Maximum pixel + } else { + _WriteLong(-32768); // Minimum pixel + _WriteLong(32767); // Maximum pixel + } + _WriteLong(0); // Reserved + + char name[80]; // Name of file in image header + memset(name, 0, sizeof(name)); + sprintf(name, "OpenBeOS SGITranslator"); + fStream->Write(name, sizeof(name)); + + // fill the rest of the image header with zeros + for (int32 i = 0; i < 102; i++) + _WriteLong(0); + + switch (fCompression) { + case SGI_COMP_NONE : // No compression + // This file is uncompressed. To avoid problems with + // sparse files, we need to write blank pixels for the + // entire image... + +/* if (fBytesPerChannel == 1) { + for (int32 i = fWidth * fHeight * fChannelCount; i > 0; i --) + _WriteChar(0); + } else { + for (int32 i = fWidth * fHeight * fChannelCount; i > 0; i --) + _WriteShort(0); + }*/ + break; + + case SGI_COMP_ARLE: // Aggressive RLE + fARLERow = (uint16*)calloc(fWidth, sizeof(uint16)); + fARLEOffset = 0; + // FALL THROUGH + case SGI_COMP_RLE : // Run-Length Encoding + // This file is compressed; write the (blank) scanline tables... + +// for (int32 i = 2 * fHeight * fChannelCount; i > 0; i--) +// _WriteLong(0); +fStream->Seek(2 * fHeight * fChannelCount * sizeof(int32), SEEK_CUR); + + fFirstRowOffset = fStream->Position(); + fNextRowOffset = fStream->Position(); + + // allocate and read offset table + fOffsetTable = (int32**)calloc(fChannelCount, sizeof(int32*)); + fOffsetTable[0] = (int32*)calloc(fHeight * fChannelCount, sizeof(int32)); + + for (int32 i = 1; i < fChannelCount; i ++) + fOffsetTable[i] = fOffsetTable[0] + i * fHeight; + + // allocate and read length table + fLengthTable = (int32**)calloc(fChannelCount, sizeof(int32*)); + fLengthTable[0] = (int32*)calloc(fHeight * fChannelCount, sizeof(int32)); + + for (int32 i = 1; i < fChannelCount; i ++) + fLengthTable[i] = fLengthTable[0] + i * fHeight; + break; + } + return B_OK; +} + +// Unset +// +// if in write mode, writes final information to the stream +status_t +SGIImage::Unset() +{ + status_t ret = InitCheck(); // return status + if (ret >= B_OK) { + + if (fMode == SGI_WRITE && fCompression != SGI_COMP_NONE) { + // write the scanline offset table to the file... + + fStream->Seek(512, SEEK_SET); + +/* off_t* offset = fOffsetTable[0]; + for (int32 i = fHeight * fChannelCount; i > 0; i--) { + if ((ret = _WriteLong(offset[0])) < B_OK) + break; + offset++; + }*/ + +int32 size = fHeight * fChannelCount * sizeof(int32); +swap_data(B_INT32_TYPE, fOffsetTable[0], size, B_SWAP_HOST_TO_BENDIAN); +ret = fStream->Write(fOffsetTable[0], size); + + if (ret >= B_OK) { + +/* int32* length = fLengthTable[0]; + for (int32 i = fHeight * fChannelCount; i > 0; i--) { + if ((ret = _WriteLong(length[0])) < B_OK) + break; + length++; + }*/ + +swap_data(B_INT32_TYPE, fLengthTable[0], size, B_SWAP_HOST_TO_BENDIAN); +ret = fStream->Write(fLengthTable[0], size); + + } + } + + if (fOffsetTable != NULL) { + free(fOffsetTable[0]); + free(fOffsetTable); + fOffsetTable = NULL; + } + + if (fLengthTable != NULL) { + free(fLengthTable[0]); + free(fLengthTable); + fLengthTable = NULL; + } + + if (fARLERow) { + free(fARLERow); + fARLERow = NULL; + } + + fStream = NULL; + } + return ret; +} + +// ReadRow +// +// reads a row of image data from the stream +// +// row pointer to buffer (row of pixels) to read +// y index (line number) of this row +// z which channel to read +status_t +SGIImage::ReadRow(void* row, int32 y, int32 z) +{ + // sanitiy checks + if (row == NULL || + y < 0 || y >= fHeight || + z < 0 || z >= fChannelCount) + return B_BAD_VALUE; + + + status_t ret = B_ERROR; + + switch (fCompression) { + case SGI_COMP_NONE: { + // seek to the image row + // optimize buffering by only seeking if necessary... + + off_t offset = 512 + (y + z * fHeight) * fWidth * fBytesPerChannel; + fStream->Seek(offset, SEEK_SET); + + uint32 bytes = fWidth * fBytesPerChannel; +//printf("reading %ld bytes 8 Bit uncompressed row: %ld, channel: %ld\n", bytes, y, z); + ret = fStream->Read(row, bytes); + + break; + } + case SGI_COMP_RLE: { + int32 offset = fOffsetTable[z][y]; + int32 rleLength = fLengthTable[z][y]; + fStream->Seek(offset, SEEK_SET); + uint8* rleBuffer = new uint8[rleLength]; + fStream->Read(rleBuffer, rleLength); + + if (fBytesPerChannel == 1) { +//printf("reading 8 Bit RLE compressed row: %ld, channel: %ld\n", y, z); +// ret = _ReadRLE8((uint8*)row, fWidth); + ret = _ReadRLE8((uint8*)row, rleBuffer, fWidth); + } else { +//printf("reading 16 Bit RLE compressed row: %ld, channel: %ld\n", y, z); +// ret = _ReadRLE16((uint16*)row, fWidth); + if ((ret = swap_data(B_INT16_TYPE, rleBuffer, rleLength, B_SWAP_BENDIAN_TO_HOST)) >= B_OK) + ret = _ReadRLE16((uint16*)row, (uint16*)rleBuffer, fWidth); + } + delete[] rleBuffer; + break; + } + } + return ret; +} + +// WriteRow +// +// writes a row of image data to the stream +// +// row pointer to buffer (row of pixels) to write +// y index (line number) of this row +// z which channel to write +status_t +SGIImage::WriteRow(void* row, int32 y, int32 z) +{ + // sanitiy checks + if (row == NULL || + y < 0 || y >= fHeight || + z < 0 || z >= fChannelCount) + return B_BAD_VALUE; + + int32 x; // x coordinate + int32 offset; // stream offset + + status_t ret = B_ERROR; + + switch (fCompression) { + case SGI_COMP_NONE: { + // Seek to the image row + + offset = 512 + (y + z * fHeight) * fWidth * fBytesPerChannel; + fStream->Seek(offset, SEEK_SET); + + uint32 bytes = fWidth * fBytesPerChannel; +//printf("writing %ld bytes %ld byte/channel uncompressed row: %ld, channel: %ld\n", bytes, fBytesPerChannel, y, z); + ret = fStream->Write(row, bytes); +/* if (fBytesPerChannel == 1) { + for (x = fWidth; x > 0; x--) { + _WriteChar(*row); + row++; + } + } else { + for (x = fWidth; x > 0; x--) { + _WriteShort(*row); + row++; + } + }*/ + break; + } + case SGI_COMP_ARLE: + if (fOffsetTable[z][y] != 0) + return B_ERROR; + + // First check the last row written... + + if (fARLEOffset > 0) { + if (fBytesPerChannel == 1) { + uint8* arleRow = (uint8*)fARLERow; + uint8* src = (uint8*)row; + for (x = 0; x < fWidth; x++) + if (*src++ != *arleRow++) + break; + } else { + uint16* arleRow = (uint16*)fARLERow; + uint16* src = (uint16*)row; + for (x = 0; x < fWidth; x++) + if (*src++ != *arleRow++) + break; + } + + if (x == fWidth) { + fOffsetTable[z][y] = fARLEOffset; + fLengthTable[z][y] = fARLELength; + return B_OK; + } + } + + // If that didn't match, search all the previous rows... + + fStream->Seek(fFirstRowOffset, SEEK_SET); + + if (fBytesPerChannel == 1) { + do { + fARLEOffset = fStream->Position(); + + uint8* arleRow = (uint8*)fARLERow; + if ((fARLELength = _ReadRLE8(arleRow, fWidth)) < B_OK) { + x = 0; + break; + } + + uint8* src = (uint8*)row; + for (x = 0; x < fWidth; x++) + if (*src++ != *arleRow++) + break; + } while (x < fWidth); + } else { + do { + fARLEOffset = fStream->Position(); + + uint16* arleRow = (uint16*)fARLERow; + if ((fARLELength = _ReadRLE16(arleRow, fWidth)) < B_OK) { + x = 0; + break; + } + + uint16* src = (uint16*)row; + for (x = 0; x < fWidth; x++) + if (*src++ != *arleRow++) + break; + } while (x < fWidth); + } + + if (x == fWidth) { + fOffsetTable[z][y] = fARLEOffset; + fLengthTable[z][y] = fARLELength; + return B_OK; + } else + fStream->Seek(0, SEEK_END); // seek to end of stream + // FALL THROUGH! + case SGI_COMP_RLE : + if (fOffsetTable[z][y] != 0) + return B_ERROR; + + offset = fOffsetTable[z][y] = fNextRowOffset; + + if (offset != fStream->Position()) + fStream->Seek(offset, SEEK_SET); + +//printf("writing %d pixels %ld byte/channel RLE row: %ld, channel: %ld\n", fWidth, fBytesPerChannel, y, z); + + if (fBytesPerChannel == 1) + x = _WriteRLE8((uint8*)row, fWidth); + else + x = _WriteRLE16((uint16*)row, fWidth); + + if (fCompression == SGI_COMP_ARLE) { + fARLEOffset = offset; + fARLELength = x; + memcpy(fARLERow, row, fWidth * fBytesPerChannel); + } + + fNextRowOffset = fStream->Position(); + fLengthTable[z][y] = x; + + return x; + default: + break; + } + + return ret; +} + +// _ReadLong +// +// reads 4 bytes from the stream and +// returns a 32-bit big-endian integer +int32 +SGIImage::_ReadLong() const +{ + int32 n; + if (fStream->Read(&n, 4) == 4) { + return B_BENDIAN_TO_HOST_INT32(n); + } else + return 0; +} + +// _ReadShort +// +// reads 2 bytes from the stream and +// returns a 16-bit big-endian integer +int16 +SGIImage::_ReadShort() const +{ + int16 n; + if (fStream->Read(&n, 2) == 2) { + return B_BENDIAN_TO_HOST_INT16(n); + } else + return 0; +} + +// _ReadChar +// +// reads 1 byte from the stream and +// returns it +int8 +SGIImage::_ReadChar() const +{ + int8 b; + ssize_t read = fStream->Read(&b, 1); + if (read == 1) + return b; + else if (read < B_OK) + return (int8)read; + return (int8)B_ERROR; +} + +// _WriteLong +// +// writes a 32-bit big-endian integer to the stream +status_t +SGIImage::_WriteLong(int32 n) const +{ + int32 bigN = B_HOST_TO_BENDIAN_INT32(n); + ssize_t written = fStream->Write(&bigN, sizeof(int32)); + if (written == sizeof(int32)) + return B_OK; + if (written < B_OK) + return written; + return B_ERROR; +} + +// _WriteShort +// +// writes a 16-bit big-endian integer to the stream +status_t +SGIImage::_WriteShort(uint16 n) const +{ + uint16 bigN = B_HOST_TO_BENDIAN_INT16(n); + ssize_t written = fStream->Write(&bigN, sizeof(uint16)); + if (written == sizeof(uint16)) + return B_OK; + if (written < B_OK) + return written; + return B_ERROR; +} + +// _WriteChar +// +// writes one byte to the stream +status_t +SGIImage::_WriteChar(int8 n) const +{ + ssize_t written = fStream->Write(&n, sizeof(int8)); + if (written == sizeof(int8)) + return B_OK; + if (written < B_OK) + return written; + return B_ERROR; +} + +// _ReadRLE8 +// +// reads 8-bit RLE data into provided buffer +// +// row pointer to buffer for one row +// numPixels number of pixels that fit into row buffer +ssize_t +SGIImage::_ReadRLE8(uint8* row, int32 numPixels) const +{ + int32 ch; // current charater + uint32 count; // RLE count + uint32 length = 0; // number of bytes read + + uint32 bufferSize = 1024; + uint8* buffer = new uint8[bufferSize]; + uint32 bufferPos = bufferSize; + + status_t ret = B_OK; + + while (numPixels > 0) { + + // fetch another buffer if we need to + if (bufferPos >= bufferSize) { + ret = fStream->Read(buffer, bufferSize); + if (ret < B_OK) + break; + else + bufferPos = 0; + } + + ch = buffer[bufferPos ++]; + length ++; + + count = ch & 127; + if (count == 0) + break; + + if (ch & 128) { + for (uint32 i = 0; i < count; i++) { + + // fetch another buffer if we need to + if (bufferPos >= bufferSize) { + ret = fStream->Read(buffer, bufferSize); + if (ret < B_OK) { + delete[] buffer; + return ret; + } else + bufferPos = 0; + } + + *row = buffer[bufferPos ++]; + row ++; + numPixels --; + length ++; + } + } else { + + // fetch another buffer if we need to + if (bufferPos >= bufferSize) { + ret = fStream->Read(buffer, bufferSize); + if (ret < B_OK) { + delete[] buffer; + return ret; + } else + bufferPos = 0; + } + + ch = buffer[bufferPos ++]; + length ++; + for (uint32 i = 0; i < count; i++) { + *row = ch; + row ++; + numPixels --; + } + } + } + delete[] buffer; + + return (numPixels > 0 ? ret : length); +} + +// _ReadRLE8 +// +// reads 8-bit RLE data into provided buffer +// +// row pointer to buffer for one row +// numPixels number of pixels that fit into row buffer +ssize_t +SGIImage::_ReadRLE8(uint8* row, uint8* rleBuffer, int32 numPixels) const +{ + int32 ch; // current charater + uint32 count; // RLE count + uint32 length = 0; // number of bytes read + + while (numPixels > 0) { + + ch = *rleBuffer ++; + length ++; + + count = ch & 127; + if (count == 0) + break; + + if (ch & 128) { + for (uint32 i = 0; i < count; i++) { + + *row = *rleBuffer ++; + row ++; + numPixels --; + length ++; + } + } else { + + ch = *rleBuffer ++; + length ++; + for (uint32 i = 0; i < count; i++) { + *row = ch; + row ++; + numPixels --; + } + } + } + + return (numPixels > 0 ? B_ERROR : length); +} +/*ssize_t +SGIImage::_ReadRLE8(uint8* row, int32 numPixels) const +{ + int32 ch; // current charater + uint32 count; // RLE count + uint32 length = 0; // number of bytes read + + while (numPixels > 0) { + ch = _ReadChar(); + length ++; + + count = ch & 127; + if (count == 0) + break; + + if (ch & 128) { + for (uint32 i = 0; i < count; i++) { + *row = _ReadChar(); + row ++; + numPixels --; + length ++; + } + } else { + ch = _ReadChar(); + length ++; + for (uint32 i = 0; i < count; i++) { + *row = ch; + row ++; + numPixels --; + } + } + } + return (numPixels > 0 ? B_ERROR : length); +}*/ + +// read_and_swap +status_t +read_and_swap(BPositionIO* stream, int16* buffer, uint32 size) +{ + status_t ret = stream->Read(buffer, size); + if (ret >= B_OK) + return swap_data(B_INT16_TYPE, buffer, ret, B_SWAP_BENDIAN_TO_HOST); + return ret; +} + +// _ReadRLE16 +// +// reads 16-bit RLE data into provided buffer +// +// row pointer to buffer for one row +// numPixels number of pixels that fit into row buffer +ssize_t +SGIImage::_ReadRLE16(uint16* row, int32 numPixels) const +{ + int32 ch; // current character + uint32 count; // RLE count + uint32 length = 0; // number of bytes read... + + uint32 bufferSize = 1024; + int16* buffer = new int16[bufferSize]; + uint32 bufferPos = bufferSize; + status_t ret = B_OK; + + while (numPixels > 0) { + + // fetch another buffer if we need to + if (bufferPos >= bufferSize) { + ret = read_and_swap(fStream, buffer, bufferSize * 2); + if (ret < B_OK) + break; + bufferPos = 0; + } + + ch = buffer[bufferPos ++]; + length ++; + + count = ch & 127; + if (count == 0) + break; + + if (ch & 128) { + for (uint32 i = 0; i < count; i++) { + + // fetch another buffer if we need to + if (bufferPos >= bufferSize) { + ret = read_and_swap(fStream, buffer, bufferSize * 2); + if (ret < B_OK) { + delete[] buffer; + return ret; + } else + bufferPos = 0; + } + + *row = B_HOST_TO_BENDIAN_INT16(buffer[bufferPos ++]); + row++; + numPixels--; + length++; + } + } else { + + // fetch another buffer if we need to + if (bufferPos >= bufferSize) { + ret = read_and_swap(fStream, buffer, bufferSize * 2); + if (ret < B_OK) { + delete[] buffer; + return ret; + } else + bufferPos = 0; + } + + ch = B_HOST_TO_BENDIAN_INT16(buffer[bufferPos ++]); + length ++; + for (uint32 i = 0; i < count; i++) { + *row = ch; + row++; + numPixels--; + } + } + } + delete[] buffer; + return (numPixels > 0 ? ret : length * 2); +} + +// _ReadRLE16 +// +// reads 16-bit RLE data into provided buffer +// +// row pointer to buffer for one row +// numPixels number of pixels that fit into row buffer +ssize_t +SGIImage::_ReadRLE16(uint16* row, uint16* rleBuffer, int32 numPixels) const +{ + int32 ch; // current character + uint32 count; // RLE count + uint32 length = 0; // number of bytes read... + + while (numPixels > 0) { + + ch = *rleBuffer ++; + length ++; + + count = ch & 127; + if (count == 0) + break; + + if (ch & 128) { + for (uint32 i = 0; i < count; i++) { + + *row = B_HOST_TO_BENDIAN_INT16(*rleBuffer ++); + row++; + numPixels--; + length++; + } + } else { + + ch = B_HOST_TO_BENDIAN_INT16(*rleBuffer ++); + length ++; + for (uint32 i = 0; i < count; i++) { + *row = ch; + row++; + numPixels--; + } + } + } + return (numPixels > 0 ? B_ERROR : length * 2); +} + +// _WriteRLE8 +// +// writes 8-bit RLE data into the stream +// +// row pointer to buffer for one row +// numPixels number of pixels that fit into row buffer +ssize_t +SGIImage::_WriteRLE8(uint8* row, int32 numPixels) const +{ + int32 length = 0; // length of output line + int32 count; // number of repeated/non-repeated pixels + int32 i; // looping var + uint8* start; // start of sequence + uint16 repeat; // repeated pixel + + + for (int32 x = numPixels; x > 0;) { + start = row; + row += 2; + x -= 2; + + while (x > 0 && (row[-2] != row[-1] || row[-1] != row[0])) { + row++; + x--; + } + + row -= 2; + x += 2; + + count = row - start; + while (count > 0) { + i = count > 126 ? 126 : count; + count -= i; + + if (_WriteChar(128 | i) == EOF) + return EOF; + length ++; + + while (i > 0) { + if (_WriteChar(*start) == EOF) + return EOF; + start ++; + i --; + length ++; + } + } + + if (x <= 0) + break; + + start = row; + repeat = row[0]; + + row ++; + x --; + + while (x > 0 && *row == repeat) { + row ++; + x --; + } + + count = row - start; + while (count > 0) { + i = count > 126 ? 126 : count; + count -= i; + + if (_WriteChar(i) == EOF) + return EOF; + length ++; + + if (_WriteChar(repeat) == EOF) + return (-1); + length ++; + } + } + + length ++; + + if (_WriteChar(0) == EOF) + return EOF; + else + return length; +} + + +// _WriteRLE16 +// +// writes 16-bit RLE data into the stream +// +// row pointer to buffer for one row +// numPixels number of pixels that fit into row buffer +ssize_t +SGIImage::_WriteRLE16(uint16* row, int32 numPixels) const +{ + int32 length = 0; // length of output line + int32 count; // number of repeated/non-repeated pixels + int32 i; // looping var + int32 x; // looping var + uint16* start; // start of sequence + uint16 repeat; // repeated pixel + + + for (x = numPixels; x > 0;) { + start = row; + row += 2; + x -= 2; + + while (x > 0 && (row[-2] != row[-1] || row[-1] != row[0])) { + row ++; + x --; + } + + row -= 2; + x += 2; + + count = row - start; + while (count > 0) { + i = count > 126 ? 126 : count; + count -= i; + + if (_WriteShort(128 | i) == EOF) + return EOF; + length ++; + + while (i > 0) { + if (_WriteShort(*start) == EOF) + return EOF; + start ++; + i --; + length ++; + } + } + + if (x <= 0) + break; + + start = row; + repeat = row[0]; + + row ++; + x --; + + while (x > 0 && *row == repeat) { + row ++; + x --; + } + + count = row - start; + while (count > 0) { + i = count > 126 ? 126 : count; + count -= i; + + if (_WriteShort(i) == EOF) + return EOF; + length ++; + + if (_WriteShort(repeat) == EOF) + return EOF; + length ++; + } + } + + length ++; + + if (_WriteShort(0) == EOF) + return EOF; + else + return (2 * length); +} + + diff --git a/src/add-ons/translators/sgitranslator/SGIImage.h b/src/add-ons/translators/sgitranslator/SGIImage.h new file mode 100644 index 0000000000..88893431f4 --- /dev/null +++ b/src/add-ons/translators/sgitranslator/SGIImage.h @@ -0,0 +1,138 @@ +/* + * "$Id: SGIImage.h,v 1.1 2004/02/02 23:55:38 mwilber Exp $" + * + * SGI image file format library definitions. + * + * Copyright 1997-1998 Michael Sweet (mike@easysw.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Revision History: + * + * $Log: SGIImage.h,v $ + * Revision 1.1 2004/02/02 23:55:38 mwilber + * Initial check in for Stephan Assmus' SGITranslator + * + * Revision 1.5 1998/05/17 16:01:33 mike + * Added header file. + * + * Revision 1.4 1998/04/23 17:40:49 mike + * Updated to support 16-bit image data. + * + * Revision 1.3 1998/02/05 17:10:58 mike + * Added sgiOpenFile() function for opening an existing file pointer. + * + * Revision 1.2 1997/06/18 00:55:28 mike + * Updated to hold length table when writing. + * Updated to hold current length when doing ARLE. + * + * Revision 1.1 1997/06/15 03:37:19 mike + * Initial revision + */ + +#ifndef SGI_IMAGE_H +#define SGI_IMAGE_H + +#include +#include + +#define SGI_MAGIC 474 // magic number in image file + +#define SGI_READ 0 // read from an SGI image file +#define SGI_WRITE 1 // write to an SGI image file + +#define SGI_COMP_NONE 0 // no compression +#define SGI_COMP_RLE 1 // run-length encoding +#define SGI_COMP_ARLE 2 // agressive run-length encoding + +extern const char kSGICopyright[]; + +class SGIImage { + public: + SGIImage(); + virtual ~SGIImage(); + + // not really necessary, SetTo() will return an error anyways + status_t InitCheck() const; + + // first version -> read from an existing sgi image in stream + status_t SetTo(BPositionIO* stream); + // second version -> set up a stream for writing an sgi image; + // when SetTo() returns, the image header will have been written + // already + status_t SetTo(BPositionIO* stream, + uint16 width, uint16 height, + uint16 channels, uint32 bytesPerChannel, + uint32 compression); + // has to be called if writing, writes final information to the stream + status_t Unset(); + + // access to each row of image data + status_t ReadRow(void* row, int32 lineNum, int32 channel); + // write one row of image data + // right now, could be used to modify an image in place, but only + // if dealing with uncompressed data, compressed data is currently + // not supported + status_t WriteRow(void* row, int32 lineNum, int32 channel); + + // access to the attributes of the sgi image + uint16 Width() const + { return fWidth; } + uint16 Height() const + { return fHeight; } + uint32 BytesPerChannel() const + { return fBytesPerChannel; } + uint32 CountChannels() const + { return fChannelCount; } + + private: + int32 _ReadLong() const; + int16 _ReadShort() const; + int8 _ReadChar() const; + status_t _WriteLong(int32 n) const; + status_t _WriteShort(uint16 n) const; + status_t _WriteChar(int8 n) const; + + ssize_t _ReadRLE8(uint8* row, int32 numPixels) const; + ssize_t _ReadRLE8(uint8* row, uint8* rleBuffer, int32 numPixels) const; + ssize_t _ReadRLE16(uint16* row, int32 numPixels) const; + ssize_t _ReadRLE16(uint16* row, uint16* rleBuffer, int32 numPixels) const; + ssize_t _WriteRLE8(uint8* row, int32 numPixels) const; + ssize_t _WriteRLE16(uint16* row, int32 numPixels) const; + + + BPositionIO* fStream; + + uint32 fMode; // reading or writing + uint32 fBytesPerChannel; + uint32 fCompression; + + uint16 fWidth; // in number of pixels + uint16 fHeight; // in number of pixels + uint16 fChannelCount; + + off_t fFirstRowOffset; // offset into stream + off_t fNextRowOffset; // offset into stream + + int32** fOffsetTable; // offset table for compression + int32** fLengthTable; // length table for compression + + uint16* fARLERow; // advanced RLE compression buffer + int32 fARLEOffset; // advanced RLE buffer offset + int32 fARLELength; // advanced RLE buffer length +}; + +#endif // SGI_IMAGE_H + diff --git a/src/add-ons/translators/sgitranslator/SGIMain.cpp b/src/add-ons/translators/sgitranslator/SGIMain.cpp new file mode 100644 index 0000000000..8e510f4477 --- /dev/null +++ b/src/add-ons/translators/sgitranslator/SGIMain.cpp @@ -0,0 +1,104 @@ +/*****************************************************************************/ +// SGITranslator +// Adopted by Stephan Aßmus, +// from TIFFMain written by +// Michael Wilber, OBOS Translation Kit Team +// +// Version: +// +// This translator opens and writes SGI images. +// +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2003 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#include +#include +#include +#include "SGITranslator.h" +#include "SGIWindow.h" +#include "SGIView.h" + +// --------------------------------------------------------------- +// main +// +// Creates a BWindow for displaying info about the SGITranslator +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +int +main() +{ + BApplication app("application/x-vnd.obos-sgi-translator"); + SGITranslator *ptranslator = new SGITranslator; + BView *view = NULL; + BRect rect(0, 0, 225, 175); + if (ptranslator->MakeConfigurationView(NULL, &view, &rect)) { + BAlert *err = new BAlert("Error", + "Unable to create the SGITranslator view.", "OK"); + err->Go(); + return 1; + } + // release the translator even though I never really used it anyway + ptranslator->Release(); + ptranslator = NULL; + + SGIWindow *wnd = new SGIWindow(rect); + view->ResizeTo(rect.Width(), rect.Height()); + wnd->AddChild(view); + BPoint wndpt = B_ORIGIN; + { + BScreen scrn; + BRect frame = scrn.Frame(); + frame.InsetBy(10, 23); + // if the point is outside of the screen frame, + // use the mouse location to find a better point + if (!frame.Contains(wndpt)) { + uint32 dummy; + view->GetMouse(&wndpt, &dummy, false); + wndpt.x -= rect.Width() / 2; + wndpt.y -= rect.Height() / 2; + // clamp location to screen + if (wndpt.x < frame.left) + wndpt.x = frame.left; + if (wndpt.y < frame.top) + wndpt.y = frame.top; + if (wndpt.x > frame.right) + wndpt.x = frame.right; + if (wndpt.y > frame.bottom) + wndpt.y = frame.bottom; + } + } + wnd->MoveTo(wndpt); + wnd->Show(); + app.Run(); + return 0; +} diff --git a/src/add-ons/translators/sgitranslator/SGITranslator.cpp b/src/add-ons/translators/sgitranslator/SGITranslator.cpp new file mode 100644 index 0000000000..3d3e21ed67 --- /dev/null +++ b/src/add-ons/translators/sgitranslator/SGITranslator.cpp @@ -0,0 +1,1085 @@ +/*****************************************************************************/ +// SGITranslator +// Written by Stephan Aßmus +// based on TIFFTranslator written mostly by +// Michael Wilber, OBOS Translation Kit Team +// +// SGITranslator.cpp +// +// This BTranslator based object is for opening and writing +// SGI images. +// +// +// Copyright (c) 2003 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. +/*****************************************************************************/ +// +// How this works: +// +// libtiff has a special version of SGIOpen() 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 SGI* handle that is +// returned by SGIOpen(), libtiff uses the special reading writing etc +// functions so that all stream io happens on the BPositionIO object. + +#include +#include +#include + +#include + +#include "SGIImage.h" +#include "SGITranslator.h" +#include "SGITranslatorSettings.h" +#include "SGIView.h" + +// The input formats that this translator supports. +translation_format gInputFormats[] = { + { + B_TRANSLATOR_BITMAP, + B_TRANSLATOR_BITMAP, + BBT_IN_QUALITY, + BBT_IN_CAPABILITY, + "image/x-be-bitmap", + "Be Bitmap Format (SGITranslator)" + }, + { + SGI_FORMAT, + B_TRANSLATOR_BITMAP, + SGI_IN_QUALITY, + SGI_IN_CAPABILITY, + "image/sgi", + "SGI image" + } +}; + +// The output formats that this translator supports. +translation_format gOutputFormats[] = { + { + B_TRANSLATOR_BITMAP, + B_TRANSLATOR_BITMAP, + BBT_OUT_QUALITY, + BBT_OUT_CAPABILITY, + "image/x-be-bitmap", + "Be Bitmap Format (SGITranslator)" + }, + { + SGI_FORMAT, + B_TRANSLATOR_BITMAP, + SGI_OUT_QUALITY, + SGI_OUT_CAPABILITY, + "image/sgi", + "SGI image" + } +}; + +// --------------------------------------------------------------- +// make_nth_translator +// +// Creates a SGITranslator object to be used by BTranslatorRoster +// +// Preconditions: +// +// Parameters: n, The translator to return. Since +// SGITranslator only publishes one +// translator, it only returns a +// SGITranslator if n == 0 +// +// you, The image_id of the add-on that +// contains code (not used). +// +// flags, Has no meaning yet, should be 0. +// +// Postconditions: +// +// Returns: NULL if n is not zero, +// a new SGITranslator if n is zero +// --------------------------------------------------------------- +BTranslator * +make_nth_translator(int32 n, image_id you, uint32 flags, ...) +{ + if (!n) + return new SGITranslator(); + else + return NULL; +} + +// --------------------------------------------------------------- +// Constructor +// +// Sets up the version info and the name of the translator so that +// these values can be returned when they are requested. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +SGITranslator::SGITranslator() + : BTranslator(), + fSettings(new SGITranslatorSettings()) +{ + fSettings->LoadSettings(); + // load settings from the SGI Translator settings file + + strcpy(fName, "SGI Images"); + sprintf(fInfo, "SGI image translator v%d.%d.%d %s", + SGI_TRANSLATOR_VERSION / 100, (SGI_TRANSLATOR_VERSION / 10) % 10, + SGI_TRANSLATOR_VERSION % 10, __DATE__); +} + +// --------------------------------------------------------------- +// Destructor +// +// releases the settings object +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +SGITranslator::~SGITranslator() +{ + fSettings->Release(); +} + +// --------------------------------------------------------------- +// TranslatorName +// +// Returns the short name of the translator. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: a const char * to the short name of the translator +// --------------------------------------------------------------- +const char * +SGITranslator::TranslatorName() const +{ + return fName; +} + +// --------------------------------------------------------------- +// TranslatorInfo +// +// Returns a more verbose name for the translator than the one +// TranslatorName() returns. This usually includes version info. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: a const char * to the verbose name of the translator +// --------------------------------------------------------------- +const char * +SGITranslator::TranslatorInfo() const +{ + return fInfo; +} + +// --------------------------------------------------------------- +// TranslatorVersion +// +// Returns the integer representation of the current version of +// this translator. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +int32 +SGITranslator::TranslatorVersion() const +{ + return SGI_TRANSLATOR_VERSION; +} + +// --------------------------------------------------------------- +// InputFormats +// +// Returns a list of input formats supported by this translator. +// +// Preconditions: +// +// Parameters: out_count, The number of input formats +// support is returned here. +// +// Postconditions: +// +// Returns: the list of input formats and the number of input +// formats through the out_count parameter, if out_count is NULL, +// NULL is returned +// --------------------------------------------------------------- +const translation_format * +SGITranslator::InputFormats(int32 *out_count) const +{ + if (out_count) { + *out_count = sizeof(gInputFormats) / + sizeof(translation_format); + return gInputFormats; + } else + return NULL; +} + +// --------------------------------------------------------------- +// OutputFormats +// +// Returns a list of output formats supported by this translator. +// +// Preconditions: +// +// Parameters: out_count, The number of output formats +// support is returned here. +// +// Postconditions: +// +// Returns: the list of output formats and the number of output +// formats through the out_count parameter, if out_count is NULL, +// NULL is returned +// --------------------------------------------------------------- +const translation_format * +SGITranslator::OutputFormats(int32 *out_count) const +{ + if (out_count) { + *out_count = sizeof(gOutputFormats) / + sizeof(translation_format); + return gOutputFormats; + } else + return NULL; +} + +// --------------------------------------------------------------- +// identify_bits_header +// +// Determines if the data in inSource is in the +// B_TRANSLATOR_BITMAP ('bits') format. If it is, it returns +// info about the data in inSource to outInfo and pheader. +// +// Preconditions: +// +// Parameters: inSource, The source of the image data +// +// outInfo, Information about the translator +// is copied here +// +// amtread, Amount of data read from inSource +// before this function was called +// +// read, Pointer to the data that was read +// in before this function was called +// +// pheader, The bits header is copied here after +// it is read in from inSource +// +// Postconditions: +// +// Returns: B_NO_TRANSLATOR, if the data does not look like +// bits format data +// +// B_ERROR, if the header data could not be converted to host +// format +// +// B_OK, if the data looks like bits data and no errors were +// encountered +// --------------------------------------------------------------- +status_t +identify_bits_header(BPositionIO *inSource, translator_info *outInfo, + ssize_t amtread, uint8 *read, TranslatorBitmap *pheader = NULL) +{ + TranslatorBitmap header; + + memcpy(&header, read, amtread); + // copy portion of header already read in + // read in the rest of the header + ssize_t size = sizeof(TranslatorBitmap) - amtread; + if (inSource->Read( + (reinterpret_cast (&header)) + amtread, size) != size) + return B_NO_TRANSLATOR; + + // convert to host byte order + if (swap_data(B_UINT32_TYPE, &header, sizeof(TranslatorBitmap), + B_SWAP_BENDIAN_TO_HOST) != B_OK) + return B_ERROR; + +// TODO: supress unwanted colorspaces here already? + // check if header values are reasonable + if (header.colors != B_RGB32 && + header.colors != B_RGB32_BIG && + header.colors != B_RGBA32 && + header.colors != B_RGBA32_BIG && + header.colors != B_RGB24 && + header.colors != B_RGB24_BIG && + header.colors != B_RGB16 && + header.colors != B_RGB16_BIG && + header.colors != B_RGB15 && + header.colors != B_RGB15_BIG && + header.colors != B_RGBA15 && + header.colors != B_RGBA15_BIG && + header.colors != B_CMAP8 && + header.colors != B_GRAY8 && + header.colors != B_GRAY1 && + header.colors != B_CMYK32 && + header.colors != B_CMY32 && + header.colors != B_CMYA32 && + header.colors != B_CMY24) + return B_NO_TRANSLATOR; + if (header.rowBytes * (header.bounds.Height() + 1) != header.dataSize) + return B_NO_TRANSLATOR; + + if (outInfo) { + outInfo->type = B_TRANSLATOR_BITMAP; + outInfo->group = B_TRANSLATOR_BITMAP; + outInfo->quality = BBT_IN_QUALITY; + outInfo->capability = BBT_IN_CAPABILITY; + strcpy(outInfo->name, "Be Bitmap Format (SGITranslator)"); + strcpy(outInfo->MIME, "image/x-be-bitmap"); + } + + if (pheader) { + pheader->magic = header.magic; + pheader->bounds = header.bounds; + pheader->rowBytes = header.rowBytes; + pheader->colors = header.colors; + pheader->dataSize = header.dataSize; + } + + return B_OK; +} + +status_t +identify_sgi_header(BPositionIO *inSource, BMessage *ioExtension, + translator_info *outInfo, uint32 outType, + SGIImage **poutSGIImage = NULL) +{ + // Can only output to bits for now + if (outType != B_TRANSLATOR_BITMAP) + return B_NO_TRANSLATOR; + + status_t status = B_NO_MEMORY; + // construct new SGIImage object and set it to the provided BPositionIO + SGIImage* sgiImage = new(nothrow) SGIImage(); + if (sgiImage) + status = sgiImage->SetTo(inSource); + + if (status >= B_OK) { + if (outInfo) { + outInfo->type = SGI_FORMAT; + outInfo->group = B_TRANSLATOR_BITMAP; + outInfo->quality = SGI_IN_QUALITY; + outInfo->capability = SGI_IN_CAPABILITY; + strcpy(outInfo->MIME, "image/sgi"); + strcpy(outInfo->name, "SGI image"); + } + } else { + delete sgiImage; + sgiImage = NULL; + } + if (!poutSGIImage) + // close SGIImage if caller is not interested in SGIImage handle + delete sgiImage; + else + // leave SGIImage open (if it is) and return handle if caller needs it + *poutSGIImage = sgiImage; + + return status; +} + +// --------------------------------------------------------------- +// Identify +// +// Examines the data from inSource and determines if it is in a +// format that this translator knows how to work with. +// +// Preconditions: +// +// Parameters: inSource, where the data to examine is +// +// inFormat, a hint about the data in inSource, +// it is ignored since it is only a hint +// +// ioExtension, configuration settings for the +// translator (not used) +// +// outInfo, information about what data is in +// inSource and how well this translator +// can handle that data is stored here +// +// outType, The format that the user wants +// the data in inSource to be +// converted to +// +// Postconditions: +// +// Returns: B_NO_TRANSLATOR, if this translator can't handle +// the data in inSource +// +// B_ERROR, if there was an error converting the data to the host +// format +// +// B_BAD_VALUE, if the settings in ioExtension are bad +// +// B_OK, if this translator understood the data and there were +// no errors found +// +// Other errors if BPositionIO::Read() returned an error value +// --------------------------------------------------------------- +status_t +SGITranslator::Identify(BPositionIO *inSource, + const translation_format *inFormat, BMessage *ioExtension, + translator_info *outInfo, uint32 outType) +{ + if (!outType) + outType = B_TRANSLATOR_BITMAP; + if (outType != B_TRANSLATOR_BITMAP && outType != SGI_FORMAT) + return B_NO_TRANSLATOR; + + // Convert the magic numbers to the various byte orders so that + // I won't have to convert the data read in to see whether or not + // it is a supported type + uint32 nbits = B_TRANSLATOR_BITMAP; + if (swap_data(B_UINT32_TYPE, &nbits, sizeof(uint32), + B_SWAP_HOST_TO_BENDIAN) != B_OK) + return B_ERROR; + + // Read in the magic number and determine if it + // is a supported type + uint8 ch[4]; + if (inSource->Read(ch, 4) != 4) + return B_NO_TRANSLATOR; + // Read settings from ioExtension + 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)); + // if B_TRANSLATOR_BITMAP type + if (n32ch == nbits) + return identify_bits_header(inSource, outInfo, 4, ch); + // Might be SGI image + else + return identify_sgi_header(inSource, ioExtension, outInfo, outType); +} + +// translate_from_bits +status_t +translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read, + BMessage *ioExtension, uint32 outType, BPositionIO *outDestination, + SGITranslatorSettings &settings) +{ + TranslatorBitmap bitsHeader; + +// TODO: how do I comply with these requests for SGIImage?!? + bool bheaderonly = settings.SetGetHeaderOnly(); + bool bdataonly = settings.SetGetDataOnly(); + uint32 compression = settings.SetGetCompression(); + + status_t ret = identify_bits_header(inSource, NULL, amtread, read, &bitsHeader); + if (ret < B_OK) + return ret; + + // 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 SGI_FORMAT + } else if (outType == SGI_FORMAT) { + + // common fields which are independent of the bitmap format + uint32 width = bitsHeader.bounds.IntegerWidth() + 1; + uint32 height = bitsHeader.bounds.IntegerHeight() + 1; + uint32 bytesPerRow = bitsHeader.rowBytes; + uint32 bytesPerChannel = 1; + color_space format = bitsHeader.colors; + + uint32 channelCount; + switch (format) { + case B_GRAY8: + channelCount = 1; + break; + case B_RGB32: + case B_RGB32_BIG: + case B_RGB24: + case B_RGB24_BIG: + channelCount = 3; + break; + case B_RGBA32: + case B_RGBA32_BIG: + channelCount = 4; + break; + default: + return B_NO_TRANSLATOR; + } + + // Set up SGI header + SGIImage* sgiImage = new SGIImage(); + status_t ret = sgiImage->SetTo(outDestination, width, height, + channelCount, bytesPerChannel, compression); + if (ret >= B_OK) { + // read one row at a time, + // convert to the correct format + // and write out the results + + // SGI Images store each channel separately + // a buffer is allocated big enough to hold all channels + // then the pointers are assigned with offsets into that buffer + uint8** rows = new(nothrow) uint8*[channelCount]; + if (rows) + rows[0] = new(nothrow) uint8[width * channelCount * bytesPerChannel]; + // rowBuffer is going to hold the converted data + uint8* rowBuffer = new(nothrow) uint8[bytesPerRow]; + if (rows && rows[0] && rowBuffer) { + // assign the other pointers (channel offsets in row buffer) + for (uint32 i = 1; i < channelCount; i++) + rows[i] = rows[0] + i * width; + // loop through all lines of the image + for (int32 y = height - 1; y >= 0 && ret >= B_OK; y--) { + + ret = inSource->Read(rowBuffer, bytesPerRow); + // see if an error happened while reading + if (ret < B_OK) + break; + // convert to native format (big endian) + switch (format) { + case B_GRAY8: { + uint8* src = rowBuffer; + for (uint32 x = 0; x < width; x++) { + rows[0][x] = src[0]; + src += 1; + } + break; + } + case B_RGB24: { + uint8* src = rowBuffer; + for (uint32 x = 0; x < width; x++) { + rows[0][x] = src[2]; + rows[1][x] = src[1]; + rows[2][x] = src[0]; + src += 3; + } + break; + } + case B_RGB24_BIG: { + uint8* src = rowBuffer; + for (uint32 x = 0; x < width; x++) { + rows[0][x] = src[0]; + rows[1][x] = src[1]; + rows[2][x] = src[2]; + src += 3; + } + break; + } + case B_RGB32: { + uint8* src = rowBuffer; + for (uint32 x = 0; x < width; x++) { + rows[0][x] = src[2]; + rows[1][x] = src[1]; + rows[2][x] = src[0]; + // ignore src[3] + src += 4; + } + break; + } + case B_RGB32_BIG: { + uint8* src = rowBuffer; + for (uint32 x = 0; x < width; x++) { + rows[0][x] = src[1]; + rows[1][x] = src[2]; + rows[2][x] = src[3]; + // ignore src[0] + src += 4; + } + break; + } + case B_RGBA32: { + uint8* src = rowBuffer; + for (uint32 x = 0; x < width; x++) { + rows[0][x] = src[2]; + rows[1][x] = src[1]; + rows[2][x] = src[0]; + rows[3][x] = src[3]; + src += 4; + } + break; + } + case B_RGBA32_BIG: { + uint8* src = rowBuffer; + for (uint32 x = 0; x < width; x++) { + rows[0][x] = src[1]; + rows[1][x] = src[2]; + rows[2][x] = src[3]; + rows[3][x] = src[0]; + src += 4; + } + break; + } + default: + // cannot be here + break; + } // switch (format) + + // for each channel, write a row buffer + for (uint32 z = 0; z < channelCount; z++) { + ret = sgiImage->WriteRow(rows[z], y, z); + if (ret < B_OK) { +printf("WriteRow() returned %s!\n", strerror(ret)); + break; + } + } + + } // for (uint32 y = 0; y < height && ret >= B_OK; y++) + if (ret >= B_OK) + ret = B_OK; + } else // if (rows && rows[0] && rowBuffer) + ret = B_NO_MEMORY; + + delete[] rows[0]; + delete[] rows; + delete[] rowBuffer; + } + + // done with the SGIImage object + delete sgiImage; + + return ret; + } + return B_NO_TRANSLATOR; +} + +// translate_from_sgi +status_t +translate_from_sgi(BPositionIO *inSource, BMessage *ioExtension, + uint32 outType, BPositionIO *outDestination, + SGITranslatorSettings &settings) +{ + status_t ret = B_NO_TRANSLATOR; + + // variables needing cleanup + SGIImage* sgiImage = NULL; + + ret = identify_sgi_header(inSource, ioExtension, NULL, outType, &sgiImage); + + if (ret >= B_OK) { + + bool bheaderonly = settings.SetGetHeaderOnly(); + bool bdataonly = settings.SetGetDataOnly(); + + uint32 width = sgiImage->Width(); + uint32 height = sgiImage->Height(); + uint32 channelCount = sgiImage->CountChannels(); + color_space format = B_RGBA32; + uint32 bytesPerRow = 0; + uint32 bytesPerChannel = sgiImage->BytesPerChannel(); + + if (channelCount == 1) { +// format = B_GRAY8; // this format is not supported by most applications +// bytesPerRow = width; + format = B_RGB32; + bytesPerRow = width * 4; + } else if (channelCount == 2) { + // means gray (luminance) + alpha, we convert that to B_RGBA32 + format = B_RGBA32; + bytesPerRow = width * 4; + } else if (channelCount == 3) { + format = B_RGB32; // should be B_RGB24, but let's not push it too hard... + bytesPerRow = width * 4; + } else if (channelCount == 4) { + format = B_RGBA32; + bytesPerRow = width * 4; + } else + ret = B_NO_TRANSLATOR; // we cannot handle this image + + if (ret >= B_OK && !bdataonly) { + // Construct and write Be bitmap header + TranslatorBitmap bitsHeader; + bitsHeader.magic = B_TRANSLATOR_BITMAP; + bitsHeader.bounds.left = 0; + bitsHeader.bounds.top = 0; + bitsHeader.bounds.right = width - 1; + bitsHeader.bounds.bottom = height - 1; + bitsHeader.rowBytes = bytesPerRow; + bitsHeader.colors = format; + bitsHeader.dataSize = bitsHeader.rowBytes * height; + if ((ret = swap_data(B_UINT32_TYPE, &bitsHeader, + sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN)) < B_OK) { + return ret; + } else + ret = outDestination->Write(&bitsHeader, sizeof(TranslatorBitmap)); + } +if (ret < B_OK) +printf("error writing bits header: %s\n", strerror(ret)); + if (ret >= B_OK && !bheaderonly) { + // read one row at a time, + // convert to the correct format + // and write out the results + + // SGI Images store each channel separately + // a buffer is allocated big enough to hold all channels + // then the pointers are assigned with offsets into that buffer + uint8** rows = new(nothrow) uint8*[channelCount]; + if (rows) + rows[0] = new(nothrow) uint8[width * channelCount * bytesPerChannel]; + // rowBuffer is going to hold the converted data + uint8* rowBuffer = new(nothrow) uint8[bytesPerRow]; + if (rows && rows[0] && rowBuffer) { + // assign the other pointers (channel offsets in row buffer) + for (uint32 i = 1; i < channelCount; i++) + rows[i] = rows[0] + i * width * bytesPerChannel; + // loop through all lines of the image + for (int32 y = height - 1; y >= 0 && ret >= B_OK; y--) { + // fill the row buffer with each channel + for (uint32 z = 0; z < channelCount; z++) { + ret = sgiImage->ReadRow(rows[z], y, z); + if (ret < B_OK) + break; + } + // see if an error happened while reading + if (ret < B_OK) + break; + // convert to native format (big endian) + if (bytesPerChannel == 1) { + switch (format) { + case B_GRAY8: { + uint8* dst = rowBuffer; + for (uint32 x = 0; x < width; x++) { + dst[0] = rows[0][x]; + dst += 1; + } + break; + } + case B_RGB24: { + uint8* dst = rowBuffer; + for (uint32 x = 0; x < width; x++) { + dst[0] = rows[2][x]; + dst[1] = rows[1][x]; + dst[2] = rows[0][x]; + dst += 3; + } + break; + } + case B_RGB32: { + uint8* dst = rowBuffer; + if (channelCount == 1) { + for (uint32 x = 0; x < width; x++) { + dst[0] = rows[0][x]; + dst[1] = rows[0][x]; + dst[2] = rows[0][x]; + dst[3] = 255; + dst += 4; + } + } else { + for (uint32 x = 0; x < width; x++) { + dst[0] = rows[2][x]; + dst[1] = rows[1][x]; + dst[2] = rows[0][x]; + dst[3] = 255; + dst += 4; + } + } + break; + } + case B_RGBA32: { + uint8* dst = rowBuffer; + if (channelCount == 2) { + for (uint32 x = 0; x < width; x++) { + dst[0] = rows[0][x]; + dst[1] = rows[0][x]; + dst[2] = rows[0][x]; + dst[3] = rows[1][x]; + dst += 4; + } + } else { + for (uint32 x = 0; x < width; x++) { + dst[0] = rows[2][x]; + dst[1] = rows[1][x]; + dst[2] = rows[0][x]; + dst[3] = rows[3][x]; + dst += 4; + } + } + break; + } + default: + // cannot be here + break; + } // switch (format) + ret = outDestination->Write(rowBuffer, bytesPerRow); + } else { + // support for 16 bits per channel images + uint16** rows16 = (uint16**)rows; + switch (format) { + case B_GRAY8: { + uint8* dst = rowBuffer; + for (uint32 x = 0; x < width; x++) { + dst[0] = rows16[0][x] >> 8; + dst += 1; + } + break; + } + case B_RGB24: { + uint8* dst = rowBuffer; + for (uint32 x = 0; x < width; x++) { + dst[0] = rows16[2][x] >> 8; + dst[1] = rows16[1][x] >> 8; + dst[2] = rows16[0][x] >> 8; + dst += 3; + } + break; + } + case B_RGB32: { + uint8* dst = rowBuffer; + if (channelCount == 1) { + for (uint32 x = 0; x < width; x++) { + dst[0] = rows16[0][x] >> 8; + dst[1] = rows16[0][x] >> 8; + dst[2] = rows16[0][x] >> 8; + dst[3] = 255; + dst += 4; + } + } else { + for (uint32 x = 0; x < width; x++) { + dst[0] = rows16[2][x] >> 8; + dst[1] = rows16[1][x] >> 8; + dst[2] = rows16[0][x] >> 8; + dst[3] = 255; + dst += 4; + } + } + break; + } + case B_RGBA32: { + uint8* dst = rowBuffer; + if (channelCount == 2) { + for (uint32 x = 0; x < width; x++) { + dst[0] = rows16[0][x] >> 8; + dst[1] = rows16[0][x] >> 8; + dst[2] = rows16[0][x] >> 8; + dst[3] = rows16[1][x] >> 8; + dst += 4; + } + } else { + for (uint32 x = 0; x < width; x++) { + dst[0] = rows16[2][x] >> 8; + dst[1] = rows16[1][x] >> 8; + dst[2] = rows16[0][x] >> 8; + dst[3] = rows16[3][x] >> 8; + dst += 4; + } + } + break; + } + default: + // cannot be here + break; + } // switch (format) + ret = outDestination->Write(rowBuffer, bytesPerRow); + } // 16 bit version + } // for (uint32 y = 0; y < height && ret >= B_OK; y++) + if (ret >= B_OK) + ret = B_OK; + } else // if (rows && rows[0] && rowBuffer) + ret = B_NO_MEMORY; + delete[] rows[0]; + delete[] rows; + delete[] rowBuffer; + } // if (ret >= B_OK && !bheaderonly) + } // if (ret >= B_OK) + delete sgiImage; + + return ret; +} + +// --------------------------------------------------------------- +// Translate +// +// Translates the data in inSource to the type outType and stores +// the translated data in outDestination. +// +// Preconditions: +// +// Parameters: inSource, the data to be translated +// +// inInfo, hint about the data in inSource (not used) +// +// ioExtension, configuration options for the +// translator +// +// outType, the type to convert inSource to +// +// outDestination, where the translated data is +// put +// +// Postconditions: +// +// Returns: B_BAD_VALUE, if the options in ioExtension are bad +// +// B_NO_TRANSLATOR, if this translator doesn't understand the data +// +// B_ERROR, if there was an error allocating memory or converting +// data +// +// B_OK, if all went well +// --------------------------------------------------------------- +status_t +SGITranslator::Translate(BPositionIO *inSource, + const translator_info *inInfo, BMessage *ioExtension, + uint32 outType, BPositionIO *outDestination) +{ + if (!outType) + outType = B_TRANSLATOR_BITMAP; + if (outType != B_TRANSLATOR_BITMAP && outType != SGI_FORMAT) + return B_NO_TRANSLATOR; + + // Convert the magic numbers to the various byte orders so that + // I won't have to convert the data read in to see whether or not + // it is a supported type + uint32 nbits = B_TRANSLATOR_BITMAP; + if (swap_data(B_UINT32_TYPE, &nbits, sizeof(uint32), + B_SWAP_HOST_TO_BENDIAN) != B_OK) + return B_ERROR; + + // Read in the magic number and determine if it + // is a supported type + uint8 ch[4]; + inSource->Seek(0, SEEK_SET); + if (inSource->Read(ch, 4) != 4) + return B_NO_TRANSLATOR; + + // Read settings from ioExtension + 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 + return translate_from_bits(inSource, 4, ch, ioExtension, outType, + outDestination, *fSettings); + } else + // Might be SGI image + return translate_from_sgi(inSource, ioExtension, outType, + outDestination, *fSettings); +} + +// returns the current translator settings into ioExtension +status_t +SGITranslator::GetConfigurationMessage(BMessage *ioExtension) +{ + return fSettings->GetConfigurationMessage(ioExtension); +} + +// --------------------------------------------------------------- +// MakeConfigurationView +// +// Makes a BView object for configuring / displaying info about +// this translator. +// +// Preconditions: +// +// Parameters: ioExtension, configuration options for the +// translator +// +// outView, the view to configure the +// translator is stored here +// +// outExtent, the bounds of the view are +// stored here +// +// Postconditions: +// +// Returns: B_BAD_VALUE if outView or outExtent is NULL, +// B_NO_MEMORY if the view couldn't be allocated, +// B_OK if no errors +// --------------------------------------------------------------- +status_t +SGITranslator::MakeConfigurationView(BMessage *ioExtension, BView **outView, + BRect *outExtent) +{ + if (!outView || !outExtent) + return B_BAD_VALUE; + if (ioExtension && fSettings->LoadSettings(ioExtension) < B_OK) + return B_BAD_VALUE; + + SGIView *view = new SGIView(BRect(0, 0, 225, 175), + "SGITranslator Settings", B_FOLLOW_ALL, B_WILL_DRAW, + AcquireSettings()); + if (!view) + return B_NO_MEMORY; + + *outView = view; + *outExtent = view->Bounds(); + + return B_OK; +} + +// AcquireSettings +SGITranslatorSettings * +SGITranslator::AcquireSettings() +{ + return fSettings->Acquire(); +} + diff --git a/src/add-ons/translators/sgitranslator/SGITranslator.h b/src/add-ons/translators/sgitranslator/SGITranslator.h new file mode 100644 index 0000000000..287433c547 --- /dev/null +++ b/src/add-ons/translators/sgitranslator/SGITranslator.h @@ -0,0 +1,128 @@ +/*****************************************************************************/ +// SGITranslator +// Written by Stephan Aßmus +// based on TIFFTranslator written mostly by +// Michael Wilber, OBOS Translation Kit Team +// +// SGITranslator.h +// +// This BTranslator based object is for opening and writing +// SGI images. +// +// +// Copyright (c) 2003 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 SGI_TRANSLATOR_H +#define SGI_TRANSLATOR_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SGI_TRANSLATOR_VERSION 100 + +#define SGI_IN_QUALITY 0.5 +#define SGI_IN_CAPABILITY 0.6 +#define SGI_OUT_QUALITY 1.0 + // high out quality because this code outputs fully standard SGIs +#define SGI_OUT_CAPABILITY 0.4 + // medium out capability because not many SGI 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 + +enum { + SGI_FORMAT = 'SGI ', +}; + +class SGITranslatorSettings; + +class SGITranslator : public BTranslator { +public: + SGITranslator(); + + virtual const char *TranslatorName() const; + // returns the short name of the translator + + virtual const char *TranslatorInfo() const; + // returns a verbose name/description for the translator + + virtual int32 TranslatorVersion() const; + // returns the version of the translator + + virtual const translation_format *InputFormats(int32 *out_count) + const; + // returns the input formats and the count of input formats + // that this translator supports + + virtual const translation_format *OutputFormats(int32 *out_count) + const; + // returns the output formats and the count of output formats + // that this translator supports + + virtual status_t Identify(BPositionIO *inSource, + const translation_format *inFormat, BMessage *ioExtension, + translator_info *outInfo, uint32 outType); + // determines whether or not this translator can convert the + // data in inSource to the type outType + + virtual status_t Translate(BPositionIO *inSource, + const translator_info *inInfo, BMessage *ioExtension, + uint32 outType, BPositionIO *outDestination); + // 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 + + SGITranslatorSettings *AcquireSettings(); + +protected: + virtual ~SGITranslator(); + // this is protected because the object is deleted by the + // Release() function instead of being deleted directly by + // the user + +private: + SGITranslatorSettings *fSettings; + + char fName[30]; + char fInfo[100]; +}; + +#endif // #ifndef SGI_TRANSLATOR_H diff --git a/src/add-ons/translators/sgitranslator/SGITranslatorSettings.cpp b/src/add-ons/translators/sgitranslator/SGITranslatorSettings.cpp new file mode 100644 index 0000000000..b1ca9b9149 --- /dev/null +++ b/src/add-ons/translators/sgitranslator/SGITranslatorSettings.cpp @@ -0,0 +1,447 @@ +/*****************************************************************************/ +// SGITranslatorSettings +// Adopted by Stephan Aßmus, +// from TGATranslatorSettings written by +// Written by Michael Wilber, OBOS Translation Kit Team +// +// SGITranslatorSettings.cpp +// +// This class manages (saves/loads/locks/unlocks) the settings +// for the SGITranslator. +// +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#include +#include +#include + // for B_TRANSLATOR_EXT_* + +#include "SGIImage.h" + +#include "SGITranslatorSettings.h" + +// --------------------------------------------------------------- +// Constructor +// +// Sets the default settings, location for the settings file +// and sets the reference count to 1 +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +SGITranslatorSettings::SGITranslatorSettings() + : fLock("SGI Settings Lock") +{ + if (find_directory(B_USER_SETTINGS_DIRECTORY, &fSettingsPath) < B_OK) + fSettingsPath.SetTo("/tmp"); + fSettingsPath.Append(SGI_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(SGI_SETTING_COMPRESSION, SGI_COMP_RLE); + // compression is set to RLE by default +} + +// --------------------------------------------------------------- +// Acquire +// +// Returns a pointer to the SGITranslatorSettings and increments +// the reference count. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: pointer to this SGITranslatorSettings object +// --------------------------------------------------------------- +SGITranslatorSettings * +SGITranslatorSettings::Acquire() +{ + SGITranslatorSettings *psettings = NULL; + + if (fLock.Lock()) { + fRefCount++; + psettings = this; + fLock.Unlock(); + } + + return psettings; +} + +// --------------------------------------------------------------- +// Release +// +// Decrements the reference count and deletes the +// SGITranslatorSettings if the reference count is zero. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: pointer to this SGITranslatorSettings object if +// the reference count is greater than zero, returns NULL +// if the reference count is zero and the SGITranslatorSettings +// object has been deleted +// --------------------------------------------------------------- +SGITranslatorSettings * +SGITranslatorSettings::Release() +{ + SGITranslatorSettings *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: +// --------------------------------------------------------------- +SGITranslatorSettings::~SGITranslatorSettings() +{ +} + +// --------------------------------------------------------------- +// 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 +SGITranslatorSettings::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 +SGITranslatorSettings::LoadSettings(BMessage *pmsg) +{ + status_t result = B_BAD_VALUE; + + if (pmsg) { + // Make certain that no SGI 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(SGI_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(SGI_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 +SGITranslatorSettings::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 +SGITranslatorSettings::GetConfigurationMessage(BMessage *pmsg) +{ + status_t result = B_BAD_VALUE; + + if (pmsg) { + const char *kNames[] = { + B_TRANSLATOR_EXT_HEADER_ONLY, + B_TRANSLATOR_EXT_DATA_ONLY, + SGI_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(SGI_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 +SGITranslatorSettings::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 +SGITranslatorSettings::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, SGI images created by the +// SGITranslator 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 +SGITranslatorSettings::SetGetCompression(uint32 *pCompression) +{ + uint32 prevValue; + + if (fLock.Lock()) { + fSettingsMSG.FindInt32(SGI_SETTING_COMPRESSION, (int32*)&prevValue); + if (pCompression) + fSettingsMSG.ReplaceInt32(SGI_SETTING_COMPRESSION, *pCompression); + fLock.Unlock(); + } + + return prevValue; +} + diff --git a/src/add-ons/translators/sgitranslator/SGITranslatorSettings.h b/src/add-ons/translators/sgitranslator/SGITranslatorSettings.h new file mode 100644 index 0000000000..069c59770f --- /dev/null +++ b/src/add-ons/translators/sgitranslator/SGITranslatorSettings.h @@ -0,0 +1,91 @@ +/*****************************************************************************/ +// SGITranslatorSettings +// Adopted by Stephan Aßmus, +// from TGATranslatorSettings written by +// Michael Wilber, OBOS Translation Kit Team +// +// SGITranslatorSettings.h +// +// This class manages (saves/loads/locks/unlocks) the settings +// for the SGITranslator. +// +// +// 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 SGI_TRANSLATOR_SETTINGS_H +#define SGI_TRANSLATOR_SETTINGS_H + +#include +#include +#include + +#define SGI_SETTINGS_FILENAME "SGITranslator_Settings" + +// SGI Translator Settings +#define SGI_SETTING_COMPRESSION "sgi /compression" + +class SGITranslatorSettings { +public: + SGITranslatorSettings(); + + SGITranslatorSettings *Acquire(); + // increments the reference count, returns this + SGITranslatorSettings *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 SGITranslator creates SGI images + +private: + ~SGITranslatorSettings(); + // 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 SGI_TRANSLATOR_SETTTINGS_H diff --git a/src/add-ons/translators/sgitranslator/SGIView.cpp b/src/add-ons/translators/sgitranslator/SGIView.cpp new file mode 100644 index 0000000000..2f6d0f56b1 --- /dev/null +++ b/src/add-ons/translators/sgitranslator/SGIView.cpp @@ -0,0 +1,335 @@ +/*****************************************************************************/ +// SGIView +// Adopted by Stephan Aßmus, +// from TIFFView written by +// Picking the compression method added by Stephan Aßmus, +// +// SGIView.cpp +// +// This BView based object displays information about the SGITranslator. +// +// +// Copyright (c) 2003 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include + +#include "SGIImage.h" +#include "SGITranslator.h" +#include "SGITranslatorSettings.h" + +#include "SGIView.h" + +const char* author = "Stephan Aßmus, "; + +// add_menu_item +void +add_menu_item(BMenu* menu, + uint32 compression, + const char* label, + uint32 currentCompression) +{ + BMessage* message = new BMessage(SGIView::MSG_COMPRESSION_CHANGED); + message->AddInt32("value", compression); + BMenuItem* item = new BMenuItem(label, message); + item->SetMarked(currentCompression == compression); + menu->AddItem(item); +} + +// --------------------------------------------------------------- +// Constructor +// +// Sets up the view settings +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +SGIView::SGIView(const BRect &frame, const char *name, + uint32 resize, uint32 flags, SGITranslatorSettings* settings) + : BView(frame, name, resize, flags), + fSettings(settings) +{ + 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, SGI_COMP_NONE, "None", currentCompression); +// menu->AddSeparatorItem(); + add_menu_item(menu, SGI_COMP_RLE, "RLE", currentCompression); + +// DON'T turn this on, it's so slow that I didn't wait long enough +// the one time I tested this. So I don't know if the code even works. +// Supposedly, this would look for an already written scanline, and +// modify the scanline tables so that the current row is not written +// at all... + +// add_menu_item(menu, SGI_COMP_ARLE, "Agressive RLE", currentCompression); + + BRect menuFrame = Bounds(); + menuFrame.bottom = menuFrame.top + menu->Bounds().Height(); + fCompressionMF = new BMenuField(menuFrame, "compression", + "Use Compression:", menu, true/*, + B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP*/); + if (fCompressionMF->MenuBar()) + fCompressionMF->MenuBar()->ResizeToPreferred(); + fCompressionMF->ResizeToPreferred(); + + // figure out where the text ends + font_height fh; + be_bold_font->GetHeight(&fh); + float xbold, ybold; + xbold = fh.descent + 1; + ybold = fh.ascent + fh.descent * 2 + fh.leading; + + font_height plainh; + be_plain_font->GetHeight(&plainh); + float yplain; + yplain = plainh.ascent + plainh.descent * 2 + plainh.leading; + + // position the menu field below all the text we draw in Draw() + BPoint textOffset(0.0, yplain * 2 + ybold); + fCompressionMF->MoveTo(textOffset); + + AddChild(fCompressionMF); + + ResizeToPreferred(); +} + +// --------------------------------------------------------------- +// Destructor +// +// Does nothing +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +SGIView::~SGIView() +{ + fSettings->Release(); +} + +// --------------------------------------------------------------- +// MessageReceived +// +// Handles state changes of the Compression menu field +// +// Preconditions: +// +// Parameters: area, not used +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +void +SGIView::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 +SGIView::AllAttached() +{ + fCompressionMF->Menu()->SetTargetForItems(this); +} + +// --------------------------------------------------------------- +// AttachedToWindow +// +// hack to make the window recognize our size +// +// Preconditions: +// +// Parameters: area, not used +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +void +SGIView::AttachedToWindow() +{ + // Hack for DataTranslations which doesn't resize visible area to requested by view + // which makes some parts of bigger than usual translationviews out of visible area + // so if it was loaded to DataTranslations resize window if needed + BWindow *window = Window(); + if (!strcmp(window->Name(), "DataTranslations")) { + BView *view = Parent(); + if (view) { + BRect frame = view->Frame(); + float x, y; + GetPreferredSize(&x, &y); + if (frame.Width() < x || (frame.Height() - 48) < y) { + x -= frame.Width(); + y -= frame.Height() - 48; + if (x < 0) x = 0; + if (y < 0) y = 0; + + // DataTranslations has main view called "Background" + // change it's resizing mode so it will always resize with window + // also make sure view will be redrawed after resize + view = window->FindView("Background"); + if (view) { + view->SetResizingMode(B_FOLLOW_ALL); + view->SetFlags(B_FULL_UPDATE_ON_RESIZE); + } + + // The same with "Info..." button, except redrawing, which isn't needed + view = window->FindView("Info…"); + if (view) + view->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + + window->ResizeBy( x, y); + } + } + } +} + +// --------------------------------------------------------------- +// Draw +// +// Draws information about the SGITranslator to this view. +// +// Preconditions: +// +// Parameters: area, not used +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +void +SGIView::Draw(BRect area) +{ + SetFont(be_bold_font); + font_height fh; + GetFontHeight(&fh); + float xbold, ybold; + xbold = fh.descent + 1; + ybold = fh.ascent + fh.descent * 2 + fh.leading; + + const char* text = "OpenBeOS SGI Image Translator"; + DrawString(text, BPoint(xbold, ybold)); + + SetFont(be_plain_font); + font_height plainh; + GetFontHeight(&plainh); + float yplain; + yplain = plainh.ascent + plainh.descent * 2 + plainh.leading; + + char detail[100]; + sprintf(detail, "Version %d.%d.%d %s", + SGI_TRANSLATOR_VERSION / 100, (SGI_TRANSLATOR_VERSION / 10) % 10, + SGI_TRANSLATOR_VERSION % 10, __DATE__); + DrawString(detail, BPoint(xbold, yplain + ybold)); + + BPoint offset = fCompressionMF->Frame().LeftBottom(); + offset.x += xbold; + offset.y += 2 * ybold; + + text = "written by:"; + DrawString(text, offset); + offset.y += ybold; + + DrawString(author, offset); + offset.y += 2 * ybold; + + text = "based on GIMP SGI plugin v1.5:"; + DrawString(text, offset); + offset.y += ybold; + + DrawString(kSGICopyright, offset); +} + +// --------------------------------------------------------------- +// Draw +// +// calculated the preferred size of this view +// +// Preconditions: +// +// Parameters: width and height +// +// Postconditions: +// +// Returns: in width and height, the preferred size... +// --------------------------------------------------------------- +void +SGIView::GetPreferredSize(float* width, float* height) +{ + *width = fCompressionMF->Bounds().Width(); + // look at the two biggest strings + float width1 = StringWidth(kSGICopyright) + 15.0; + if (*width < width1) + *width = width1; + float width2 = be_plain_font->StringWidth(author) + 15.0; + if (*width < width2) + *width = width2; + + font_height fh; + be_bold_font->GetHeight(&fh); + float ybold = fh.ascent + fh.descent * 2 + fh.leading; + + *height = fCompressionMF->Bounds().bottom + 7 * ybold; +} diff --git a/src/add-ons/translators/sgitranslator/SGIView.h b/src/add-ons/translators/sgitranslator/SGIView.h new file mode 100644 index 0000000000..983782ff6e --- /dev/null +++ b/src/add-ons/translators/sgitranslator/SGIView.h @@ -0,0 +1,70 @@ +/*****************************************************************************/ +// SGIView +// Adopted by Stephan Aßmus, +// from TIFFView written by +// Picking the compression method added by Stephan Aßmus, +// +// SGIView.h +// +// This BView based object displays information about the SGITranslator. +// +// +// Copyright (c) 2003 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 SGIVIEW_H +#define SGIVIEW_H + +#include + +class BMenuField; +class SGITranslatorSettings; + +class SGIView : public BView { +public: + SGIView(const BRect &frame, const char *name, uint32 resize, + uint32 flags, SGITranslatorSettings* psettings); + // sets up the view + + ~SGIView(); + // releases the SGITranslator settings + + virtual void AllAttached(); + virtual void AttachedToWindow(); + virtual void MessageReceived(BMessage *message); + + virtual void Draw(BRect area); + // draws information about the SGITranslator + virtual void GetPreferredSize(float* width, float* height); + + enum { + MSG_COMPRESSION_CHANGED = 'cmch', + }; + +private: + BMenuField* fCompressionMF; + + SGITranslatorSettings* fSettings; + // the actual settings for the translator, + // shared with the translator +}; + +#endif // #ifndef SGIVIEW_H diff --git a/src/add-ons/translators/sgitranslator/SGIWindow.cpp b/src/add-ons/translators/sgitranslator/SGIWindow.cpp new file mode 100644 index 0000000000..b210cb4495 --- /dev/null +++ b/src/add-ons/translators/sgitranslator/SGIWindow.cpp @@ -0,0 +1,71 @@ +/*****************************************************************************/ +// SGIWindow +// Adopted by Stephan Aßmus, +// from TIFFWindow written by +// Michael Wilber, OBOS Translation Kit Team +// +// SGIWindow.cpp +// +// This BWindow based object is used to hold the SGIView object when the +// user runs the SGITranslator as an application. +// +// +// Copyright (c) 2003 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 "SGIWindow.h" + +// --------------------------------------------------------------- +// Constructor +// +// Sets up the BWindow for holding a SGIView +// +// Preconditions: +// +// Parameters: area, The bounds of the window +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +SGIWindow::SGIWindow(BRect area) + : BWindow(area, "SGITranslator", B_TITLED_WINDOW, + B_NOT_RESIZABLE | B_NOT_ZOOMABLE) +{ +} + +// --------------------------------------------------------------- +// Destructor +// +// Posts a quit message so that the application is close properly +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +SGIWindow::~SGIWindow() +{ + be_app->PostMessage(B_QUIT_REQUESTED); +} diff --git a/src/add-ons/translators/sgitranslator/SGIWindow.h b/src/add-ons/translators/sgitranslator/SGIWindow.h new file mode 100644 index 0000000000..66c3d1d999 --- /dev/null +++ b/src/add-ons/translators/sgitranslator/SGIWindow.h @@ -0,0 +1,50 @@ +/*****************************************************************************/ +// SGIWindow +// Adopted by Stephan Aßmus, +// from TIFFWindow written by +// Michael Wilber, OBOS Translation Kit Team +// +// SGIWindow.h +// +// This BWindow based object is used to hold the SGIView object when the +// user runs the SGITranslator as an application. +// +// +// Copyright (c) 2003 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 SGIWINDOW_H +#define SGIWINDOW_H + +#include +#include +#include + +class SGIWindow : public BWindow { +public: + SGIWindow(BRect area); + // Sets up a BWindow with bounds area + + ~SGIWindow(); + // Posts a quit message so that the application closes properly +}; + +#endif // #define SGIWINDOW_H