GIFTranslator: Style fixes

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