GIFTranslator: Style fixes

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