GIFTranslator: Style fixes
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user