GIFTranslator: Style fixes
This commit is contained in:
@@ -13,18 +13,24 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Additional authors: John Scipione, <[email protected]>
|
||||
|
||||
|
||||
#include "GIFLoad.h"
|
||||
#include <ByteOrder.h>
|
||||
#include <TranslatorFormats.h>
|
||||
#include <InterfaceDefs.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <ByteOrder.h>
|
||||
#include <TranslatorFormats.h>
|
||||
#include <InterfaceDefs.h>
|
||||
|
||||
|
||||
extern bool debug;
|
||||
|
||||
|
||||
GIFLoad::GIFLoad(BPositionIO *input, BPositionIO *output)
|
||||
GIFLoad::GIFLoad(BPositionIO* input, BPositionIO* output)
|
||||
:
|
||||
fatalerror(false),
|
||||
fInput(input),
|
||||
@@ -39,26 +45,32 @@ GIFLoad::GIFLoad(BPositionIO *input, BPositionIO *output)
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFLoad::GIFLoad() - Image dimensions are %d x %d\n",
|
||||
fWidth, fHeight);
|
||||
|
||||
fWidth, fHeight);
|
||||
}
|
||||
|
||||
unsigned char c;
|
||||
if (fInput->Read(&c, 1) < 1) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
|
||||
while (c != 0x3b) {
|
||||
if (c == 0x2c) {
|
||||
if ((!ReadGIFImageHeader()) || (!ReadGIFImageData())) {
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::GIFLoad() - A fatal error occurred\n");
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFLoad::GIFLoad() - "
|
||||
"A fatal error occurred\n");
|
||||
}
|
||||
|
||||
fatalerror = true;
|
||||
} else {
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::GIFLoad() - Found a single image and "
|
||||
"leaving\n");
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFLoad::GIFLoad() - "
|
||||
"Found a single image and leaving\n");
|
||||
}
|
||||
}
|
||||
free(fScanLine);
|
||||
fScanLine = NULL;
|
||||
@@ -96,32 +108,44 @@ GIFLoad::GIFLoad(BPositionIO *input, BPositionIO *output)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fInput->Read(&c, 1) < 1) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::GIFLoad() - Done\n");
|
||||
}
|
||||
|
||||
|
||||
GIFLoad::~GIFLoad()
|
||||
{
|
||||
delete fPalette;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GIFLoad::ReadGIFHeader()
|
||||
{
|
||||
// Standard header
|
||||
// standard header
|
||||
unsigned char header[13];
|
||||
if (fInput->Read(header, 13) < 13) return false;
|
||||
if (fInput->Read(header, 13) < 13)
|
||||
return false;
|
||||
|
||||
fWidth = header[6] + (header[7] << 8);
|
||||
fHeight = header[8] + (header[9] << 8);
|
||||
|
||||
|
||||
fPalette = new LoadPalette();
|
||||
// Global palette
|
||||
if (header[10] & GIF_LOCALCOLORMAP) {
|
||||
fPalette->size_in_bits = (header[10] & 0x07) + 1;
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFHeader() - Found %d bit global palette\n",
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFHeader() - "
|
||||
"Found %d bit global palette\n",
|
||||
fPalette->size_in_bits);
|
||||
}
|
||||
int s = 1 << fPalette->size_in_bits;
|
||||
fPalette->size = s;
|
||||
|
||||
@@ -132,15 +156,17 @@ GIFLoad::ReadGIFHeader()
|
||||
fPalette->SetColor(x, gp[x * 3], gp[x * 3 + 1], gp[x * 3 + 2]);
|
||||
}
|
||||
fPalette->backgroundindex = header[11];
|
||||
} else { // Install BeOS system palette in case local palette isn't present
|
||||
color_map *map = (color_map *)system_colors();
|
||||
} else {
|
||||
// install BeOS system palette in case local palette isn't present
|
||||
color_map* map = (color_map*)system_colors();
|
||||
for (int x = 0; x < 256; x++) {
|
||||
fPalette->SetColor(x, map->color_list[x].red,
|
||||
fPalette->SetColor(x, map->color_list[x].red,
|
||||
map->color_list[x].green, map->color_list[x].blue);
|
||||
}
|
||||
fPalette->size = 256;
|
||||
fPalette->size_in_bits = 8;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -151,11 +177,11 @@ GIFLoad::ReadGIFLoopBlock()
|
||||
unsigned char length;
|
||||
if (fInput->Read(&length, 1) < 1) return false;
|
||||
fInput->Seek(length, SEEK_CUR);
|
||||
|
||||
|
||||
do {
|
||||
if (fInput->Read(&length, 1) < 1) {
|
||||
if (fInput->Read(&length, 1) < 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
fInput->Seek(length, SEEK_CUR);
|
||||
} while (length != 0);
|
||||
|
||||
@@ -169,78 +195,93 @@ GIFLoad::ReadGIFControlBlock()
|
||||
unsigned char data[6];
|
||||
if (fInput->Read(data, 6) < 6)
|
||||
return false;
|
||||
|
||||
if (data[1] & 0x01) {
|
||||
fPalette->usetransparent = true;
|
||||
fPalette->transparentindex = data[4];
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFControlBlock() - Transparency active, "
|
||||
"using palette index %d\n", data[4]);
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFControlBlock() - "
|
||||
"Transparency active, using palette index %d\n", data[4]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GIFLoad::ReadGIFCommentBlock()
|
||||
bool
|
||||
GIFLoad::ReadGIFCommentBlock()
|
||||
{
|
||||
if (debug) syslog(LOG_ERR, "GIFLoad::ReadGIFCommentBlock() - Found:\n");
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFCommentBlock() - Found:\n");
|
||||
|
||||
unsigned char length;
|
||||
char comment_data[256];
|
||||
do {
|
||||
if (fInput->Read(&length, 1) < 1)
|
||||
return false;
|
||||
|
||||
if (fInput->Read(comment_data, length) < length)
|
||||
return false;
|
||||
|
||||
comment_data[length] = 0x00;
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "%s", comment_data);
|
||||
} while (length != 0x00);
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GIFLoad::ReadGIFUnknownBlock(unsigned char c)
|
||||
bool
|
||||
GIFLoad::ReadGIFUnknownBlock(unsigned char c)
|
||||
{
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFUnknownBlock() - Found: %d\n", c);
|
||||
|
||||
unsigned char length;
|
||||
do {
|
||||
if (fInput->Read(&length, 1) < 1)
|
||||
return false;
|
||||
|
||||
fInput->Seek(length, SEEK_CUR);
|
||||
} while (length != 0x00);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GIFLoad::ReadGIFImageHeader()
|
||||
bool
|
||||
GIFLoad::ReadGIFImageHeader()
|
||||
{
|
||||
unsigned char data[9];
|
||||
if (fInput->Read(data, 9) < 9)
|
||||
return false;
|
||||
|
||||
|
||||
int localWidth = data[4] + (data[5] << 8);
|
||||
int localHeight = data[6] + (data[7] << 8);
|
||||
if (fWidth != localWidth || fHeight != localHeight) {
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageHeader() - Local dimensions do not "
|
||||
"match global, setting to %d x %d\n", localWidth, localHeight);
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageHeader() - "
|
||||
"Local dimensions do not match global, setting to %d x %d\n",
|
||||
localWidth, localHeight);
|
||||
}
|
||||
fWidth = localWidth;
|
||||
fHeight = localHeight;
|
||||
}
|
||||
|
||||
fScanLine = (uint32 *)malloc(fWidth * 4);
|
||||
|
||||
fScanLine = (uint32*)malloc(fWidth * 4);
|
||||
if (fScanLine == NULL) {
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageHeader() - Could not allocate "
|
||||
"scanline\n");
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageHeader() - "
|
||||
"Could not allocate scanline\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
BRect rect(0, 0, fWidth - 1, fHeight - 1);
|
||||
TranslatorBitmap header;
|
||||
header.magic = B_HOST_TO_BENDIAN_INT32(B_TRANSLATOR_BITMAP);
|
||||
@@ -254,126 +295,137 @@ GIFLoad::ReadGIFImageHeader()
|
||||
if (fOutput->Write(&header, 32) < 32)
|
||||
return false;
|
||||
|
||||
// Has local palette
|
||||
if (data[8] & GIF_LOCALCOLORMAP) {
|
||||
// has local palette
|
||||
fPalette->size_in_bits = (data[8] & 0x07) + 1;
|
||||
int s = 1 << fPalette->size_in_bits;
|
||||
fPalette->size = s;
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageHeader() - Found %d bit local "
|
||||
"palette\n", fPalette->size_in_bits);
|
||||
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageHeader() - "
|
||||
"Found %d bit local palette\n", fPalette->size_in_bits);
|
||||
}
|
||||
|
||||
unsigned char lp[256 * 3];
|
||||
if (fInput->Read(lp, s * 3) < s * 3)
|
||||
return false;
|
||||
for (int x = 0; x < s; x++) {
|
||||
|
||||
for (int x = 0; x < s; x++)
|
||||
fPalette->SetColor(x, lp[x * 3], lp[x * 3 + 1], lp[x * 3 + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fInterlaced = data[8] & GIF_INTERLACED;
|
||||
if (debug) {
|
||||
if (fInterlaced)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageHeader() - Image is interlaced\n");
|
||||
else
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageHeader() - Image is not "
|
||||
"interlaced\n");
|
||||
if (fInterlaced) {
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageHeader() - "
|
||||
"Image is interlaced\n");
|
||||
} else {
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageHeader() - "
|
||||
"Image is not interlaced\n");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GIFLoad::ReadGIFImageData()
|
||||
GIFLoad::ReadGIFImageData()
|
||||
{
|
||||
unsigned char newEntry[4096];
|
||||
|
||||
|
||||
unsigned char cs;
|
||||
fInput->Read(&cs, 1);
|
||||
if (cs == fPalette->size_in_bits) {
|
||||
if (!InitFrame(fPalette->size_in_bits))
|
||||
return false;
|
||||
} else if (cs > fPalette->size_in_bits) {
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageData() - Code_size should be %d, not "
|
||||
"%d, allowing it\n", fCodeSize, cs);
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageData() - "
|
||||
"Code_size should be %d, not %d, allowing it\n",
|
||||
fCodeSize, cs);
|
||||
}
|
||||
if (!InitFrame(cs))
|
||||
return false;
|
||||
} else if (cs < fPalette->size_in_bits) {
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageData() - Code_size should be %d, not "
|
||||
"%d\n", fCodeSize, cs);
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageData() - "
|
||||
"Code_size should be %d, not %d\n", fCodeSize, cs);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageData() - Starting LZW\n");
|
||||
|
||||
|
||||
while ((fNewCode = NextCode()) != -1 && fNewCode != fEndCode) {
|
||||
if (fNewCode == fClearCode) {
|
||||
ResetTable();
|
||||
fNewCode = NextCode();
|
||||
fOldCode[0] = fNewCode;
|
||||
fOldCodeLength = 1;
|
||||
if (!OutputColor(fOldCode, 1)) goto bad_end;
|
||||
if (!OutputColor(fOldCode, 1))
|
||||
goto bad_end;
|
||||
|
||||
if (fNewCode == -1 || fNewCode == fEndCode) {
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageData() - Premature fEndCode "
|
||||
"or error\n");
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageData() - "
|
||||
"Premature fEndCode or error reading fNewCode\n");
|
||||
}
|
||||
goto bad_end;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Explicitly check for lack of clear code at start of file
|
||||
|
||||
// explicitly check for lack of clear code at start of file
|
||||
if (fOldCodeLength == 0) {
|
||||
fOldCode[0] = fNewCode;
|
||||
fOldCodeLength = 1;
|
||||
if (!OutputColor(fOldCode, 1))
|
||||
goto bad_end;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fTable[fNewCode] != NULL) { // Does exist in table
|
||||
|
||||
if (fTable[fNewCode] != NULL) {
|
||||
// exists in table
|
||||
|
||||
if (!OutputColor(fTable[fNewCode], fEntrySize[fNewCode]))
|
||||
goto bad_end;
|
||||
|
||||
|
||||
//memcpy(newEntry, fOldCode, fOldCodeLength);
|
||||
for (unsigned int x = 0; x < fOldCodeLength; x++) {
|
||||
for (unsigned int x = 0; x < fOldCodeLength; x++)
|
||||
newEntry[x] = fOldCode[x];
|
||||
}
|
||||
|
||||
|
||||
//memcpy(newEntry + fOldCodeLength, fTable[fNewCode], 1);
|
||||
newEntry[fOldCodeLength] = *fTable[fNewCode];
|
||||
} else { // Does not exist in table
|
||||
} else {
|
||||
// does not exist in table
|
||||
|
||||
//memcpy(newEntry, fOldCode, fOldCodeLength);
|
||||
for (unsigned int x = 0; x < fOldCodeLength; x++) {
|
||||
for (unsigned int x = 0; x < fOldCodeLength; x++)
|
||||
newEntry[x] = fOldCode[x];
|
||||
}
|
||||
|
||||
|
||||
//memcpy(newEntry + fOldCodeLength, fOldCode, 1);
|
||||
newEntry[fOldCodeLength] = *fOldCode;
|
||||
|
||||
|
||||
if (!OutputColor(newEntry, fOldCodeLength + 1))
|
||||
goto bad_end;
|
||||
}
|
||||
fTable[fNextCode] = MemblockAllocate(fOldCodeLength + 1);
|
||||
|
||||
//memcpy(fTable[fNextCode], newEntry, fOldCodeLength + 1);
|
||||
for (unsigned int x = 0; x < fOldCodeLength + 1; x++) {
|
||||
for (unsigned int x = 0; x < fOldCodeLength + 1; x++)
|
||||
fTable[fNextCode][x] = newEntry[x];
|
||||
}
|
||||
|
||||
|
||||
fEntrySize[fNextCode] = fOldCodeLength + 1;
|
||||
|
||||
|
||||
//memcpy(fOldCode, fTable[fNewCode], fEntrySize[fNewCode]);
|
||||
for (int x = 0; x < fEntrySize[fNewCode]; x++) {
|
||||
for (int x = 0; x < fEntrySize[fNewCode]; x++)
|
||||
fOldCode[x] = fTable[fNewCode][x];
|
||||
}
|
||||
|
||||
|
||||
fOldCodeLength = fEntrySize[fNewCode];
|
||||
fNextCode++;
|
||||
|
||||
|
||||
if (fNextCode > fMaxCode && fBits != 12) {
|
||||
fBits++;
|
||||
fMaxCode = (1 << fBits) - 1;
|
||||
@@ -383,27 +435,36 @@ GIFLoad::ReadGIFImageData()
|
||||
MemblockDeleteAll();
|
||||
if (fNewCode == -1)
|
||||
return false;
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageData() - Done\n");
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
bad_end:
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFLoad::ReadGIFImageData() - Reached a bad end\n");
|
||||
|
||||
MemblockDeleteAll();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
short
|
||||
GIFLoad::NextCode()
|
||||
short
|
||||
GIFLoad::NextCode()
|
||||
{
|
||||
while (fBitCount < fBits) {
|
||||
if (fByteCount == 0) {
|
||||
if (fInput->Read(&fByteCount, 1) < 1) return -1;
|
||||
if (fByteCount == 0) return fEndCode;
|
||||
if (fInput->Read(fByteBuffer + (255 - fByteCount),
|
||||
fByteCount) < fByteCount) return -1;
|
||||
if (fInput->Read(&fByteCount, 1) < 1)
|
||||
return -1;
|
||||
|
||||
if (fByteCount == 0)
|
||||
return fEndCode;
|
||||
|
||||
if (fInput->Read(fByteBuffer + (255 - fByteCount), fByteCount)
|
||||
< fByteCount) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
fBitBuffer |= (unsigned int)fByteBuffer[255 - fByteCount] << fBitCount;
|
||||
fByteCount--;
|
||||
@@ -413,17 +474,18 @@ GIFLoad::NextCode()
|
||||
short s = fBitBuffer & ((1 << fBits) - 1);
|
||||
fBitBuffer >>= fBits;
|
||||
fBitCount -= fBits;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GIFLoad::ResetTable()
|
||||
void
|
||||
GIFLoad::ResetTable()
|
||||
{
|
||||
fBits = fCodeSize + 1;
|
||||
fNextCode = fClearCode + 2;
|
||||
fMaxCode = (1 << fBits) - 1;
|
||||
|
||||
|
||||
MemblockDeleteAll();
|
||||
for (int x = 0; x < 4096; x++) {
|
||||
fTable[x] = NULL;
|
||||
@@ -436,53 +498,58 @@ GIFLoad::ResetTable()
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GIFLoad::InitFrame(int size)
|
||||
bool
|
||||
GIFLoad::InitFrame(int size)
|
||||
{
|
||||
fCodeSize = size;
|
||||
if (fCodeSize == 1)
|
||||
fCodeSize++;
|
||||
|
||||
fBits = fCodeSize + 1;
|
||||
fClearCode = 1 << fCodeSize;
|
||||
fEndCode = fClearCode + 1;
|
||||
fNextCode = fClearCode + 2;
|
||||
fMaxCode = (1 << fBits) - 1;
|
||||
fPass = 0;
|
||||
|
||||
if (fInterlaced)
|
||||
fRow = gl_pass_starts_at[0];
|
||||
else
|
||||
else
|
||||
fRow = 0;
|
||||
|
||||
|
||||
fBitCount = 0;
|
||||
fBitBuffer = 0;
|
||||
fByteCount = 0;
|
||||
fOldCodeLength = 0;
|
||||
fNewCode = 0;
|
||||
fScanlinePosition = 0;
|
||||
|
||||
|
||||
ResetTable();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Do 4k mallocs, keep them in a linked list, do a first fit across them
|
||||
// when a new request comes along
|
||||
uchar *
|
||||
GIFLoad::MemblockAllocate(int size)
|
||||
uchar*
|
||||
GIFLoad::MemblockAllocate(int size)
|
||||
{
|
||||
// Do 4k mallocs, keep them in a linked list, do a first fit across
|
||||
// them when a new request comes along.
|
||||
|
||||
if (fHeadMemblock == NULL) {
|
||||
fHeadMemblock = new Memblock();
|
||||
uchar *value = fHeadMemblock->data;
|
||||
uchar* value = fHeadMemblock->data;
|
||||
fHeadMemblock->offset = size;
|
||||
fHeadMemblock->next = NULL;
|
||||
|
||||
return value;
|
||||
} else {
|
||||
Memblock *block = fHeadMemblock;
|
||||
Memblock *last = NULL;
|
||||
Memblock* block = fHeadMemblock;
|
||||
Memblock* last = NULL;
|
||||
while (block != NULL) {
|
||||
if (4096 - block->offset > size) {
|
||||
uchar *value = block->data + block->offset;
|
||||
uchar* value = block->data + block->offset;
|
||||
block->offset += size;
|
||||
|
||||
return value;
|
||||
}
|
||||
last = block;
|
||||
@@ -490,21 +557,23 @@ GIFLoad::MemblockAllocate(int size)
|
||||
}
|
||||
|
||||
block = new Memblock();
|
||||
uchar *value = block->data;
|
||||
uchar* value = block->data;
|
||||
block->offset = size;
|
||||
block->next = NULL;
|
||||
last->next = block;
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Delete the linked list
|
||||
void
|
||||
GIFLoad::MemblockDeleteAll()
|
||||
void
|
||||
GIFLoad::MemblockDeleteAll()
|
||||
{
|
||||
Memblock *block = NULL;
|
||||
Memblock* block = NULL;
|
||||
|
||||
while (fHeadMemblock != NULL) {
|
||||
// delete the linked list
|
||||
block = fHeadMemblock->next;
|
||||
delete fHeadMemblock;
|
||||
fHeadMemblock = block;
|
||||
@@ -512,8 +581,33 @@ GIFLoad::MemblockDeleteAll()
|
||||
}
|
||||
|
||||
|
||||
GIFLoad::~GIFLoad()
|
||||
bool
|
||||
GIFLoad::OutputColor(unsigned char* string, int size)
|
||||
{
|
||||
delete fPalette;
|
||||
}
|
||||
int bpr = fWidth << 2;
|
||||
|
||||
for (int x = 0; x < size; x++) {
|
||||
fScanLine[fScanlinePosition] = fPalette->ColorForIndex(string[x]);
|
||||
fScanlinePosition++;
|
||||
|
||||
if (fScanlinePosition >= fWidth) {
|
||||
if (fOutput->WriteAt(32 + (fRow * bpr), fScanLine, bpr) < bpr)
|
||||
return false;
|
||||
|
||||
fScanlinePosition = 0;
|
||||
if (fInterlaced) {
|
||||
fRow += gl_increment_pass_by[fPass];
|
||||
while (fRow >= fHeight) {
|
||||
fPass++;
|
||||
if (fPass > 3)
|
||||
return true;
|
||||
|
||||
fRow = gl_pass_starts_at[fPass];
|
||||
}
|
||||
} else
|
||||
fRow++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -13,96 +13,93 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GIFLOAD_H
|
||||
#define GIFLOAD_H
|
||||
// Additional authors: John Scipione, <[email protected]>
|
||||
|
||||
#ifndef GIF_LOAD_H
|
||||
#define GIF_LOAD_H
|
||||
|
||||
|
||||
#include <DataIO.h>
|
||||
#include "LoadPalette.h"
|
||||
|
||||
|
||||
#define GIF_INTERLACED 0x40
|
||||
#define GIF_LOCALCOLORMAP 0x80
|
||||
|
||||
|
||||
class Memblock {
|
||||
public:
|
||||
uchar data[4096];
|
||||
int offset;
|
||||
Memblock *next;
|
||||
struct Memblock {
|
||||
uchar data[4096];
|
||||
int offset;
|
||||
Memblock* next;
|
||||
};
|
||||
|
||||
|
||||
const int gl_pass_starts_at[] = {0, 4, 2, 1, 0};
|
||||
const int gl_increment_pass_by[] = {8, 8, 4, 2, 0};
|
||||
const int gl_pass_starts_at[] = { 0, 4, 2, 1, 0 };
|
||||
const int gl_increment_pass_by[] = { 8, 8, 4, 2, 0 };
|
||||
|
||||
|
||||
class GIFLoad {
|
||||
public:
|
||||
GIFLoad(BPositionIO *input, BPositionIO *output);
|
||||
~GIFLoad();
|
||||
bool fatalerror;
|
||||
|
||||
private:
|
||||
bool ReadGIFHeader();
|
||||
bool ReadGIFLoopBlock();
|
||||
bool ReadGIFControlBlock();
|
||||
bool ReadGIFImageHeader();
|
||||
bool ReadGIFImageData();
|
||||
bool ReadGIFCommentBlock();
|
||||
bool ReadGIFUnknownBlock(unsigned char c);
|
||||
|
||||
bool InitFrame(int size);
|
||||
short NextCode();
|
||||
void ResetTable();
|
||||
|
||||
uchar *MemblockAllocate(int size);
|
||||
void MemblockDeleteAll();
|
||||
public:
|
||||
GIFLoad(BPositionIO* input,
|
||||
BPositionIO* output);
|
||||
virtual ~GIFLoad();
|
||||
|
||||
inline bool OutputColor(unsigned char *string, int size) {
|
||||
int bpr = fWidth << 2;
|
||||
|
||||
for (int x = 0; x < size; x++) {
|
||||
fScanLine[fScanlinePosition] = fPalette->ColorForIndex(string[x]);
|
||||
fScanlinePosition++;
|
||||
|
||||
if (fScanlinePosition >= fWidth) {
|
||||
if (fOutput->WriteAt(32 + (fRow * bpr), fScanLine, bpr) < bpr) return false;
|
||||
fScanlinePosition = 0;
|
||||
if (fInterlaced) {
|
||||
fRow += gl_increment_pass_by[fPass];
|
||||
while (fRow >= fHeight) {
|
||||
fPass++;
|
||||
if (fPass > 3) return true;
|
||||
fRow = gl_pass_starts_at[fPass];
|
||||
}
|
||||
} else fRow++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BPositionIO *fInput, *fOutput;
|
||||
LoadPalette *fPalette;
|
||||
bool fInterlaced;
|
||||
int fPass, fRow, fWidth, fHeight;
|
||||
|
||||
unsigned char fOldCode[4096];
|
||||
unsigned int fOldCodeLength;
|
||||
short fNewCode;
|
||||
int fBits, fMaxCode, fCodeSize;
|
||||
short fClearCode, fEndCode, fNextCode;
|
||||
|
||||
unsigned char *fTable[4096];
|
||||
short fEntrySize[4096];
|
||||
Memblock *fHeadMemblock;
|
||||
|
||||
int fBitCount;
|
||||
unsigned int fBitBuffer;
|
||||
unsigned char fByteCount;
|
||||
unsigned char fByteBuffer[255];
|
||||
bool fatalerror;
|
||||
|
||||
uint32 *fScanLine;
|
||||
int fScanlinePosition;
|
||||
private:
|
||||
bool ReadGIFHeader();
|
||||
bool ReadGIFLoopBlock();
|
||||
bool ReadGIFControlBlock();
|
||||
bool ReadGIFImageHeader();
|
||||
bool ReadGIFImageData();
|
||||
bool ReadGIFCommentBlock();
|
||||
bool ReadGIFUnknownBlock(unsigned char c);
|
||||
|
||||
bool InitFrame(int size);
|
||||
short NextCode();
|
||||
void ResetTable();
|
||||
|
||||
uchar* MemblockAllocate(int size);
|
||||
void MemblockDeleteAll();
|
||||
|
||||
inline bool OutputColor(unsigned char* string, int size);
|
||||
|
||||
BPositionIO* fInput;
|
||||
BPositionIO* fOutput;
|
||||
LoadPalette* fPalette;
|
||||
|
||||
bool fInterlaced;
|
||||
|
||||
int fPass;
|
||||
int fRow;
|
||||
|
||||
int fWidth;
|
||||
int fHeight;
|
||||
|
||||
unsigned char fOldCode[4096];
|
||||
unsigned int fOldCodeLength;
|
||||
|
||||
short fNewCode;
|
||||
int fBits;
|
||||
int fMaxCode;
|
||||
int fCodeSize;
|
||||
|
||||
short fClearCode;
|
||||
short fEndCode;
|
||||
short fNextCode;
|
||||
|
||||
unsigned char* fTable[4096];
|
||||
short fEntrySize[4096];
|
||||
Memblock* fHeadMemblock;
|
||||
|
||||
int fBitCount;
|
||||
unsigned int fBitBuffer;
|
||||
unsigned char fByteCount;
|
||||
unsigned char fByteBuffer[255];
|
||||
|
||||
uint32* fScanLine;
|
||||
int fScanlinePosition;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // GIF_LOAD_H
|
||||
|
||||
@@ -15,12 +15,16 @@
|
||||
|
||||
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||
// Philippe Saint-Pierre, <[email protected]>
|
||||
// John Scipione, <[email protected]>
|
||||
|
||||
|
||||
#include "GIFSave.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
|
||||
|
||||
const int gs_pass_starts_at[] = {0, 4, 2, 1, 0};
|
||||
const int gs_increment_pass_by[] = {8, 8, 4, 2, 0};
|
||||
const int32 one_sixteenth = (int32)((1.0 / 16.0) * 32768);
|
||||
@@ -30,12 +34,13 @@ const int32 seven_sixteenth = (int32)((7.0 / 16.0) * 32768);
|
||||
|
||||
extern bool debug;
|
||||
|
||||
|
||||
class ColorCache : public HashItem {
|
||||
public:
|
||||
unsigned char index;
|
||||
};
|
||||
|
||||
// constructor
|
||||
|
||||
GIFSave::GIFSave(BBitmap* bitmap, BPositionIO* output,
|
||||
TranslatorSettings* settings)
|
||||
{
|
||||
@@ -48,7 +53,7 @@ GIFSave::GIFSave(BBitmap* bitmap, BPositionIO* output,
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fatalerror = false;
|
||||
if (fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE) == OPTIMAL_PALETTE)
|
||||
palette = new SavePalette(bitmap,
|
||||
@@ -60,23 +65,28 @@ GIFSave::GIFSave(BBitmap* bitmap, BPositionIO* output,
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
width = bitmap->Bounds().IntegerWidth() + 1;
|
||||
height = bitmap->Bounds().IntegerHeight() + 1;
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - Image dimensions are %d by %d\n",
|
||||
width, height);
|
||||
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - "
|
||||
"Image dimensions are %d by %d\n", width, height);
|
||||
}
|
||||
|
||||
if (fSettings->SetGetBool(GIF_SETTING_USE_DITHERING)) {
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - Using dithering\n");
|
||||
|
||||
red_error = new int32[width + 2];
|
||||
red_error = &red_error[1]; // Allow index of -1 too
|
||||
red_error = &red_error[1];
|
||||
// Allow index of -1 too
|
||||
green_error = new int32[width + 2];
|
||||
green_error = &green_error[1]; // Allow index of -1 too
|
||||
green_error = &green_error[1];
|
||||
// Allow index of -1 too
|
||||
blue_error = new int32[width + 2];
|
||||
blue_error = &blue_error[1]; // Allow index of -1 too
|
||||
|
||||
blue_error = &blue_error[1];
|
||||
// Allow index of -1 too
|
||||
|
||||
red_side_error = green_side_error = blue_side_error = 0;
|
||||
for (int32 x = -1; x < width + 1; x++) {
|
||||
red_error[x] = 0;
|
||||
@@ -85,7 +95,7 @@ GIFSave::GIFSave(BBitmap* bitmap, BPositionIO* output,
|
||||
}
|
||||
} else if (debug)
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - Not using dithering\n");
|
||||
|
||||
|
||||
if (debug) {
|
||||
if (fSettings->SetGetBool(GIF_SETTING_INTERLACED))
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - Interlaced, ");
|
||||
@@ -107,21 +117,23 @@ GIFSave::GIFSave(BBitmap* bitmap, BPositionIO* output,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT)) {
|
||||
if (fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO)) {
|
||||
palette->PrepareForAutoTransparency();
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - Using transparent index %d\n",
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - "
|
||||
"Using transparent index %d\n",
|
||||
palette->TransparentIndex());
|
||||
}
|
||||
} else {
|
||||
palette->SetTransparentColor(
|
||||
(uint8)fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_RED),
|
||||
(uint8)fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_GREEN),
|
||||
(uint8)fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_BLUE));
|
||||
if (debug) {
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - Found transparent color %d,%d,%d "
|
||||
"at index %d\n",
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - "
|
||||
"Found transparent color %d,%d,%d at index %d\n",
|
||||
fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_RED),
|
||||
fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_GREEN),
|
||||
fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_BLUE),
|
||||
@@ -138,22 +150,24 @@ GIFSave::GIFSave(BBitmap* bitmap, BPositionIO* output,
|
||||
WriteGIFHeader();
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - Wrote gif header\n");
|
||||
|
||||
|
||||
hash = new SFHash(1 << 16);
|
||||
WriteGIFControlBlock();
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - Wrote gif control block\n");
|
||||
|
||||
WriteGIFImageHeader();
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - Wrote gif image header\n");
|
||||
|
||||
WriteGIFImageData();
|
||||
if (debug)
|
||||
syslog(LOG_ERR, "GIFSave::GIFSave() - Wrote gif image data\n");
|
||||
|
||||
|
||||
if (fSettings->SetGetBool(GIF_SETTING_USE_DITHERING)) {
|
||||
delete [] &red_error[-1];
|
||||
delete [] &green_error[-1];
|
||||
delete [] &blue_error[-1];
|
||||
delete[] &red_error[-1];
|
||||
delete[] &green_error[-1];
|
||||
delete[] &blue_error[-1];
|
||||
}
|
||||
delete hash;
|
||||
|
||||
@@ -162,19 +176,20 @@ GIFSave::GIFSave(BBitmap* bitmap, BPositionIO* output,
|
||||
output->Write(&t, 1);
|
||||
}
|
||||
|
||||
// destructor
|
||||
|
||||
GIFSave::~GIFSave()
|
||||
{
|
||||
delete palette;
|
||||
fSettings->Release();
|
||||
}
|
||||
|
||||
// WriteGIFHeader
|
||||
|
||||
void
|
||||
GIFSave::WriteGIFHeader()
|
||||
{
|
||||
// Standard header
|
||||
unsigned char header[] = {'G', 'I', 'F', '8', '9', 'a', 0, 0, 0, 0, 0, 0, 0};
|
||||
unsigned char header[]
|
||||
= { 'G', 'I', 'F', '8', '9', 'a', 0, 0, 0, 0, 0, 0, 0 };
|
||||
header[6] = width & 0xff;
|
||||
header[7] = (width & 0xff00) >> 8;
|
||||
header[8] = height & 0xff;
|
||||
@@ -182,20 +197,21 @@ GIFSave::WriteGIFHeader()
|
||||
header[10] = 0xf0 | (palette->SizeInBits() - 1);
|
||||
header[11] = palette->BackgroundIndex();
|
||||
output->Write(header, 13);
|
||||
|
||||
// Global palette
|
||||
|
||||
// global palette
|
||||
int size = (1 << palette->SizeInBits()) * 3;
|
||||
uint8* buffer = new uint8[size]; // can't be bigger than this
|
||||
uint8* buffer = new uint8[size];
|
||||
// can't be bigger than this
|
||||
palette->GetColors(buffer, size);
|
||||
output->Write(buffer, size);
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
// WriteGIFControlBlock
|
||||
|
||||
void
|
||||
GIFSave::WriteGIFControlBlock()
|
||||
{
|
||||
unsigned char b[8] = {0x21, 0xf9, 0x04, 0, 0, 0, 0, 0x00};
|
||||
unsigned char b[8] = { 0x21, 0xf9, 0x04, 0, 0, 0, 0, 0x00 };
|
||||
if (palette->UseTransparent()) {
|
||||
b[3] = b[3] | 1;
|
||||
b[6] = palette->TransparentIndex();
|
||||
@@ -203,14 +219,15 @@ GIFSave::WriteGIFControlBlock()
|
||||
output->Write(b, 8);
|
||||
}
|
||||
|
||||
// WriteGIFImageHeader
|
||||
void GIFSave::WriteGIFImageHeader()
|
||||
|
||||
void
|
||||
GIFSave::WriteGIFImageHeader()
|
||||
{
|
||||
unsigned char header[10];
|
||||
header[0] = 0x2c;
|
||||
header[1] = header[2] = 0;
|
||||
header[3] = header[4] = 0;
|
||||
|
||||
|
||||
header[5] = width & 0xff;
|
||||
header[6] = (width & 0xff00) >> 8;
|
||||
header[7] = height & 0xff;
|
||||
@@ -220,39 +237,42 @@ void GIFSave::WriteGIFImageHeader()
|
||||
header[9] = 0x40;
|
||||
else
|
||||
header[9] = 0x00;
|
||||
|
||||
output->Write(header, 10);
|
||||
}
|
||||
|
||||
// WriteGIFImageData
|
||||
void GIFSave::WriteGIFImageData()
|
||||
|
||||
void
|
||||
GIFSave::WriteGIFImageData()
|
||||
{
|
||||
InitFrame();
|
||||
code_value = (short *)malloc(HASHSIZE * 2);
|
||||
prefix_code = (short *)malloc(HASHSIZE * 2);
|
||||
append_char = (unsigned char *)malloc(HASHSIZE);
|
||||
code_value = (short*)malloc(HASHSIZE * 2);
|
||||
prefix_code = (short*)malloc(HASHSIZE * 2);
|
||||
append_char = (unsigned char*)malloc(HASHSIZE);
|
||||
ResetHashtable();
|
||||
|
||||
|
||||
output->Write(&code_size, 1);
|
||||
OutputCode(clear_code, BITS);
|
||||
string_code = NextPixel(0);
|
||||
int area = height * width;
|
||||
|
||||
|
||||
for (int x = 1; x < area; x++) {
|
||||
character = NextPixel(x);
|
||||
int y = 0;
|
||||
if ((y = CheckHashtable(string_code, character)) != -1) {
|
||||
if ((y = CheckHashtable(string_code, character)) != -1)
|
||||
string_code = y;
|
||||
} else {
|
||||
else {
|
||||
AddToHashtable(string_code, character);
|
||||
OutputCode(string_code, BITS);
|
||||
|
||||
|
||||
if (next_code > max_code) {
|
||||
BITS++;
|
||||
if (BITS > 12) {
|
||||
OutputCode(clear_code, 12);
|
||||
BITS = code_size + 1;
|
||||
ResetHashtable();
|
||||
next_code = clear_code + 1; // this is different
|
||||
next_code = clear_code + 1;
|
||||
// this is different
|
||||
}
|
||||
max_code = (1 << BITS) - 1;
|
||||
}
|
||||
@@ -260,6 +280,7 @@ void GIFSave::WriteGIFImageData()
|
||||
next_code++;
|
||||
}
|
||||
}
|
||||
|
||||
OutputCode(string_code, BITS);
|
||||
OutputCode(end_code, BITS);
|
||||
OutputCode(0, BITS, true);
|
||||
@@ -270,7 +291,7 @@ void GIFSave::WriteGIFImageData()
|
||||
free(append_char);
|
||||
}
|
||||
|
||||
// OutputCode
|
||||
|
||||
void
|
||||
GIFSave::OutputCode(short code, int BITS, bool flush)
|
||||
{
|
||||
@@ -278,10 +299,10 @@ GIFSave::OutputCode(short code, int BITS, bool flush)
|
||||
bit_buffer |= (unsigned int) code << bit_count;
|
||||
bit_count += BITS;
|
||||
while (bit_count >= 8) {
|
||||
byte_buffer[byte_count + 1] = (unsigned char)(bit_buffer & 0xff);
|
||||
byte_count++;
|
||||
bit_buffer >>= 8;
|
||||
bit_count -= 8;
|
||||
byte_buffer[byte_count + 1] = (unsigned char)(bit_buffer & 0xff);
|
||||
byte_count++;
|
||||
bit_buffer >>= 8;
|
||||
bit_count -= 8;
|
||||
}
|
||||
if (byte_count >= 255) {
|
||||
byte_buffer[0] = 255;
|
||||
@@ -289,7 +310,8 @@ GIFSave::OutputCode(short code, int BITS, bool flush)
|
||||
if (byte_count == 256) {
|
||||
byte_buffer[1] = byte_buffer[256];
|
||||
byte_count = 1;
|
||||
} else byte_count = 0;
|
||||
} else
|
||||
byte_count = 0;
|
||||
}
|
||||
} else {
|
||||
bit_buffer |= (unsigned int) code << bit_count;
|
||||
@@ -307,7 +329,7 @@ GIFSave::OutputCode(short code, int BITS, bool flush)
|
||||
}
|
||||
}
|
||||
|
||||
// ResetHashtable
|
||||
|
||||
void
|
||||
GIFSave::ResetHashtable()
|
||||
{
|
||||
@@ -318,7 +340,7 @@ GIFSave::ResetHashtable()
|
||||
}
|
||||
}
|
||||
|
||||
// CheckHashtable
|
||||
|
||||
int
|
||||
GIFSave::CheckHashtable(int s, unsigned char c)
|
||||
{
|
||||
@@ -326,34 +348,40 @@ GIFSave::CheckHashtable(int s, unsigned char c)
|
||||
int hashindex = HASH(s, c);
|
||||
int nextindex;
|
||||
while ((nextindex = code_value[hashindex]) != -1) {
|
||||
if (prefix_code[nextindex] == s && append_char[nextindex] == c)
|
||||
return nextindex;
|
||||
hashindex = (hashindex + HASHSTEP) % HASHSIZE;
|
||||
}
|
||||
if (prefix_code[nextindex] == s && append_char[nextindex] == c)
|
||||
return nextindex;
|
||||
hashindex = (hashindex + HASHSTEP) % HASHSIZE;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// AddToHashtable
|
||||
|
||||
void
|
||||
GIFSave::AddToHashtable(int s, unsigned char c)
|
||||
{
|
||||
int hashindex = HASH(s, c);
|
||||
while (code_value[hashindex] != -1) hashindex = (hashindex + HASHSTEP) % HASHSIZE;
|
||||
code_value[hashindex] = next_code;
|
||||
prefix_code[next_code] = s;
|
||||
append_char[next_code] = c;
|
||||
int hashindex = HASH(s, c);
|
||||
while (code_value[hashindex] != -1)
|
||||
hashindex = (hashindex + HASHSTEP) % HASHSIZE;
|
||||
|
||||
code_value[hashindex] = next_code;
|
||||
prefix_code[next_code] = s;
|
||||
append_char[next_code] = c;
|
||||
}
|
||||
|
||||
// NextPixel
|
||||
|
||||
unsigned char
|
||||
GIFSave::NextPixel(int pixel)
|
||||
{
|
||||
int bpr = bitmap->BytesPerRow();
|
||||
color_space cs = bitmap->ColorSpace();
|
||||
bool useAlphaForTransparency =
|
||||
(fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO)
|
||||
(fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO)
|
||||
&& cs == B_RGBA32) || cs == B_RGBA32_BIG;
|
||||
unsigned char r, g, b, a;
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
unsigned char a;
|
||||
|
||||
if (cs == B_RGB32 || cs == B_RGBA32) {
|
||||
b = gifbits[0];
|
||||
@@ -374,7 +402,6 @@ GIFSave::NextPixel(int pixel)
|
||||
|| r != fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_RED)
|
||||
|| g != fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_GREEN)
|
||||
|| b != fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_BLUE)) {
|
||||
|
||||
if (fSettings->SetGetBool(GIF_SETTING_USE_DITHERING)) {
|
||||
if (pixel % width == 0)
|
||||
red_side_error = green_side_error = blue_side_error = 0;
|
||||
@@ -384,7 +411,7 @@ GIFSave::NextPixel(int pixel)
|
||||
r = min_c(255, max_c(0, r - red_side_error));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fSettings->SetGetBool(GIF_SETTING_INTERLACED)) {
|
||||
if (pos >= bpr) {
|
||||
pos = 0;
|
||||
@@ -393,17 +420,17 @@ GIFSave::NextPixel(int pixel)
|
||||
pass++;
|
||||
row = gs_pass_starts_at[pass];
|
||||
}
|
||||
gifbits = (unsigned char *)bitmap->Bits() + (bpr * row);
|
||||
gifbits = (unsigned char*)bitmap->Bits() + (bpr * row);
|
||||
}
|
||||
}
|
||||
/*
|
||||
#if 0
|
||||
unsigned int key = (r << 16) + (g << 8) + b;
|
||||
ColorCache *cc = (ColorCache *)hash->GetItem(key);
|
||||
ColorCache* cc = (ColorCache*)hash->GetItem(key);
|
||||
if (cc == NULL) {
|
||||
cc = new ColorCache();
|
||||
cc->key = key;
|
||||
cc->index = palette->IndexForColor(r, g, b);
|
||||
hash->AddItem((HashItem *)cc);
|
||||
hash->AddItem((HashItem*)cc);
|
||||
}
|
||||
|
||||
if (prefs->usedithering) {
|
||||
@@ -422,10 +449,13 @@ GIFSave::NextPixel(int pixel)
|
||||
int32 green_total_error = palette->pal[cc->index].green - g;
|
||||
int32 blue_total_error = palette->pal[cc->index].blue - b;
|
||||
|
||||
red_side_error = (red_error[x + 1] + (red_total_error * seven_sixteenth)) >> 15;
|
||||
blue_side_error = (blue_error[x + 1] + (blue_total_error * seven_sixteenth)) >> 15;
|
||||
green_side_error = (green_error[x + 1] + (green_total_error * seven_sixteenth)) >> 15;
|
||||
|
||||
red_side_error = (red_error[x + 1]
|
||||
+ (red_total_error * seven_sixteenth)) >> 15;
|
||||
blue_side_error = (blue_error[x + 1]
|
||||
+ (blue_total_error * seven_sixteenth)) >> 15;
|
||||
green_side_error = (green_error[x + 1]
|
||||
+ (green_total_error * seven_sixteenth)) >> 15;
|
||||
|
||||
red_error[x - 1] += (red_total_error * three_sixteenth);
|
||||
green_error[x - 1] += (green_total_error * three_sixteenth);
|
||||
blue_error[x - 1] += (blue_total_error * three_sixteenth);
|
||||
@@ -438,15 +468,17 @@ GIFSave::NextPixel(int pixel)
|
||||
green_error[x + 1] = (green_total_error * one_sixteenth);
|
||||
blue_error[x + 1] = (blue_total_error * one_sixteenth);
|
||||
}
|
||||
|
||||
return cc->index;*/
|
||||
|
||||
int index = palette->IndexForColor(r, g, b, useAlphaForTransparency ? a : 255);
|
||||
return cc->index;
|
||||
#endif
|
||||
|
||||
int index = palette->IndexForColor(r, g, b, useAlphaForTransparency
|
||||
? a : 255);
|
||||
|
||||
if (index != palette->TransparentIndex()
|
||||
&& fSettings->SetGetBool(GIF_SETTING_USE_DITHERING)) {
|
||||
int x = pixel % width;
|
||||
// Don't carry error on to next line when interlaced because
|
||||
// don't carry error on to next line when interlaced because
|
||||
// that line won't be adjacent, hence error is meaningless
|
||||
if (fSettings->SetGetBool(GIF_SETTING_INTERLACED) && x == width - 1) {
|
||||
for (int32 y = -1; y < width + 1; y++) {
|
||||
@@ -460,10 +492,13 @@ GIFSave::NextPixel(int pixel)
|
||||
int32 green_total_error = palette->pal[index].green - g;
|
||||
int32 blue_total_error = palette->pal[index].blue - b;
|
||||
|
||||
red_side_error = (red_error[x + 1] + (red_total_error * seven_sixteenth)) >> 15;
|
||||
blue_side_error = (blue_error[x + 1] + (blue_total_error * seven_sixteenth)) >> 15;
|
||||
green_side_error = (green_error[x + 1] + (green_total_error * seven_sixteenth)) >> 15;
|
||||
|
||||
red_side_error = (red_error[x + 1]
|
||||
+ (red_total_error * seven_sixteenth)) >> 15;
|
||||
blue_side_error = (blue_error[x + 1]
|
||||
+ (blue_total_error * seven_sixteenth)) >> 15;
|
||||
green_side_error = (green_error[x + 1]
|
||||
+ (green_total_error * seven_sixteenth)) >> 15;
|
||||
|
||||
red_error[x - 1] += (red_total_error * three_sixteenth);
|
||||
green_error[x - 1] += (green_total_error * three_sixteenth);
|
||||
blue_error[x - 1] += (blue_total_error * three_sixteenth);
|
||||
@@ -480,13 +515,14 @@ GIFSave::NextPixel(int pixel)
|
||||
return index;
|
||||
}
|
||||
|
||||
// InitFrame
|
||||
|
||||
void
|
||||
GIFSave::InitFrame()
|
||||
{
|
||||
code_size = palette->SizeInBits();
|
||||
if (code_size == 1)
|
||||
code_size++;
|
||||
|
||||
BITS = code_size + 1;
|
||||
clear_code = 1 << code_size;
|
||||
end_code = clear_code + 1;
|
||||
@@ -495,13 +531,13 @@ GIFSave::InitFrame()
|
||||
string_code = 0;
|
||||
character = 0;
|
||||
table_size = 1 << 12;
|
||||
|
||||
|
||||
bit_count = 0;
|
||||
bit_buffer = 0;
|
||||
byte_count = 0;
|
||||
|
||||
|
||||
pass = pos = 0;
|
||||
row = gs_pass_starts_at[0];
|
||||
|
||||
gifbits = (unsigned char *)bitmap->Bits();
|
||||
|
||||
gifbits = (unsigned char*)bitmap->Bits();
|
||||
}
|
||||
|
||||
@@ -13,8 +13,13 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GIFSAVE_H
|
||||
#define GIFSAVE_H
|
||||
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||
// Philippe Saint-Pierre, <[email protected]>
|
||||
// John Scipione, <[email protected]>
|
||||
|
||||
#ifndef GIF_SAVE_H
|
||||
#define GIF_SAVE_H
|
||||
|
||||
|
||||
#include <DataIO.h>
|
||||
#include <Bitmap.h>
|
||||
@@ -23,60 +28,77 @@
|
||||
|
||||
#include "GIFTranslator.h"
|
||||
|
||||
|
||||
#define HASHSIZE 9973
|
||||
#define HASHSTEP 2039
|
||||
|
||||
#define HASH(index, lastbyte) (((lastbyte << 8) ^ index) % HASHSIZE)
|
||||
|
||||
|
||||
class GIFSave {
|
||||
public:
|
||||
GIFSave(BBitmap* bitmap, BPositionIO* output, TranslatorSettings* settings);
|
||||
~GIFSave();
|
||||
public:
|
||||
GIFSave(BBitmap* bitmap, BPositionIO* output,
|
||||
TranslatorSettings* settings);
|
||||
virtual ~GIFSave();
|
||||
|
||||
bool fatalerror;
|
||||
bool fatalerror;
|
||||
|
||||
private:
|
||||
void WriteGIFHeader();
|
||||
void WriteGIFControlBlock();
|
||||
void WriteGIFImageHeader();
|
||||
void WriteGIFImageData();
|
||||
void OutputCode(short code, int BITS, bool flush=false);
|
||||
private:
|
||||
void WriteGIFHeader();
|
||||
void WriteGIFControlBlock();
|
||||
void WriteGIFImageHeader();
|
||||
void WriteGIFImageData();
|
||||
void OutputCode(short code, int BITS,
|
||||
bool flush = false);
|
||||
|
||||
unsigned char NextPixel(int pixel);
|
||||
void InitFrame();
|
||||
void ResetHashtable();
|
||||
int CheckHashtable(int s, unsigned char c);
|
||||
void AddToHashtable(int s, unsigned char c);
|
||||
|
||||
BPositionIO *output;
|
||||
BBitmap *bitmap;
|
||||
SavePalette *palette;
|
||||
SFHash *hash;
|
||||
TranslatorSettings *fSettings;
|
||||
|
||||
short *code_value, *prefix_code;
|
||||
unsigned char *append_char;
|
||||
int BITS, max_code;
|
||||
char code_size;
|
||||
short clear_code, end_code, next_code;
|
||||
int string_code;
|
||||
unsigned char character;
|
||||
int table_size;
|
||||
|
||||
int bit_count;
|
||||
unsigned int bit_buffer;
|
||||
int byte_count;
|
||||
unsigned char byte_buffer[257];
|
||||
int pass, row, pos;
|
||||
unsigned char NextPixel(int pixel);
|
||||
void InitFrame();
|
||||
void ResetHashtable();
|
||||
int CheckHashtable(int s, unsigned char c);
|
||||
void AddToHashtable(int s, unsigned char c);
|
||||
|
||||
BPositionIO* output;
|
||||
BBitmap* bitmap;
|
||||
SavePalette* palette;
|
||||
SFHash* hash;
|
||||
TranslatorSettings* fSettings;
|
||||
|
||||
short* code_value;
|
||||
short* prefix_code;
|
||||
|
||||
unsigned char* append_char;
|
||||
int BITS;
|
||||
int max_code;
|
||||
char code_size;
|
||||
short clear_code;
|
||||
short end_code;
|
||||
short next_code;
|
||||
int string_code;
|
||||
unsigned char character;
|
||||
int table_size;
|
||||
|
||||
int bit_count;
|
||||
unsigned int bit_buffer;
|
||||
int byte_count;
|
||||
unsigned char byte_buffer[257];
|
||||
int pass;
|
||||
int row;
|
||||
int pos;
|
||||
|
||||
unsigned char* gifbits;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
unsigned char *gifbits;
|
||||
|
||||
int width, height;
|
||||
|
||||
// For dithering
|
||||
int32 *red_error, *green_error, *blue_error;
|
||||
int16 red_side_error, green_side_error, blue_side_error;
|
||||
int32* red_error;
|
||||
int32* green_error;
|
||||
int32* blue_error;
|
||||
|
||||
int16 red_side_error;
|
||||
int16 green_side_error;
|
||||
int16 blue_side_error;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // GIF_SAVE_H
|
||||
|
||||
@@ -12,12 +12,16 @@
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||
|
||||
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||
// John Scipione, <[email protected]>
|
||||
|
||||
#include "GIFTranslator.h"
|
||||
#include "GIFView.h"
|
||||
#include "GIFSave.h"
|
||||
#include "GIFLoad.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <Application.h>
|
||||
#include <ByteOrder.h>
|
||||
@@ -28,13 +32,12 @@
|
||||
#include <TranslatorAddOn.h>
|
||||
#include <TranslatorFormats.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "GIFView.h"
|
||||
#include "GIFSave.h"
|
||||
#include "GIFLoad.h"
|
||||
#include "TranslatorWindow.h"
|
||||
|
||||
|
||||
#ifndef GIF_TYPE
|
||||
#define GIF_TYPE 'GIF '
|
||||
#endif
|
||||
@@ -43,40 +46,64 @@
|
||||
#define B_TRANSLATION_CONTEXT "GIFTranslator"
|
||||
|
||||
|
||||
// This global will be externed in other files - set once here
|
||||
// for the entire translator
|
||||
bool debug = false;
|
||||
// this global will be externed in other files - set once here
|
||||
// for the entire translator
|
||||
|
||||
bool DetermineType(BPositionIO *source, bool *is_gif);
|
||||
status_t GetBitmap(BPositionIO *in, BBitmap **out);
|
||||
bool DetermineType(BPositionIO* source, bool* isGif);
|
||||
status_t GetBitmap(BPositionIO* in, BBitmap** out);
|
||||
|
||||
static const translation_format sInputFormats[] = {
|
||||
{ GIF_TYPE, B_TRANSLATOR_BITMAP, GIF_IN_QUALITY, GIF_IN_CAPABILITY,
|
||||
"image/gif", "GIF image" },
|
||||
{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, BBM_IN_QUALITY, BBM_IN_CAPABILITY,
|
||||
"image/x-be-bitmap", "Be Bitmap Format (GIFTranslator)" }
|
||||
{
|
||||
GIF_TYPE,
|
||||
B_TRANSLATOR_BITMAP,
|
||||
GIF_IN_QUALITY,
|
||||
GIF_IN_CAPABILITY,
|
||||
"image/gif",
|
||||
"GIF image"
|
||||
},
|
||||
{
|
||||
B_TRANSLATOR_BITMAP,
|
||||
B_TRANSLATOR_BITMAP,
|
||||
BBM_IN_QUALITY,
|
||||
BBM_IN_CAPABILITY,
|
||||
"image/x-be-bitmap",
|
||||
"Be Bitmap Format (GIFTranslator)"
|
||||
}
|
||||
};
|
||||
|
||||
static const translation_format sOutputFormats[] = {
|
||||
{ GIF_TYPE, B_TRANSLATOR_BITMAP, GIF_OUT_QUALITY, GIF_OUT_CAPABILITY, "image/gif",
|
||||
"GIF image" },
|
||||
{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, BBM_OUT_QUALITY, BBM_OUT_CAPABILITY,
|
||||
"image/x-be-bitmap", "Be Bitmap Format (GIFTranslator)" }
|
||||
{
|
||||
GIF_TYPE,
|
||||
B_TRANSLATOR_BITMAP,
|
||||
GIF_OUT_QUALITY,
|
||||
GIF_OUT_CAPABILITY,
|
||||
"image/gif",
|
||||
"GIF image"
|
||||
},
|
||||
{
|
||||
B_TRANSLATOR_BITMAP,
|
||||
B_TRANSLATOR_BITMAP,
|
||||
BBM_OUT_QUALITY,
|
||||
BBM_OUT_CAPABILITY,
|
||||
"image/x-be-bitmap",
|
||||
"Be Bitmap Format (GIFTranslator)"
|
||||
}
|
||||
};
|
||||
|
||||
// Default settings for the Translator
|
||||
static const TranSetting sDefaultSettings[] = {
|
||||
{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
|
||||
{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false},
|
||||
{GIF_SETTING_INTERLACED, TRAN_SETTING_BOOL, false},
|
||||
{GIF_SETTING_USE_TRANSPARENT, TRAN_SETTING_BOOL, false},
|
||||
{GIF_SETTING_USE_TRANSPARENT_AUTO, TRAN_SETTING_BOOL, false},
|
||||
{GIF_SETTING_USE_DITHERING, TRAN_SETTING_BOOL, false},
|
||||
{GIF_SETTING_PALETTE_MODE, TRAN_SETTING_INT32, 0},
|
||||
{GIF_SETTING_PALETTE_SIZE, TRAN_SETTING_INT32, 8},
|
||||
{GIF_SETTING_TRANSPARENT_RED, TRAN_SETTING_INT32, 0},
|
||||
{GIF_SETTING_TRANSPARENT_GREEN, TRAN_SETTING_INT32, 0},
|
||||
{GIF_SETTING_TRANSPARENT_BLUE, TRAN_SETTING_INT32, 0}
|
||||
{ B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false },
|
||||
{ B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false },
|
||||
{ GIF_SETTING_INTERLACED, TRAN_SETTING_BOOL, false },
|
||||
{ GIF_SETTING_USE_TRANSPARENT, TRAN_SETTING_BOOL, false },
|
||||
{ GIF_SETTING_USE_TRANSPARENT_AUTO, TRAN_SETTING_BOOL, false },
|
||||
{ GIF_SETTING_USE_DITHERING, TRAN_SETTING_BOOL, false },
|
||||
{ GIF_SETTING_PALETTE_MODE, TRAN_SETTING_INT32, 0 },
|
||||
{ GIF_SETTING_PALETTE_SIZE, TRAN_SETTING_INT32, 8 },
|
||||
{ GIF_SETTING_TRANSPARENT_RED, TRAN_SETTING_INT32, 0 },
|
||||
{ GIF_SETTING_TRANSPARENT_GREEN, TRAN_SETTING_INT32, 0 },
|
||||
{ GIF_SETTING_TRANSPARENT_BLUE, TRAN_SETTING_INT32, 0 }
|
||||
};
|
||||
|
||||
const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
|
||||
@@ -85,31 +112,35 @@ const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting
|
||||
|
||||
|
||||
/* Look at first few bytes in stream to determine type - throw it back
|
||||
if it is not a GIF or a BBitmap that we understand */
|
||||
* if it is not a GIF or a BBitmap that we understand.
|
||||
*/
|
||||
bool
|
||||
DetermineType(BPositionIO *source, bool *is_gif)
|
||||
DetermineType(BPositionIO* source, bool* isGif)
|
||||
{
|
||||
unsigned char header[7];
|
||||
*is_gif = true;
|
||||
*isGif = true;
|
||||
if (source->Read(header, 6) != 6)
|
||||
return false;
|
||||
header[6] = 0x00;
|
||||
|
||||
if (strcmp((char *)header, "GIF87a") != 0 && strcmp((char *)header,
|
||||
"GIF89a") != 0) {
|
||||
*is_gif = false;
|
||||
int32 magic = (header[0] << 24) + (header[1] << 16) + (header[2] << 8)
|
||||
if (strcmp((char*)header, "GIF87a") != 0
|
||||
&& strcmp((char*)header, "GIF89a") != 0) {
|
||||
*isGif = false;
|
||||
int32 magic = (header[0] << 24) + (header[1] << 16) + (header[2] << 8)
|
||||
+ header[3];
|
||||
if (magic != B_TRANSLATOR_BITMAP)
|
||||
return false;
|
||||
|
||||
source->Seek(5 * 4 - 2, SEEK_CUR);
|
||||
color_space cs;
|
||||
if (source->Read(&cs, 4) != 4)
|
||||
return false;
|
||||
|
||||
cs = (color_space)B_BENDIAN_TO_HOST_INT32(cs);
|
||||
if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG
|
||||
&& cs != B_RGBA32_BIG)
|
||||
&& cs != B_RGBA32_BIG) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
source->Seek(0, SEEK_SET);
|
||||
@@ -117,12 +148,10 @@ DetermineType(BPositionIO *source, bool *is_gif)
|
||||
}
|
||||
|
||||
|
||||
/* Dump data from stream into a BBitmap */
|
||||
status_t
|
||||
GetBitmap(BPositionIO *in, BBitmap **out)
|
||||
GetBitmap(BPositionIO* in, BBitmap** out)
|
||||
{
|
||||
TranslatorBitmap header;
|
||||
|
||||
status_t err = in->Read(&header, sizeof(header));
|
||||
if (err != sizeof(header))
|
||||
return B_IO_ERROR;
|
||||
@@ -136,15 +165,18 @@ GetBitmap(BPositionIO *in, BBitmap **out)
|
||||
header.colors = (color_space)B_BENDIAN_TO_HOST_INT32(header.colors);
|
||||
header.dataSize = B_BENDIAN_TO_HOST_INT32(header.dataSize);
|
||||
|
||||
// dump data from stream into a BBitmap
|
||||
BBitmap* bitmap = new(std::nothrow) BBitmap(header.bounds, header.colors);
|
||||
*out = bitmap;
|
||||
if (bitmap == NULL)
|
||||
return B_NO_MEMORY;
|
||||
unsigned char *bits = (unsigned char *)bitmap->Bits();
|
||||
|
||||
unsigned char* bits = (unsigned char*)bitmap->Bits();
|
||||
if (bits == NULL) {
|
||||
delete bitmap;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
err = in->Read(bits, header.dataSize);
|
||||
if (err == (status_t)header.dataSize)
|
||||
return B_OK;
|
||||
@@ -155,29 +187,31 @@ GetBitmap(BPositionIO *in, BBitmap **out)
|
||||
}
|
||||
|
||||
|
||||
/* Required Identify function - may need to read entire header, not sure */
|
||||
status_t
|
||||
GIFTranslator::DerivedIdentify(BPositionIO* inSource,
|
||||
const translation_format* inFormat, BMessage* ioExtension,
|
||||
translator_info* outInfo, uint32 outType)
|
||||
{
|
||||
const char *debug_text = getenv("GIF_TRANSLATOR_DEBUG");
|
||||
// Required identify function - may need to read entire header, not sure
|
||||
const char* debug_text = getenv("GIF_TRANSLATOR_DEBUG");
|
||||
if (debug_text != NULL && atoi(debug_text) != 0)
|
||||
debug = true;
|
||||
|
||||
if (outType == 0)
|
||||
outType = B_TRANSLATOR_BITMAP;
|
||||
|
||||
if (outType != GIF_TYPE && outType != B_TRANSLATOR_BITMAP)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
bool is_gif;
|
||||
if (!DetermineType(inSource, &is_gif))
|
||||
bool isGif;
|
||||
if (!DetermineType(inSource, &isGif))
|
||||
return B_NO_TRANSLATOR;
|
||||
if (!is_gif && inFormat != NULL && inFormat->type != B_TRANSLATOR_BITMAP)
|
||||
|
||||
if (!isGif && inFormat != NULL && inFormat->type != B_TRANSLATOR_BITMAP)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
outInfo->group = B_TRANSLATOR_BITMAP;
|
||||
if (is_gif) {
|
||||
if (isGif) {
|
||||
outInfo->type = GIF_TYPE;
|
||||
outInfo->quality = GIF_IN_QUALITY;
|
||||
outInfo->capability = GIF_IN_CAPABILITY;
|
||||
@@ -191,57 +225,68 @@ GIFTranslator::DerivedIdentify(BPositionIO* inSource,
|
||||
sizeof(outInfo->name));
|
||||
strcpy(outInfo->MIME, "image/x-be-bitmap");
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Main required function - assumes that an incoming GIF must be translated
|
||||
to a BBitmap, and vice versa - this could be improved */
|
||||
* to a BBitmap, and vice versa - this could be improved
|
||||
*/
|
||||
status_t
|
||||
GIFTranslator::DerivedTranslate(BPositionIO* inSource,
|
||||
const translator_info* inInfo, BMessage* ioExtension, uint32 outType,
|
||||
BPositionIO* outDestination, int32 baseType)
|
||||
{
|
||||
const char* debug_text = getenv("GIF_TRANSLATOR_DEBUG");
|
||||
if ((debug_text != NULL) && (atoi(debug_text) != 0)) debug = true;
|
||||
if (debug_text != NULL && atoi(debug_text) != 0)
|
||||
debug = true;
|
||||
|
||||
if (outType == 0) outType = B_TRANSLATOR_BITMAP;
|
||||
if (outType != GIF_TYPE && outType != B_TRANSLATOR_BITMAP) {
|
||||
if (outType == 0)
|
||||
outType = B_TRANSLATOR_BITMAP;
|
||||
|
||||
if (outType != GIF_TYPE && outType != B_TRANSLATOR_BITMAP)
|
||||
return B_NO_TRANSLATOR;
|
||||
}
|
||||
|
||||
bool is_gif;
|
||||
if (!DetermineType(inSource, &is_gif)) return B_NO_TRANSLATOR;
|
||||
if (!is_gif && inInfo->type != B_TRANSLATOR_BITMAP) return B_NO_TRANSLATOR;
|
||||
bool isGif;
|
||||
if (!DetermineType(inSource, &isGif))
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
if (!isGif && inInfo->type != B_TRANSLATOR_BITMAP)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
status_t err = B_OK;
|
||||
bigtime_t now = system_time();
|
||||
// Going from BBitmap to GIF
|
||||
if (!is_gif) {
|
||||
BBitmap *bitmap = NULL;
|
||||
|
||||
if (!isGif) {
|
||||
// BBitmap to GIF
|
||||
BBitmap* bitmap = NULL;
|
||||
err = GetBitmap(inSource, &bitmap);
|
||||
if (err != B_OK)
|
||||
return err;
|
||||
GIFSave* gs = new GIFSave(bitmap, outDestination, fSettings);
|
||||
if (gs->fatalerror) {
|
||||
delete gs;
|
||||
|
||||
GIFSave* gitSave = new GIFSave(bitmap, outDestination, fSettings);
|
||||
if (gitSave->fatalerror) {
|
||||
delete gitSave;
|
||||
delete bitmap;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
delete gs;
|
||||
delete gitSave;
|
||||
delete bitmap;
|
||||
} else { // GIF to BBitmap
|
||||
GIFLoad *gl = new GIFLoad(inSource, outDestination);
|
||||
if (gl->fatalerror) {
|
||||
delete gl;
|
||||
} else {
|
||||
// GIF to BBitmap
|
||||
GIFLoad* gifLoad = new GIFLoad(inSource, outDestination);
|
||||
if (gifLoad->fatalerror) {
|
||||
delete gifLoad;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
delete gl;
|
||||
delete gifLoad;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
now = system_time() - now;
|
||||
syslog(LOG_ERR, "Translate() - Translation took %Ld microseconds\n", now);
|
||||
syslog(LOG_ERR, "Translate() - Translation took %Ld microseconds\n",
|
||||
now);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
@@ -250,22 +295,23 @@ GIFTranslator::DerivedTranslate(BPositionIO* inSource,
|
||||
BTranslator*
|
||||
make_nth_translator(int32 n, image_id you, uint32 flags, ...)
|
||||
{
|
||||
if (n == 0)
|
||||
return new GIFTranslator();
|
||||
if (n == 0)
|
||||
return new GIFTranslator();
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
GIFTranslator::GIFTranslator()
|
||||
: BaseTranslator(B_TRANSLATE("GIF images"),
|
||||
B_TRANSLATE("GIF image translator"),
|
||||
GIF_TRANSLATOR_VERSION,
|
||||
sInputFormats, kNumInputFormats,
|
||||
sOutputFormats, kNumOutputFormats,
|
||||
"GIFTranslator_Settings",
|
||||
sDefaultSettings, kNumDefaultSettings,
|
||||
B_TRANSLATOR_BITMAP, B_GIF_FORMAT)
|
||||
:
|
||||
BaseTranslator(B_TRANSLATE("GIF images"),
|
||||
B_TRANSLATE("GIF image translator"),
|
||||
GIF_TRANSLATOR_VERSION,
|
||||
sInputFormats, kNumInputFormats,
|
||||
sOutputFormats, kNumOutputFormats,
|
||||
"GIFTranslator_Settings",
|
||||
sDefaultSettings, kNumDefaultSettings,
|
||||
B_TRANSLATOR_BITMAP, B_GIF_FORMAT)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -276,7 +322,7 @@ GIFTranslator::~GIFTranslator()
|
||||
|
||||
|
||||
BView*
|
||||
GIFTranslator::NewConfigView(TranslatorSettings *settings)
|
||||
GIFTranslator::NewConfigView(TranslatorSettings* settings)
|
||||
{
|
||||
return new GIFView(settings);
|
||||
}
|
||||
@@ -285,13 +331,13 @@ GIFTranslator::NewConfigView(TranslatorSettings *settings)
|
||||
int
|
||||
main()
|
||||
{
|
||||
BApplication app("application/x-vnd.Haiku-GIFTranslator");
|
||||
status_t result;
|
||||
result = LaunchTranslatorWindow(new GIFTranslator,
|
||||
B_TRANSLATE("GIF Settings"), kRectView);
|
||||
if (result == B_OK) {
|
||||
app.Run();
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
BApplication app("application/x-vnd.Haiku-GIFTranslator");
|
||||
status_t result = LaunchTranslatorWindow(new GIFTranslator,
|
||||
B_TRANSLATE("GIF Settings"), kRectView);
|
||||
if (result == B_OK) {
|
||||
app.Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -13,11 +13,15 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GIFTRANSLATOR_H
|
||||
#define GIFTRANSLATOR_H
|
||||
// Additional authors: John Scipione, <[email protected]>
|
||||
|
||||
#ifndef GIF_TRANSLATOR_H
|
||||
#define GIF_TRANSLATOR_H
|
||||
|
||||
|
||||
#include "BaseTranslator.h"
|
||||
|
||||
|
||||
#define GIF_IN_QUALITY 0.8
|
||||
#define GIF_IN_CAPABILITY 0.8
|
||||
#define BBM_IN_QUALITY 0.3
|
||||
@@ -28,6 +32,8 @@
|
||||
#define BBM_OUT_QUALITY 0.3
|
||||
#define BBM_OUT_CAPABILITY 0.3
|
||||
|
||||
#define GIF_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(1, 5, 0)
|
||||
|
||||
// settings
|
||||
|
||||
#define GIF_SETTING_INTERLACED "interlaced"
|
||||
@@ -41,24 +47,25 @@
|
||||
#define GIF_SETTING_TRANSPARENT_BLUE "transparent blue"
|
||||
|
||||
|
||||
#define GIF_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(1,5,0)
|
||||
|
||||
class GIFTranslator : public BaseTranslator {
|
||||
public:
|
||||
GIFTranslator();
|
||||
virtual status_t DerivedIdentify(BPositionIO* inSource,
|
||||
const translation_format* inFormat, BMessage* ioExtension,
|
||||
translator_info* outInfo, uint32 outType);
|
||||
public:
|
||||
GIFTranslator();
|
||||
virtual status_t DerivedIdentify(BPositionIO* inSource,
|
||||
const translation_format* inFormat,
|
||||
BMessage* ioExtension,
|
||||
translator_info* outInfo, uint32 outType);
|
||||
|
||||
virtual status_t DerivedTranslate(BPositionIO* inSource,
|
||||
const translator_info* inInfo, BMessage* ioExtension,
|
||||
uint32 outType, BPositionIO* outDestination, int32 baseType);
|
||||
|
||||
virtual BView* NewConfigView(TranslatorSettings* settings);
|
||||
|
||||
protected:
|
||||
virtual ~GIFTranslator();
|
||||
virtual status_t DerivedTranslate(BPositionIO* inSource,
|
||||
const translator_info* inInfo,
|
||||
BMessage* ioExtension,
|
||||
uint32 outType, BPositionIO* outDestination,
|
||||
int32 baseType);
|
||||
|
||||
virtual BView* NewConfigView(TranslatorSettings* settings);
|
||||
|
||||
protected:
|
||||
virtual ~GIFTranslator();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // GIF_TRANSLATOR_H
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||
// Maxime Simon, <maxime.simon@gmail.com>
|
||||
// Philippe Saint-Pierre, <stpere@gmail.com>
|
||||
// Philippe Saint-Pierre, <stpere@gmail.com>
|
||||
// Maxime Simon, <maxime.simon@gmail.com>
|
||||
// John Scipione, <[email protected]>
|
||||
|
||||
#include "GIFView.h"
|
||||
#include "GIFTranslator.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -28,13 +28,14 @@
|
||||
#include <LayoutBuilder.h>
|
||||
#include <String.h>
|
||||
|
||||
#include "GIFTranslator.h"
|
||||
#include "SavePalette.h"
|
||||
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
#define B_TRANSLATION_CONTEXT "GIFView"
|
||||
|
||||
|
||||
// constructor
|
||||
GIFView::GIFView(TranslatorSettings* settings)
|
||||
:
|
||||
BView("GIFView", B_WILL_DRAW),
|
||||
@@ -42,20 +43,23 @@ GIFView::GIFView(TranslatorSettings* settings)
|
||||
{
|
||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
|
||||
BStringView *title = new BStringView("Title", B_TRANSLATE("GIF image translator"));
|
||||
BStringView* title = new BStringView("Title",
|
||||
B_TRANSLATE("GIF image translator"));
|
||||
title->SetFont(be_bold_font);
|
||||
|
||||
char version_string[100];
|
||||
snprintf(version_string, sizeof(version_string), B_TRANSLATE("v%d.%d.%d %s"),
|
||||
int(B_TRANSLATION_MAJOR_VERSION(GIF_TRANSLATOR_VERSION)),
|
||||
int(B_TRANSLATION_MINOR_VERSION(GIF_TRANSLATOR_VERSION)),
|
||||
int(B_TRANSLATION_REVISION_VERSION(GIF_TRANSLATOR_VERSION)),
|
||||
__DATE__);
|
||||
char version_string[100];
|
||||
snprintf(version_string, sizeof(version_string),
|
||||
B_TRANSLATE("v%d.%d.%d %s"),
|
||||
int(B_TRANSLATION_MAJOR_VERSION(GIF_TRANSLATOR_VERSION)),
|
||||
int(B_TRANSLATION_MINOR_VERSION(GIF_TRANSLATOR_VERSION)),
|
||||
int(B_TRANSLATION_REVISION_VERSION(GIF_TRANSLATOR_VERSION)),
|
||||
__DATE__);
|
||||
|
||||
BStringView *version = new BStringView("Version", version_string);
|
||||
BStringView* version = new BStringView("Version", version_string);
|
||||
|
||||
const char *copyrightString = "©2003 Daniel Switkin, [email protected]";
|
||||
BStringView *copyright = new BStringView("Copyright", copyrightString);
|
||||
const char* copyrightString
|
||||
= "©2003 Daniel Switkin, [email protected]";
|
||||
BStringView* copyright = new BStringView("Copyright", copyrightString);
|
||||
|
||||
// menu fields (Palette & Colors)
|
||||
fWebSafeMI = new BMenuItem(B_TRANSLATE("Websafe"),
|
||||
@@ -66,7 +70,8 @@ GIFView::GIFView(TranslatorSettings* settings)
|
||||
new BMessage(GV_GREYSCALE), 0, 0);
|
||||
fOptimalMI = new BMenuItem(B_TRANSLATE("Optimal"),
|
||||
new BMessage(GV_OPTIMAL), 0, 0);
|
||||
fPaletteM = new BPopUpMenu("PalettePopUpMenu", true, true, B_ITEMS_IN_COLUMN);
|
||||
fPaletteM = new BPopUpMenu("PalettePopUpMenu", true, true,
|
||||
B_ITEMS_IN_COLUMN);
|
||||
fPaletteM->AddItem(fWebSafeMI);
|
||||
fPaletteM->AddItem(fBeOSSystemMI);
|
||||
fPaletteM->AddItem(fGreyScaleMI);
|
||||
@@ -86,34 +91,37 @@ GIFView::GIFView(TranslatorSettings* settings)
|
||||
}
|
||||
fColorCount256MI = fColorCountMI[7];
|
||||
|
||||
fPaletteMF = new BMenuField(B_TRANSLATE("Palette"), fPaletteM);
|
||||
fColorCountMF = new BMenuField(B_TRANSLATE("Colors"), fColorCountM);
|
||||
fPaletteMF = new BMenuField(B_TRANSLATE("Palette"), fPaletteM);
|
||||
fColorCountMF = new BMenuField(B_TRANSLATE("Colors"), fColorCountM);
|
||||
|
||||
// check boxes
|
||||
fUseDitheringCB = new BCheckBox(B_TRANSLATE("Use dithering"),
|
||||
new BMessage(GV_USE_DITHERING));
|
||||
// check boxes
|
||||
fUseDitheringCB = new BCheckBox(B_TRANSLATE("Use dithering"),
|
||||
new BMessage(GV_USE_DITHERING));
|
||||
|
||||
fInterlacedCB = new BCheckBox(B_TRANSLATE("Write interlaced images"),
|
||||
new BMessage(GV_INTERLACED));
|
||||
fInterlacedCB = new BCheckBox(B_TRANSLATE("Write interlaced images"),
|
||||
new BMessage(GV_INTERLACED));
|
||||
|
||||
fUseTransparentCB = new BCheckBox(B_TRANSLATE("Write transparent images"),
|
||||
new BMessage(GV_USE_TRANSPARENT));
|
||||
fUseTransparentCB = new BCheckBox(B_TRANSLATE("Write transparent images"),
|
||||
new BMessage(GV_USE_TRANSPARENT));
|
||||
|
||||
// radio buttons
|
||||
fUseTransparentAutoRB = new BRadioButton(
|
||||
B_TRANSLATE("Automatic (from alpha channel)"),
|
||||
new BMessage(GV_USE_TRANSPARENT_AUTO));
|
||||
// radio buttons
|
||||
fUseTransparentAutoRB = new BRadioButton(
|
||||
B_TRANSLATE("Automatic (from alpha channel)"),
|
||||
new BMessage(GV_USE_TRANSPARENT_AUTO));
|
||||
|
||||
fUseTransparentColorRB = new BRadioButton(B_TRANSLATE("Use RGB color"),
|
||||
new BMessage(GV_USE_TRANSPARENT_COLOR));
|
||||
fUseTransparentColorRB = new BRadioButton(B_TRANSLATE("Use RGB color"),
|
||||
new BMessage(GV_USE_TRANSPARENT_COLOR));
|
||||
|
||||
fTransparentRedTC = new BTextControl("", "0", new BMessage(GV_TRANSPARENT_RED));
|
||||
fTransparentGreenTC = new BTextControl("", "0", new BMessage(GV_TRANSPARENT_GREEN));
|
||||
fTransparentBlueTC = new BTextControl("", "0", new BMessage(GV_TRANSPARENT_BLUE));
|
||||
fTransparentRedTC = new BTextControl("", "0",
|
||||
new BMessage(GV_TRANSPARENT_RED));
|
||||
fTransparentGreenTC = new BTextControl("", "0",
|
||||
new BMessage(GV_TRANSPARENT_GREEN));
|
||||
fTransparentBlueTC = new BTextControl("", "0",
|
||||
new BMessage(GV_TRANSPARENT_BLUE));
|
||||
|
||||
BTextView *tr = fTransparentRedTC->TextView();
|
||||
BTextView *tg = fTransparentGreenTC->TextView();
|
||||
BTextView *tb = fTransparentBlueTC->TextView();
|
||||
BTextView* tr = fTransparentRedTC->TextView();
|
||||
BTextView* tg = fTransparentGreenTC->TextView();
|
||||
BTextView* tb = fTransparentBlueTC->TextView();
|
||||
|
||||
for (uint32 x = 0; x < 256; x++) {
|
||||
if (x < '0' || x > '9') {
|
||||
@@ -134,10 +142,10 @@ GIFView::GIFView(TranslatorSettings* settings)
|
||||
|
||||
.AddGrid(10, 10)
|
||||
.Add(fPaletteMF->CreateLabelLayoutItem(), 0, 0)
|
||||
.Add(fPaletteMF->CreateMenuBarLayoutItem(), 1, 0)
|
||||
.Add(fPaletteMF->CreateMenuBarLayoutItem(), 1, 0)
|
||||
|
||||
.Add(fColorCountMF->CreateLabelLayoutItem(), 0, 1)
|
||||
.Add(fColorCountMF->CreateMenuBarLayoutItem(), 1, 1)
|
||||
.Add(fColorCountMF->CreateMenuBarLayoutItem(), 1, 1)
|
||||
.End()
|
||||
.AddGlue()
|
||||
|
||||
@@ -156,7 +164,8 @@ GIFView::GIFView(TranslatorSettings* settings)
|
||||
|
||||
BFont font;
|
||||
GetFont(&font);
|
||||
SetExplicitPreferredSize(BSize((font.Size() * 400)/12, (font.Size() * 300)/12));
|
||||
SetExplicitPreferredSize(BSize((font.Size() * 400) / 12,
|
||||
(font.Size() * 300) / 12));
|
||||
|
||||
RestorePrefs();
|
||||
}
|
||||
@@ -178,23 +187,26 @@ GIFView::RestorePrefs()
|
||||
case WEB_SAFE_PALETTE:
|
||||
fWebSafeMI->SetMarked(true);
|
||||
break;
|
||||
|
||||
case BEOS_SYSTEM_PALETTE:
|
||||
fBeOSSystemMI->SetMarked(true);
|
||||
break;
|
||||
|
||||
case GREYSCALE_PALETTE:
|
||||
fGreyScaleMI->SetMarked(true);
|
||||
fUseDitheringCB->SetEnabled(false);
|
||||
break;
|
||||
|
||||
case OPTIMAL_PALETTE:
|
||||
fOptimalMI->SetMarked(true);
|
||||
fColorCountMF->SetEnabled(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
int32 value = WEB_SAFE_PALETTE;
|
||||
fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE, &value);
|
||||
fSettings->SaveSettings();
|
||||
fWebSafeMI->SetMarked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fColorCountMF->IsEnabled()
|
||||
@@ -215,9 +227,10 @@ GIFView::RestorePrefs()
|
||||
|
||||
if (fGreyScaleMI->IsMarked())
|
||||
fUseDitheringCB->SetValue(false);
|
||||
else
|
||||
else {
|
||||
fUseDitheringCB->SetValue(
|
||||
fSettings->SetGetBool(GIF_SETTING_USE_DITHERING));
|
||||
}
|
||||
fUseTransparentCB->SetValue(
|
||||
fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT));
|
||||
fUseTransparentAutoRB->SetValue(
|
||||
@@ -254,7 +267,6 @@ GIFView::RestorePrefs()
|
||||
}
|
||||
|
||||
|
||||
// AllAttached
|
||||
void
|
||||
GIFView::AllAttached()
|
||||
{
|
||||
@@ -273,9 +285,8 @@ GIFView::AllAttached()
|
||||
}
|
||||
|
||||
|
||||
// MessageReceived
|
||||
void
|
||||
GIFView::MessageReceived(BMessage *message)
|
||||
GIFView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case GV_WEB_SAFE:
|
||||
@@ -287,6 +298,7 @@ GIFView::MessageReceived(BMessage *message)
|
||||
fColorCount256MI->SetMarked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case GV_BEOS_SYSTEM:
|
||||
{
|
||||
int32 value = BEOS_SYSTEM_PALETTE;
|
||||
@@ -296,6 +308,7 @@ GIFView::MessageReceived(BMessage *message)
|
||||
fColorCount256MI->SetMarked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case GV_GREYSCALE:
|
||||
{
|
||||
int32 value = GREYSCALE_PALETTE;
|
||||
@@ -308,6 +321,7 @@ GIFView::MessageReceived(BMessage *message)
|
||||
fColorCount256MI->SetMarked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case GV_OPTIMAL:
|
||||
{
|
||||
int32 value = OPTIMAL_PALETTE;
|
||||
@@ -318,6 +332,7 @@ GIFView::MessageReceived(BMessage *message)
|
||||
->SetMarked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case GV_SET_COLOR_COUNT:
|
||||
if (fColorCountMF->IsEnabled()) {
|
||||
int32 sizeInBits;
|
||||
@@ -329,18 +344,21 @@ GIFView::MessageReceived(BMessage *message)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GV_INTERLACED:
|
||||
{
|
||||
bool value = fInterlacedCB->Value();
|
||||
fSettings->SetGetBool(GIF_SETTING_INTERLACED, &value);
|
||||
break;
|
||||
}
|
||||
|
||||
case GV_USE_DITHERING:
|
||||
{
|
||||
bool value = fUseDitheringCB->Value();
|
||||
fSettings->SetGetBool(GIF_SETTING_USE_DITHERING, &value);
|
||||
break;
|
||||
}
|
||||
|
||||
case GV_USE_TRANSPARENT:
|
||||
{
|
||||
bool value = fUseTransparentCB->Value();
|
||||
@@ -360,6 +378,7 @@ GIFView::MessageReceived(BMessage *message)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case GV_USE_TRANSPARENT_AUTO:
|
||||
{
|
||||
bool value = true;
|
||||
@@ -369,6 +388,7 @@ GIFView::MessageReceived(BMessage *message)
|
||||
fTransparentBlueTC->SetEnabled(false);
|
||||
break;
|
||||
}
|
||||
|
||||
case GV_USE_TRANSPARENT_COLOR:
|
||||
{
|
||||
bool value = false;
|
||||
@@ -378,33 +398,37 @@ GIFView::MessageReceived(BMessage *message)
|
||||
fTransparentBlueTC->SetEnabled(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case GV_TRANSPARENT_RED:
|
||||
{
|
||||
int32 value = CheckInput(fTransparentRedTC);
|
||||
fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_RED, &value);
|
||||
break;
|
||||
}
|
||||
|
||||
case GV_TRANSPARENT_GREEN:
|
||||
{
|
||||
int32 value = CheckInput(fTransparentGreenTC);
|
||||
fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_GREEN, &value);
|
||||
break;
|
||||
}
|
||||
|
||||
case GV_TRANSPARENT_BLUE:
|
||||
{
|
||||
int32 value = CheckInput(fTransparentBlueTC);
|
||||
fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_BLUE, &value);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BView::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
|
||||
fSettings->SaveSettings();
|
||||
}
|
||||
|
||||
|
||||
int GIFView::CheckInput(BTextControl *control) {
|
||||
int GIFView::CheckInput(BTextControl* control) {
|
||||
int value = atoi(control->Text());
|
||||
if (value < 0 || value > 255) {
|
||||
value = (value < 0) ? 0 : 255;
|
||||
@@ -412,6 +436,6 @@ int GIFView::CheckInput(BTextControl *control) {
|
||||
sprintf(temp, "%d", value);
|
||||
control->SetText(temp);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,20 +14,16 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||
// Philippe Saint-Pierre, 2013, <[email protected]>
|
||||
// Philippe Saint-Pierre, <[email protected]>
|
||||
// John Scipione, <[email protected]>
|
||||
|
||||
#ifndef GIF_VIEW_H
|
||||
#define GIF_VIEW_H
|
||||
|
||||
#ifndef GIFVIEW_H
|
||||
#define GIFVIEW_H
|
||||
|
||||
#include <View.h>
|
||||
#include "TranslatorSettings.h"
|
||||
|
||||
class BMenuField;
|
||||
class BPopUpMenu;
|
||||
class BMenuItem;
|
||||
class BCheckBox;
|
||||
class BRadioButton;
|
||||
class BTextControl;
|
||||
|
||||
#define GV_WEB_SAFE 'gvws'
|
||||
#define GV_BEOS_SYSTEM 'gvbe'
|
||||
@@ -46,43 +42,51 @@ class BTextControl;
|
||||
|
||||
const BRect kRectView(110, 110, 339, 339);
|
||||
|
||||
|
||||
class BMenuField;
|
||||
class BPopUpMenu;
|
||||
class BMenuItem;
|
||||
class BCheckBox;
|
||||
class BRadioButton;
|
||||
class BTextControl;
|
||||
|
||||
class GIFView : public BView {
|
||||
public:
|
||||
GIFView(TranslatorSettings* settings);
|
||||
virtual ~GIFView();
|
||||
public:
|
||||
GIFView(TranslatorSettings* settings);
|
||||
virtual ~GIFView();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual void AllAttached();
|
||||
|
||||
private:
|
||||
void RestorePrefs();
|
||||
int CheckInput(BTextControl* control);
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual void AllAttached();
|
||||
|
||||
TranslatorSettings* fSettings;
|
||||
private:
|
||||
void RestorePrefs();
|
||||
int CheckInput(BTextControl* control);
|
||||
|
||||
BMenuField* fPaletteMF;
|
||||
BPopUpMenu* fPaletteM;
|
||||
BMenuItem* fWebSafeMI;
|
||||
BMenuItem* fBeOSSystemMI;
|
||||
BMenuItem* fGreyScaleMI;
|
||||
BMenuItem* fOptimalMI;
|
||||
TranslatorSettings* fSettings;
|
||||
|
||||
BMenuField* fColorCountMF;
|
||||
BPopUpMenu* fColorCountM;
|
||||
BMenuItem* fColorCountMI[8];
|
||||
BMenuItem* fColorCount256MI;
|
||||
BMenuField* fPaletteMF;
|
||||
BPopUpMenu* fPaletteM;
|
||||
BMenuItem* fWebSafeMI;
|
||||
BMenuItem* fBeOSSystemMI;
|
||||
BMenuItem* fGreyScaleMI;
|
||||
BMenuItem* fOptimalMI;
|
||||
|
||||
BCheckBox* fInterlacedCB;
|
||||
BCheckBox* fUseTransparentCB;
|
||||
BCheckBox* fUseDitheringCB;
|
||||
BMenuField* fColorCountMF;
|
||||
BPopUpMenu* fColorCountM;
|
||||
BMenuItem* fColorCountMI[8];
|
||||
BMenuItem* fColorCount256MI;
|
||||
|
||||
BRadioButton* fUseTransparentAutoRB;
|
||||
BRadioButton* fUseTransparentColorRB;
|
||||
BCheckBox* fInterlacedCB;
|
||||
BCheckBox* fUseTransparentCB;
|
||||
BCheckBox* fUseDitheringCB;
|
||||
|
||||
BTextControl* fTransparentRedTC;
|
||||
BTextControl* fTransparentGreenTC;
|
||||
BTextControl* fTransparentBlueTC;
|
||||
BRadioButton* fUseTransparentAutoRB;
|
||||
BRadioButton* fUseTransparentColorRB;
|
||||
|
||||
BTextControl* fTransparentRedTC;
|
||||
BTextControl* fTransparentGreenTC;
|
||||
BTextControl* fTransparentBlueTC;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // GIF_VIEW_H
|
||||
|
||||
@@ -13,10 +13,15 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Additional authors: John Scipione, <[email protected]>
|
||||
|
||||
|
||||
#include "LoadPalette.h"
|
||||
|
||||
#include <GraphicsDefs.h>
|
||||
#include <ByteOrder.h>
|
||||
|
||||
|
||||
LoadPalette::LoadPalette() {
|
||||
backgroundindex = 0;
|
||||
usetransparent = false;
|
||||
@@ -24,19 +29,27 @@ LoadPalette::LoadPalette() {
|
||||
size = size_in_bits = 0;
|
||||
}
|
||||
|
||||
// Never index into pal directly - this function is safe
|
||||
uint32 LoadPalette::ColorForIndex(int index) {
|
||||
|
||||
uint32
|
||||
LoadPalette::ColorForIndex(int index)
|
||||
{
|
||||
// never index into pal directly - this function is safe
|
||||
if (index >= 0 && index <= size) {
|
||||
if (usetransparent && index == transparentindex) return B_TRANSPARENT_MAGIC_RGBA32;
|
||||
else return data[index];
|
||||
} else {
|
||||
if (usetransparent && index == transparentindex)
|
||||
return B_TRANSPARENT_MAGIC_RGBA32;
|
||||
else
|
||||
return data[index];
|
||||
} else
|
||||
return B_BENDIAN_TO_HOST_INT32(0x000000ff);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadPalette::SetColor(int index, uint8 red, uint8 green, uint8 blue) {
|
||||
if (index < 0 || index > 255) return;
|
||||
|
||||
void
|
||||
LoadPalette::SetColor(int index, uint8 red, uint8 green, uint8 blue)
|
||||
{
|
||||
if (index < 0 || index > 255)
|
||||
return;
|
||||
|
||||
data[index] = (blue << 24) + (green << 16) + (red << 8) + 0xff;
|
||||
data[index] = B_BENDIAN_TO_HOST_INT32(data[index]);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,24 +13,31 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Additional authors: John Scipione, <[email protected]>
|
||||
|
||||
#ifndef LOAD_PALETTE_H
|
||||
#define LOAD_PALETTE_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
class LoadPalette {
|
||||
public:
|
||||
LoadPalette();
|
||||
uint32 ColorForIndex(int index);
|
||||
void SetColor(int index, uint8 red, uint8 green, uint8 blue);
|
||||
|
||||
int size, size_in_bits;
|
||||
int backgroundindex, transparentindex;
|
||||
bool usetransparent;
|
||||
|
||||
private:
|
||||
public:
|
||||
LoadPalette();
|
||||
|
||||
uint32 ColorForIndex(int index);
|
||||
void SetColor(int index, uint8 red, uint8 green, uint8 blue);
|
||||
|
||||
int size;
|
||||
int size_in_bits;
|
||||
int backgroundindex;
|
||||
int transparentindex;
|
||||
bool usetransparent;
|
||||
|
||||
private:
|
||||
uint32 data[256];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // LOAD_PALETTE_H
|
||||
|
||||
@@ -14,98 +14,36 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||
// John Scipione, <[email protected]>
|
||||
|
||||
|
||||
#include "SFHash.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
SFHash::SFHash(int size) {
|
||||
fatalerror = false;
|
||||
this->size = size;
|
||||
iterate_pos = iterate_depth = 0;
|
||||
main_array = (HashItem **)malloc(this->size * sizeof(HashItem *));
|
||||
main_array = (HashItem**)malloc(this->size * sizeof(HashItem*));
|
||||
|
||||
if (main_array == NULL) {
|
||||
if (main_array == NULL) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
for (int x = 0; x < this->size; x++) {
|
||||
|
||||
for (int x = 0; x < this->size; x++)
|
||||
main_array[x] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SFHash::AddItem(HashItem *item) {
|
||||
item->next = NULL;
|
||||
int pos = item->key % size;
|
||||
|
||||
if (main_array[pos] == NULL) {
|
||||
main_array[pos] = item;
|
||||
}
|
||||
else {
|
||||
HashItem *temp = main_array[pos];
|
||||
while (temp->next != NULL) temp = temp->next;
|
||||
temp->next = item;
|
||||
}
|
||||
}
|
||||
|
||||
HashItem*
|
||||
SFHash::GetItem(unsigned int key)
|
||||
{
|
||||
int pos = key % size;
|
||||
HashItem *item = main_array[pos];
|
||||
|
||||
while (item != NULL) {
|
||||
if (item->key == key) return item;
|
||||
item = item->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
SFHash::CountItems()
|
||||
{
|
||||
unsigned int count = 0;
|
||||
for (int x = 0; x < this->size; x++) {
|
||||
HashItem *item = main_array[x];
|
||||
while (item != NULL) {
|
||||
count++;
|
||||
item = item->next;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
HashItem*
|
||||
SFHash::NextItem()
|
||||
{
|
||||
if (iterate_pos >= size) {
|
||||
Rewind();
|
||||
return NULL;
|
||||
}
|
||||
HashItem *item;
|
||||
while ((item = main_array[iterate_pos]) == NULL) iterate_pos++;
|
||||
for (int d = 0; d < iterate_depth; d++) {
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
if (item->next != NULL) iterate_depth++;
|
||||
else {
|
||||
iterate_pos++;
|
||||
iterate_depth = 0;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
void SFHash::Rewind() {
|
||||
iterate_pos = 0;
|
||||
iterate_depth = 0;
|
||||
}
|
||||
|
||||
SFHash::~SFHash() {
|
||||
for (int x = 0; x < size; x++) {
|
||||
HashItem *item = main_array[x];
|
||||
HashItem* item = main_array[x];
|
||||
while (item != NULL) {
|
||||
HashItem *t = item->next;
|
||||
HashItem* t = item->next;
|
||||
delete item;
|
||||
item = t;
|
||||
}
|
||||
@@ -113,3 +51,80 @@ SFHash::~SFHash() {
|
||||
free(main_array);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SFHash::AddItem(HashItem* item) {
|
||||
item->next = NULL;
|
||||
int pos = item->key % size;
|
||||
|
||||
if (main_array[pos] == NULL)
|
||||
main_array[pos] = item;
|
||||
else {
|
||||
HashItem* temp = main_array[pos];
|
||||
while (temp->next != NULL) temp = temp->next;
|
||||
temp->next = item;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HashItem*
|
||||
SFHash::GetItem(unsigned int key)
|
||||
{
|
||||
int pos = key % size;
|
||||
HashItem* item = main_array[pos];
|
||||
|
||||
while (item != NULL) {
|
||||
if (item->key == key) return item;
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
SFHash::CountItems()
|
||||
{
|
||||
unsigned int count = 0;
|
||||
for (int x = 0; x < this->size; x++) {
|
||||
HashItem* item = main_array[x];
|
||||
while (item != NULL) {
|
||||
count++;
|
||||
item = item->next;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
HashItem*
|
||||
SFHash::NextItem()
|
||||
{
|
||||
if (iterate_pos >= size) {
|
||||
Rewind();
|
||||
return NULL;
|
||||
}
|
||||
HashItem* item;
|
||||
while ((item = main_array[iterate_pos]) == NULL)
|
||||
iterate_pos++;
|
||||
|
||||
for (int d = 0; d < iterate_depth; d++)
|
||||
item = item->next;
|
||||
|
||||
if (item->next != NULL)
|
||||
iterate_depth++;
|
||||
else {
|
||||
iterate_pos++;
|
||||
iterate_depth = 0;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SFHash::Rewind() {
|
||||
iterate_pos = 0;
|
||||
iterate_depth = 0;
|
||||
}
|
||||
|
||||
@@ -14,35 +14,41 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||
// John Scipione, <[email protected]>
|
||||
|
||||
#ifndef SFHASH_H
|
||||
#define SFHASH_H
|
||||
|
||||
|
||||
class HashItem {
|
||||
friend class SFHash;
|
||||
public:
|
||||
unsigned int key;
|
||||
private:
|
||||
HashItem *next;
|
||||
public:
|
||||
unsigned int key;
|
||||
private:
|
||||
HashItem* next;
|
||||
};
|
||||
|
||||
|
||||
class SFHash {
|
||||
public:
|
||||
SFHash(int size = 4096);
|
||||
~SFHash();
|
||||
public:
|
||||
SFHash(int size = 4096);
|
||||
virtual ~SFHash();
|
||||
|
||||
void AddItem(HashItem *item);
|
||||
HashItem* GetItem(unsigned int key);
|
||||
unsigned int CountItems();
|
||||
HashItem* NextItem();
|
||||
void Rewind();
|
||||
void AddItem(HashItem* item);
|
||||
HashItem* GetItem(unsigned int key);
|
||||
unsigned int CountItems();
|
||||
HashItem* NextItem();
|
||||
void Rewind();
|
||||
|
||||
bool fatalerror;
|
||||
bool fatalerror;
|
||||
|
||||
private:
|
||||
int size, iterate_pos, iterate_depth;
|
||||
HashItem **main_array;
|
||||
private:
|
||||
int size;
|
||||
int iterate_pos;
|
||||
int iterate_depth;
|
||||
|
||||
HashItem** main_array;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // SFHASH_H
|
||||
|
||||
@@ -14,19 +14,25 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||
// John Scipione, <[email protected]>
|
||||
|
||||
|
||||
#include "SavePalette.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "SavePalette.h"
|
||||
#include <Bitmap.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
using std::nothrow;
|
||||
|
||||
extern bool debug;
|
||||
|
||||
|
||||
// "web safe palette"
|
||||
const rgb_color wsp[256] = {
|
||||
{0xff, 0xff, 0xff, 0xff}, {0xff, 0xff, 0xcc, 0xff},
|
||||
@@ -159,40 +165,43 @@ const rgb_color wsp[256] = {
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff}
|
||||
};
|
||||
|
||||
class ColorItem : public HashItem {
|
||||
public:
|
||||
ColorItem(unsigned int k, unsigned int c,
|
||||
uint8 r, uint8 g, uint8 b)
|
||||
: count(c),
|
||||
red(r),
|
||||
green(g),
|
||||
blue(b)
|
||||
{
|
||||
key = k;
|
||||
}
|
||||
unsigned int count;
|
||||
uint8 red;
|
||||
uint8 green;
|
||||
uint8 blue;
|
||||
|
||||
struct ColorItem : public HashItem {
|
||||
ColorItem(unsigned int k, unsigned int c,
|
||||
uint8 r, uint8 g, uint8 b)
|
||||
:
|
||||
count(c),
|
||||
red(r),
|
||||
green(g),
|
||||
blue(b)
|
||||
{
|
||||
key = k;
|
||||
}
|
||||
|
||||
unsigned int count;
|
||||
uint8 red;
|
||||
uint8 green;
|
||||
uint8 blue;
|
||||
};
|
||||
|
||||
// constructor
|
||||
|
||||
SavePalette::SavePalette(int mode)
|
||||
: pal(new(nothrow) rgb_color[256]),
|
||||
fSize(0),
|
||||
fSizeInBits(8),
|
||||
fMode(mode),
|
||||
fTransparentMode(NO_TRANSPARENCY),
|
||||
fTransparentIndex(-1),
|
||||
fBackgroundIndex(0),
|
||||
fFatalError(pal == NULL)
|
||||
:
|
||||
pal(new(nothrow) rgb_color[256]),
|
||||
fSize(0),
|
||||
fSizeInBits(8),
|
||||
fMode(mode),
|
||||
fTransparentMode(NO_TRANSPARENCY),
|
||||
fTransparentIndex(-1),
|
||||
fBackgroundIndex(0),
|
||||
fFatalError(pal == NULL)
|
||||
{
|
||||
if (IsValid()) {
|
||||
if (fMode == WEB_SAFE_PALETTE) {
|
||||
memcpy(pal, wsp, sizeof(rgb_color) * 256);
|
||||
fSize = 216;
|
||||
} else if (fMode == BEOS_SYSTEM_PALETTE) {
|
||||
color_map *map = (color_map *)system_colors();
|
||||
color_map* map = (color_map*)system_colors();
|
||||
memcpy(pal, map->color_list, sizeof(rgb_color) * 256);
|
||||
fSize = 256;
|
||||
} else if (fMode == GREYSCALE_PALETTE) {
|
||||
@@ -205,17 +214,18 @@ SavePalette::SavePalette(int mode)
|
||||
}
|
||||
}
|
||||
|
||||
// make_key
|
||||
|
||||
static int
|
||||
make_key(uint8 r, uint8 g, uint8 b, uint8 bits)
|
||||
{
|
||||
r = r >> (8 - bits);
|
||||
g = g >> (8 - bits);
|
||||
b = b >> (8 - bits);
|
||||
|
||||
return (r << (bits * 2)) | (g << bits) | b;
|
||||
}
|
||||
|
||||
// touch_color_item
|
||||
|
||||
static bool
|
||||
touch_color_item(SFHash& hash, unsigned int key, uint8 r, uint8 g, uint8 b)
|
||||
{
|
||||
@@ -227,27 +237,30 @@ touch_color_item(SFHash& hash, unsigned int key, uint8 r, uint8 g, uint8 b)
|
||||
printf("Out of memory in touch_color_item()\n");
|
||||
return false;
|
||||
}
|
||||
hash.AddItem((HashItem *)ci);
|
||||
hash.AddItem((HashItem*)ci);
|
||||
} else {
|
||||
ci->count++;
|
||||
#if 0
|
||||
// use brightest color
|
||||
/* ci->red = max_c(ci->red, r);
|
||||
ci->red = max_c(ci->red, r);
|
||||
ci->green = max_c(ci->green, g);
|
||||
ci->blue = max_c(ci->blue, b);*/
|
||||
ci->blue = max_c(ci->blue, b);
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// constructor
|
||||
SavePalette::SavePalette(BBitmap *bitmap, int32 maxSizeInBits)
|
||||
: pal(new(nothrow) rgb_color[256]),
|
||||
fSize(0),
|
||||
fSizeInBits(0),
|
||||
fMode(OPTIMAL_PALETTE),
|
||||
fTransparentMode(NO_TRANSPARENCY),
|
||||
fTransparentIndex(-1),
|
||||
fBackgroundIndex(0),
|
||||
fFatalError(pal == NULL)
|
||||
|
||||
SavePalette::SavePalette(BBitmap* bitmap, int32 maxSizeInBits)
|
||||
:
|
||||
pal(new(nothrow) rgb_color[256]),
|
||||
fSize(0),
|
||||
fSizeInBits(0),
|
||||
fMode(OPTIMAL_PALETTE),
|
||||
fTransparentMode(NO_TRANSPARENCY),
|
||||
fTransparentIndex(-1),
|
||||
fBackgroundIndex(0),
|
||||
fFatalError(pal == NULL)
|
||||
{
|
||||
if (!IsValid())
|
||||
return;
|
||||
@@ -255,31 +268,35 @@ SavePalette::SavePalette(BBitmap *bitmap, int32 maxSizeInBits)
|
||||
SFHash hash(1 << 16);
|
||||
if (hash.fatalerror) {
|
||||
if (debug)
|
||||
printf("Out of memory in SavePalette(BBitmap *)\n");
|
||||
printf("Out of memory in SavePalette(BBitmap*)\n");
|
||||
fFatalError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// reject unsupported color spaces
|
||||
// TODO: B_CMAP8 and B_GRAY8 should be really easy to support as well!!
|
||||
color_space cs = bitmap->ColorSpace();
|
||||
if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG && cs != B_RGBA32_BIG) {
|
||||
if (debug) {
|
||||
printf("Wrong color space given in SavePalette(BBitmap):\n");
|
||||
printf("%d %d %d %d or 0x%x\n", (cs & 0xff000000) >> 24, (cs & 0xff0000) >> 16,
|
||||
(cs & 0xff00) >> 8, cs & 0xff, cs);
|
||||
}
|
||||
fFatalError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
color_space cs = bitmap->ColorSpace();
|
||||
if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG
|
||||
&& cs != B_RGBA32_BIG) {
|
||||
if (debug) {
|
||||
printf("Wrong color space given in SavePalette(BBitmap):\n");
|
||||
printf("%d %d %d %d or 0x%x\n",
|
||||
(cs & 0xff000000) >> 24, (cs & 0xff0000) >> 16,
|
||||
(cs & 0xff00) >> 8, cs & 0xff, cs);
|
||||
}
|
||||
fFatalError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
BRect rect = bitmap->Bounds();
|
||||
uint32 height = rect.IntegerHeight() + 1;
|
||||
uint32 width = rect.IntegerWidth() + 1;
|
||||
uint8* bits = (uint8*)bitmap->Bits();
|
||||
uint32 bpr = bitmap->BytesPerRow();
|
||||
|
||||
uint8 r, g, b;
|
||||
uint8 r;
|
||||
uint8 g;
|
||||
uint8 b;
|
||||
uint8 useBits = 3 + maxSizeInBits / 2;
|
||||
if (cs == B_RGB32 || cs == B_RGBA32) {
|
||||
for (uint32 y = 0; y < height; y++) {
|
||||
@@ -292,13 +309,15 @@ SavePalette::SavePalette(BBitmap *bitmap, int32 maxSizeInBits)
|
||||
|
||||
uint32 key = make_key(r, g, b, useBits);
|
||||
if (!touch_color_item(hash, key, r, g, b)) {
|
||||
if (debug) printf("Out of memory in SavePalette(BBitmap *)\n");
|
||||
if (debug)
|
||||
printf("Out of memory in SavePalette(BBitmap*)\n");
|
||||
|
||||
fFatalError = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
bits += bpr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
bits += bpr;
|
||||
}
|
||||
} else if ((cs == B_RGB32_BIG || cs == B_RGBA32_BIG)) {
|
||||
for (uint32 y = 0; y < height; y++) {
|
||||
uint8* handle = bits;
|
||||
@@ -310,66 +329,68 @@ SavePalette::SavePalette(BBitmap *bitmap, int32 maxSizeInBits)
|
||||
|
||||
uint32 key = make_key(r, g, b, useBits);
|
||||
if (!touch_color_item(hash, key, r, g, b)) {
|
||||
if (debug) printf("Out of memory in SavePalette(BBitmap *)\n");
|
||||
if (debug)
|
||||
printf("Out of memory in SavePalette(BBitmap*)\n");
|
||||
fFatalError = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
bits += bpr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
bits += bpr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int unique_colors = hash.CountItems();
|
||||
while (((1 << fSizeInBits) < unique_colors) && (fSizeInBits < maxSizeInBits))
|
||||
while (((1 << fSizeInBits) < unique_colors)
|
||||
&& (fSizeInBits < maxSizeInBits)) {
|
||||
fSizeInBits++;
|
||||
}
|
||||
fSize = 1 << fSizeInBits;
|
||||
|
||||
ColorItem **topcolors = (ColorItem **)malloc(fSize * sizeof(ColorItem *));
|
||||
if (topcolors == NULL) {
|
||||
if (debug) printf("Out of memory in SavePalette(BBitmap *)\n");
|
||||
fFatalError = true;
|
||||
return;
|
||||
}
|
||||
ColorItem *dummy = new ColorItem(0, 0, 0, 0, 0);
|
||||
for (int i = 0; i < fSize; i++)
|
||||
topcolors[i] = dummy;
|
||||
ColorItem** topcolors = (ColorItem**)malloc(fSize * sizeof(ColorItem*));
|
||||
if (topcolors == NULL) {
|
||||
if (debug) printf("Out of memory in SavePalette(BBitmap*)\n");
|
||||
fFatalError = true;
|
||||
return;
|
||||
}
|
||||
ColorItem* dummy = new ColorItem(0, 0, 0, 0, 0);
|
||||
for (int i = 0; i < fSize; i++)
|
||||
topcolors[i] = dummy;
|
||||
|
||||
for (int i = 0; i < unique_colors; i++) {
|
||||
ColorItem *ci = (ColorItem *)hash.NextItem();
|
||||
for (int j = 0; j < fSize; j++) {
|
||||
if (ci->count > topcolors[j]->count) {
|
||||
for (int k = fSize - 1; k > j; k--) {
|
||||
topcolors[k] = topcolors[k - 1];
|
||||
}
|
||||
topcolors[j] = ci;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < fSize; i++) {
|
||||
pal[i].red = topcolors[i]->red;
|
||||
pal[i].green = topcolors[i]->green;
|
||||
pal[i].blue = topcolors[i]->blue;
|
||||
pal[i].alpha = 0xff;
|
||||
}
|
||||
|
||||
delete dummy;
|
||||
free(topcolors);
|
||||
for (int i = 0; i < unique_colors; i++) {
|
||||
ColorItem* ci = (ColorItem*)hash.NextItem();
|
||||
for (int j = 0; j < fSize; j++) {
|
||||
if (ci->count > topcolors[j]->count) {
|
||||
for (int k = fSize - 1; k > j; k--) {
|
||||
topcolors[k] = topcolors[k - 1];
|
||||
}
|
||||
topcolors[j] = ci;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < fSize; i++) {
|
||||
pal[i].red = topcolors[i]->red;
|
||||
pal[i].green = topcolors[i]->green;
|
||||
pal[i].blue = topcolors[i]->blue;
|
||||
pal[i].alpha = 0xff;
|
||||
}
|
||||
|
||||
delete dummy;
|
||||
free(topcolors);
|
||||
}
|
||||
|
||||
// destructor
|
||||
|
||||
SavePalette::~SavePalette()
|
||||
{
|
||||
delete[] pal;
|
||||
}
|
||||
|
||||
// IndexForColor
|
||||
//
|
||||
// standard mapping services once a palette is loaded
|
||||
|
||||
uint8
|
||||
SavePalette::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
|
||||
{
|
||||
// standard mapping services once a palette is loaded
|
||||
if (fTransparentMode > NO_TRANSPARENCY && alpha < 128)
|
||||
return fTransparentIndex;
|
||||
|
||||
@@ -378,13 +399,16 @@ SavePalette::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
|
||||
if (fMode == GREYSCALE_PALETTE) {
|
||||
index = (308 * red + 600 * green + 116 * blue) / 1024;
|
||||
// avoid transparent index
|
||||
if (fTransparentMode == AUTO_TRANSPARENCY && index == 1 && fTransparentIndex == 1)
|
||||
if (fTransparentMode == AUTO_TRANSPARENCY && index == 1
|
||||
&& fTransparentIndex == 1) {
|
||||
index = 0;
|
||||
}
|
||||
} else {
|
||||
int closestDistance = 255 * 255 * 3;
|
||||
|
||||
if (fTransparentMode == AUTO_TRANSPARENCY) {
|
||||
for (int i = 0; i < fTransparentIndex && closestDistance != 0; i++) {
|
||||
for (int i = 0; i < fTransparentIndex && closestDistance != 0;
|
||||
i++) {
|
||||
int rd = (int)red - (int)pal[i].red;
|
||||
int gd = (int)green - (int)pal[i].green;
|
||||
int bd = (int)blue - (int)pal[i].blue;
|
||||
@@ -394,7 +418,8 @@ SavePalette::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
for (int i = fTransparentIndex + 1; i < fSize && closestDistance != 0; i++) {
|
||||
for (int i = fTransparentIndex + 1;
|
||||
i < fSize && closestDistance != 0; i++) {
|
||||
int rd = (int)red - (int)pal[i].red;
|
||||
int gd = (int)green - (int)pal[i].green;
|
||||
int bd = (int)blue - (int)pal[i].blue;
|
||||
@@ -417,10 +442,11 @@ SavePalette::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
// SetTransparentIndex
|
||||
|
||||
void
|
||||
SavePalette::PrepareForAutoTransparency()
|
||||
{
|
||||
@@ -448,7 +474,7 @@ SavePalette::PrepareForAutoTransparency()
|
||||
}
|
||||
}
|
||||
|
||||
// SetTransparentColor
|
||||
|
||||
void
|
||||
SavePalette::SetTransparentColor(uint8 red, uint8 green, uint8 blue)
|
||||
{
|
||||
@@ -460,7 +486,7 @@ SavePalette::SetTransparentColor(uint8 red, uint8 green, uint8 blue)
|
||||
if (pal[i].red == red &&
|
||||
pal[i].green == green &&
|
||||
pal[i].blue == blue) {
|
||||
|
||||
|
||||
fTransparentIndex = i;
|
||||
found = true;
|
||||
|
||||
@@ -489,7 +515,7 @@ SavePalette::SetTransparentColor(uint8 red, uint8 green, uint8 blue)
|
||||
}
|
||||
}
|
||||
|
||||
// GetColors
|
||||
|
||||
void
|
||||
SavePalette::GetColors(uint8* buffer, int size) const
|
||||
{
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Additional authors: John Scipione, <[email protected]>
|
||||
|
||||
#ifndef SAVE_PALETTE_H
|
||||
#define SAVE_PALETTE_H
|
||||
|
||||
|
||||
#include "SFHash.h"
|
||||
#include <GraphicsDefs.h>
|
||||
class BBitmap;
|
||||
|
||||
enum {
|
||||
WEB_SAFE_PALETTE = 0,
|
||||
@@ -33,51 +35,52 @@ enum {
|
||||
COLOR_KEY_TRANSPARENCY
|
||||
};
|
||||
|
||||
|
||||
class BBitmap;
|
||||
|
||||
class SavePalette {
|
||||
public:
|
||||
SavePalette(int mode);
|
||||
SavePalette(BBitmap *bitmap,
|
||||
int32 maxSizeInBits = 8);
|
||||
virtual ~SavePalette();
|
||||
public:
|
||||
SavePalette(int mode);
|
||||
SavePalette(BBitmap* bitmap,
|
||||
int32 maxSizeInBits = 8);
|
||||
virtual ~SavePalette();
|
||||
|
||||
inline bool IsValid() const
|
||||
{ return !fFatalError; }
|
||||
inline bool IsValid() const
|
||||
{ return !fFatalError; }
|
||||
|
||||
uint8 IndexForColor(uint8 red, uint8 green,
|
||||
uint8 blue, uint8 alpha = 255);
|
||||
inline uint8 IndexForColor(const rgb_color& color);
|
||||
uint8 IndexForColor(uint8 red, uint8 green,
|
||||
uint8 blue, uint8 alpha = 255);
|
||||
inline uint8 IndexForColor(const rgb_color& color);
|
||||
|
||||
inline bool UseTransparent() const
|
||||
{ return fTransparentMode > NO_TRANSPARENCY; }
|
||||
inline bool UseTransparent() const
|
||||
{ return fTransparentMode > NO_TRANSPARENCY; }
|
||||
|
||||
void PrepareForAutoTransparency();
|
||||
inline int TransparentIndex() const
|
||||
{ return fTransparentIndex; }
|
||||
void SetTransparentColor(uint8 red,
|
||||
uint8 green,
|
||||
uint8 blue);
|
||||
void PrepareForAutoTransparency();
|
||||
inline int TransparentIndex() const
|
||||
{ return fTransparentIndex; }
|
||||
void SetTransparentColor(uint8 red,
|
||||
uint8 green, uint8 blue);
|
||||
|
||||
inline int SizeInBits() const
|
||||
{ return fSizeInBits; }
|
||||
inline int SizeInBits() const { return fSizeInBits; }
|
||||
|
||||
inline int BackgroundIndex() const
|
||||
{ return fBackgroundIndex; }
|
||||
inline int BackgroundIndex() const
|
||||
{ return fBackgroundIndex; }
|
||||
|
||||
void GetColors(uint8* buffer, int size) const;
|
||||
void GetColors(uint8* buffer, int size) const;
|
||||
|
||||
rgb_color* pal;
|
||||
rgb_color* pal;
|
||||
|
||||
private:
|
||||
int fSize;
|
||||
int fSizeInBits;
|
||||
int fMode;
|
||||
uint32 fTransparentMode;
|
||||
int fTransparentIndex;
|
||||
int fBackgroundIndex;
|
||||
bool fFatalError;
|
||||
private:
|
||||
int fSize;
|
||||
int fSizeInBits;
|
||||
int fMode;
|
||||
uint32 fTransparentMode;
|
||||
int fTransparentIndex;
|
||||
int fBackgroundIndex;
|
||||
bool fFatalError;
|
||||
};
|
||||
|
||||
// IndexForColor
|
||||
|
||||
inline uint8
|
||||
SavePalette::IndexForColor(const rgb_color& color)
|
||||
{
|
||||
@@ -85,6 +88,4 @@ SavePalette::IndexForColor(const rgb_color& color)
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // SAVE_PALETTE_H
|
||||
|
||||
Reference in New Issue
Block a user