Initial check in for GIFTranslator, generously donated by Daniel Switkin
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5639 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c04dd9b71c
commit
1abb86b2ed
435
src/add-ons/translators/giftranslator/GIFLoad.cpp
Normal file
435
src/add-ons/translators/giftranslator/GIFLoad.cpp
Normal file
@ -0,0 +1,435 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: GIFLoad.cpp
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "GIFLoad.h"
|
||||
#include <ByteOrder.h>
|
||||
#include <TranslatorFormats.h>
|
||||
#include <InterfaceDefs.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern bool debug;
|
||||
|
||||
GIFLoad::GIFLoad(BPositionIO *input, BPositionIO *output) {
|
||||
this->input = input;
|
||||
this->output = output;
|
||||
Init();
|
||||
|
||||
if (!ReadGIFHeader()) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (debug) printf("GIFLoad::GIFLoad() - Image dimensions are %d x %d\n", width, height);
|
||||
|
||||
unsigned char c;
|
||||
if (input->Read(&c, 1) < 1) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
while (c != 0x3b) {
|
||||
if (c == 0x2c) {
|
||||
if ((!ReadGIFImageHeader()) || (!ReadGIFImageData())) {
|
||||
if (debug) printf("GIFLoad::GIFLoad() - A fatal error occurred\n");
|
||||
fatalerror = true;
|
||||
} else {
|
||||
if (debug) printf("GIFLoad::GIFLoad() - Found a single image and leaving\n");
|
||||
}
|
||||
if (scanline != NULL) free(scanline);
|
||||
return;
|
||||
} else if (c == 0x21) {
|
||||
unsigned char d;
|
||||
if (input->Read(&d, 1) < 1) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
if (d == 0xff) {
|
||||
if (!ReadGIFLoopBlock()) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
} else if (d == 0xf9) {
|
||||
if (!ReadGIFControlBlock()) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
} else if (d == 0xfe) {
|
||||
if (!ReadGIFCommentBlock()) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!ReadGIFUnknownBlock(d)) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (c != 0x00) {
|
||||
if (!ReadGIFUnknownBlock(c)) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (input->Read(&c, 1) < 1) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (debug) printf("GIFLoad::GIFLoad() - Done\n");
|
||||
}
|
||||
|
||||
void GIFLoad::Init() {
|
||||
fatalerror = false;
|
||||
scanline = NULL;
|
||||
palette = NULL;
|
||||
input->Seek(0, SEEK_SET);
|
||||
head_memblock = NULL;
|
||||
}
|
||||
|
||||
bool GIFLoad::ReadGIFHeader() {
|
||||
// Standard header
|
||||
unsigned char header[13];
|
||||
if (input->Read(header, 13) < 13) return false;
|
||||
width = header[6] + (header[7] << 8);
|
||||
height = header[8] + (header[9] << 8);
|
||||
|
||||
palette = new LoadPalette();
|
||||
// Global palette
|
||||
if (header[10] & 0x80) {
|
||||
palette->size_in_bits = (header[10] & 0x07) + 1;
|
||||
if (debug) printf("GIFLoad::ReadGIFHeader() - Found %d bit global palette\n", palette->size_in_bits);
|
||||
int s = 1 << palette->size_in_bits;
|
||||
palette->size = s;
|
||||
|
||||
unsigned char gp[256 * 3];
|
||||
if (input->Read(gp, s * 3) < s * 3) return false;
|
||||
for (int x = 0; x < s; x++) {
|
||||
palette->SetColor(x, gp[x * 3], gp[x * 3 + 1], gp[x * 3 + 2]);
|
||||
}
|
||||
palette->backgroundindex = header[11];
|
||||
} 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++) {
|
||||
palette->SetColor(x, map->color_list[x].red, map->color_list[x].green,
|
||||
map->color_list[x].blue);
|
||||
}
|
||||
palette->size = 256;
|
||||
palette->size_in_bits = 8;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GIFLoad::ReadGIFLoopBlock() {
|
||||
unsigned char length;
|
||||
if (input->Read(&length, 1) < 1) return false;
|
||||
input->Seek(length, SEEK_CUR);
|
||||
|
||||
do {
|
||||
if (input->Read(&length, 1) < 1) {
|
||||
return false;
|
||||
}
|
||||
input->Seek(length, SEEK_CUR);
|
||||
} while (length != 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GIFLoad::ReadGIFControlBlock() {
|
||||
unsigned char data[6];
|
||||
if (input->Read(data, 6) < 6) return false;
|
||||
if (data[1] & 0x01) {
|
||||
palette->usetransparent = true;
|
||||
palette->transparentindex = data[4];
|
||||
if (debug) printf("GIFLoad::ReadGIFControlBlock() - Transparency active, using palette index %d\n", data[4]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GIFLoad::ReadGIFCommentBlock() {
|
||||
if (debug) printf("GIFLoad::ReadGIFCommentBlock() - Found:\n");
|
||||
unsigned char length;
|
||||
char comment_data[256];
|
||||
do {
|
||||
if (input->Read(&length, 1) < 1) return false;
|
||||
if (input->Read(comment_data, length) < length) return false;
|
||||
comment_data[length] = 0x00;
|
||||
if (debug) printf("%s", comment_data);
|
||||
} while (length != 0x00);
|
||||
if (debug) printf("\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GIFLoad::ReadGIFUnknownBlock(unsigned char c) {
|
||||
if (debug) printf("GIFLoad::ReadGIFUnknownBlock() - Found: %d\n", c);
|
||||
unsigned char length;
|
||||
do {
|
||||
if (input->Read(&length, 1) < 1) return false;
|
||||
input->Seek(length, SEEK_CUR);
|
||||
} while (length != 0x00);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GIFLoad::ReadGIFImageHeader() {
|
||||
unsigned char data[9];
|
||||
if (input->Read(data, 9) < 9) return false;
|
||||
|
||||
int local_width = data[4] + (data[5] << 8);
|
||||
int local_height = data[6] + (data[7] << 8);
|
||||
if (width != local_width || height != local_height) {
|
||||
if (debug) printf("GIFLoad::ReadGIFImageHeader() - Local dimensions do not match global, setting to %d x %d\n",
|
||||
local_width, local_height);
|
||||
width = local_width;
|
||||
height = local_height;
|
||||
}
|
||||
|
||||
scanline = (uint32 *)malloc(width * 4);
|
||||
if (scanline == NULL) {
|
||||
if (debug) printf("GIFLoad::ReadGIFImageHeader() - Could not allocate scanline\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
BRect rect(0, 0, width - 1, height - 1);
|
||||
TranslatorBitmap header;
|
||||
header.magic = B_HOST_TO_BENDIAN_INT32(B_TRANSLATOR_BITMAP);
|
||||
header.bounds.left = B_HOST_TO_BENDIAN_FLOAT(rect.left);
|
||||
header.bounds.top = B_HOST_TO_BENDIAN_FLOAT(rect.top);
|
||||
header.bounds.right = B_HOST_TO_BENDIAN_FLOAT(rect.right);
|
||||
header.bounds.bottom = B_HOST_TO_BENDIAN_FLOAT(rect.bottom);
|
||||
header.rowBytes = B_HOST_TO_BENDIAN_INT32(width * 4);
|
||||
header.colors = (color_space)B_HOST_TO_BENDIAN_INT32(B_RGBA32);
|
||||
header.dataSize = B_HOST_TO_BENDIAN_INT32(width * 4 * height);
|
||||
if (output->Write(&header, 32) < 32) return false;
|
||||
|
||||
// Has local palette
|
||||
if (data[8] & 0x80) {
|
||||
palette->size_in_bits = (data[8] & 0x07) + 1;
|
||||
int s = 1 << palette->size_in_bits;
|
||||
palette->size = s;
|
||||
if (debug) printf("GIFLoad::ReadGIFImageHeader() - Found %d bit local palette\n",
|
||||
palette->size_in_bits);
|
||||
|
||||
unsigned char lp[256 * 3];
|
||||
if (input->Read(lp, s * 3) < s * 3) return false;
|
||||
for (int x = 0; x < s; x++) {
|
||||
palette->SetColor(x, lp[x * 3], lp[x * 3 + 1], lp[x * 3 + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (data[8] & 0x40) {
|
||||
interlaced = true;
|
||||
if (debug) printf("GIFLoad::ReadGIFImageHeader() - Image is interlaced\n");
|
||||
} else {
|
||||
interlaced = false;
|
||||
if (debug) printf("GIFLoad::ReadGIFImageHeader() - Image is not interlaced\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GIFLoad::ReadGIFImageData() {
|
||||
unsigned char new_entry[4096];
|
||||
|
||||
unsigned char cs;
|
||||
input->Read(&cs, 1);
|
||||
if (cs == palette->size_in_bits) {
|
||||
if (!InitFrame(palette->size_in_bits)) return false;
|
||||
} else if (cs > palette->size_in_bits) {
|
||||
if (debug) printf("GIFLoad::ReadGIFImageData() - Code_size should be %d, not %d, allowing it\n", code_size, cs);
|
||||
if (!InitFrame(cs)) return false;
|
||||
} else if (cs < palette->size_in_bits) {
|
||||
if (debug) printf("GIFLoad::ReadGIFImageData() - Code_size should be %d, not %d\n", code_size, cs);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debug) printf("GIFLoad::ReadGIFImageData() - Starting LZW\n");
|
||||
|
||||
while ((new_code = NextCode()) != -1 && new_code != end_code) {
|
||||
if (new_code == clear_code) {
|
||||
ResetTable();
|
||||
new_code = NextCode();
|
||||
old_code[0] = new_code;
|
||||
old_code_length = 1;
|
||||
if (!OutputColor(old_code, 1)) goto bad_end;
|
||||
if (new_code == -1 || new_code == end_code) {
|
||||
if (debug) printf("GIFLoad::ReadGIFImageData() - Premature end_code or error\n");
|
||||
goto bad_end;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Explicitly check for lack of clear code at start of file
|
||||
if (old_code_length == 0) {
|
||||
old_code[0] = new_code;
|
||||
old_code_length = 1;
|
||||
if (!OutputColor(old_code, 1)) goto bad_end;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (table[new_code] != NULL) { // Does exist in table
|
||||
if (!OutputColor(table[new_code], entry_size[new_code])) goto bad_end;
|
||||
|
||||
//memcpy(new_entry, old_code, old_code_length);
|
||||
for (int x = 0; x < old_code_length; x++) {
|
||||
new_entry[x] = old_code[x];
|
||||
}
|
||||
|
||||
//memcpy(new_entry + old_code_length, table[new_code], 1);
|
||||
new_entry[old_code_length] = *table[new_code];
|
||||
} else { // Does not exist in table
|
||||
//memcpy(new_entry, old_code, old_code_length);
|
||||
for (int x = 0; x < old_code_length; x++) {
|
||||
new_entry[x] = old_code[x];
|
||||
}
|
||||
|
||||
//memcpy(new_entry + old_code_length, old_code, 1);
|
||||
new_entry[old_code_length] = *old_code;
|
||||
|
||||
if (!OutputColor(new_entry, old_code_length + 1)) goto bad_end;
|
||||
}
|
||||
table[next_code] = MemblockAllocate(old_code_length + 1);
|
||||
|
||||
//memcpy(table[next_code], new_entry, old_code_length + 1);
|
||||
for (int x = 0; x < old_code_length + 1; x++) {
|
||||
table[next_code][x] = new_entry[x];
|
||||
}
|
||||
|
||||
entry_size[next_code] = old_code_length + 1;
|
||||
|
||||
//memcpy(old_code, table[new_code], entry_size[new_code]);
|
||||
for (int x = 0; x < entry_size[new_code]; x++) {
|
||||
old_code[x] = table[new_code][x];
|
||||
}
|
||||
|
||||
old_code_length = entry_size[new_code];
|
||||
next_code++;
|
||||
|
||||
if (next_code > max_code && BITS != 12) {
|
||||
BITS++;
|
||||
max_code = (1 << BITS) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
MemblockDeleteAll();
|
||||
if (new_code == -1) return false;
|
||||
if (debug) printf("GIFLoad::ReadGIFImageData() - Done\n");
|
||||
return true;
|
||||
|
||||
bad_end:
|
||||
if (debug) printf("GIFLoad::ReadGIFImageData() - Reached a bad end\n");
|
||||
MemblockDeleteAll();
|
||||
return false;
|
||||
}
|
||||
|
||||
short GIFLoad::NextCode() {
|
||||
while (bit_count < BITS) {
|
||||
if (byte_count == 0) {
|
||||
if (input->Read(&byte_count, 1) < 1) return -1;
|
||||
if (byte_count == 0) return end_code;
|
||||
if (input->Read(byte_buffer + (255 - byte_count), byte_count) < byte_count) return -1;
|
||||
}
|
||||
bit_buffer |= (unsigned int)byte_buffer[255 - byte_count] << bit_count;
|
||||
byte_count--;
|
||||
bit_count += 8;
|
||||
}
|
||||
|
||||
short s = bit_buffer & ((1 << BITS) - 1);
|
||||
bit_buffer >>= BITS;
|
||||
bit_count -= BITS;
|
||||
return s;
|
||||
}
|
||||
|
||||
void GIFLoad::ResetTable() {
|
||||
BITS = code_size + 1;
|
||||
next_code = clear_code + 2;
|
||||
max_code = (1 << BITS) - 1;
|
||||
|
||||
MemblockDeleteAll();
|
||||
for (int x = 0; x < 4096; x++) {
|
||||
table[x] = NULL;
|
||||
if (x < (1 << code_size)) {
|
||||
table[x] = MemblockAllocate(1);
|
||||
table[x][0] = x;
|
||||
entry_size[x] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GIFLoad::InitFrame(int size) {
|
||||
code_size = size;
|
||||
if (code_size == 1) code_size++;
|
||||
BITS = code_size + 1;
|
||||
clear_code = 1 << code_size;
|
||||
end_code = clear_code + 1;
|
||||
next_code = clear_code + 2;
|
||||
max_code = (1 << BITS) - 1;
|
||||
pass = 0;
|
||||
if (interlaced) row = gl_pass_starts_at[0];
|
||||
else row = 0;
|
||||
|
||||
bit_count = 0;
|
||||
bit_buffer = 0;
|
||||
byte_count = 0;
|
||||
old_code_length = 0;
|
||||
new_code = 0;
|
||||
scanline_position = 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) {
|
||||
if (head_memblock == NULL) {
|
||||
head_memblock = new Memblock();
|
||||
uchar *value = head_memblock->data;
|
||||
head_memblock->offset = size;
|
||||
head_memblock->next = NULL;
|
||||
return value;
|
||||
} else {
|
||||
Memblock *block = head_memblock;
|
||||
Memblock *last = NULL;
|
||||
while (block != NULL) {
|
||||
if (4096 - block->offset > size) {
|
||||
uchar *value = block->data + block->offset;
|
||||
block->offset += size;
|
||||
return value;
|
||||
}
|
||||
last = block;
|
||||
block = block->next;
|
||||
}
|
||||
|
||||
block = new Memblock();
|
||||
uchar *value = block->data;
|
||||
block->offset = size;
|
||||
block->next = NULL;
|
||||
last->next = block;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the linked list
|
||||
void GIFLoad::MemblockDeleteAll() {
|
||||
Memblock *block = NULL;
|
||||
while (head_memblock != NULL) {
|
||||
block = head_memblock->next;
|
||||
delete head_memblock;
|
||||
head_memblock = block;
|
||||
}
|
||||
}
|
||||
|
||||
GIFLoad::~GIFLoad() {
|
||||
delete palette;
|
||||
}
|
||||
|
103
src/add-ons/translators/giftranslator/GIFLoad.h
Normal file
103
src/add-ons/translators/giftranslator/GIFLoad.h
Normal file
@ -0,0 +1,103 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: GIFLoad.h
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GIFLOAD_H
|
||||
#define GIFLOAD_H
|
||||
|
||||
#include <DataIO.h>
|
||||
#include "LoadPalette.h"
|
||||
|
||||
class Memblock {
|
||||
public:
|
||||
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};
|
||||
|
||||
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);
|
||||
|
||||
void Init();
|
||||
bool InitFrame(int size);
|
||||
short NextCode();
|
||||
void ResetTable();
|
||||
|
||||
uchar *MemblockAllocate(int size);
|
||||
void MemblockDeleteAll();
|
||||
|
||||
inline bool OutputColor(unsigned char *string, int size) {
|
||||
int bpr = width << 2;
|
||||
|
||||
for (int x = 0; x < size; x++) {
|
||||
scanline[scanline_position] = palette->ColorForIndex(string[x]);
|
||||
scanline_position++;
|
||||
|
||||
if (scanline_position >= width) {
|
||||
if (output->WriteAt(32 + (row * bpr), scanline, bpr) < bpr) return false;
|
||||
scanline_position = 0;
|
||||
if (interlaced) {
|
||||
row += gl_increment_pass_by[pass];
|
||||
while (row >= height) {
|
||||
pass++;
|
||||
if (pass > 3) return true;
|
||||
row = gl_pass_starts_at[pass];
|
||||
}
|
||||
} else row++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BPositionIO *input, *output;
|
||||
LoadPalette *palette;
|
||||
bool interlaced;
|
||||
int pass, row, width, height;
|
||||
|
||||
unsigned char old_code[4096];
|
||||
int old_code_length;
|
||||
short new_code;
|
||||
int BITS, max_code, code_size;
|
||||
short clear_code, end_code, next_code;
|
||||
|
||||
unsigned char *table[4096];
|
||||
short entry_size[4096];
|
||||
Memblock *head_memblock;
|
||||
|
||||
int bit_count;
|
||||
unsigned int bit_buffer;
|
||||
unsigned char byte_count;
|
||||
unsigned char byte_buffer[255];
|
||||
|
||||
uint32 *scanline;
|
||||
int scanline_position;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
406
src/add-ons/translators/giftranslator/GIFSave.cpp
Normal file
406
src/add-ons/translators/giftranslator/GIFSave.cpp
Normal file
@ -0,0 +1,406 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: GIFSave.cpp
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "GIFSave.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.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);
|
||||
const int32 three_sixteenth = (int32)((3.0 / 16.0) * 32768);
|
||||
const int32 five_sixteenth = (int32)((5.0 / 16.0) * 32768);
|
||||
const int32 seven_sixteenth = (int32)((7.0 / 16.0) * 32768);
|
||||
|
||||
extern bool debug;
|
||||
|
||||
GIFSave::GIFSave(BBitmap *bitmap, BPositionIO *output) {
|
||||
color_space cs = bitmap->ColorSpace();
|
||||
if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG && cs != B_RGBA32_BIG) {
|
||||
if (debug) printf("GIFSave::GIFSave() - Unknown color space\n");
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
|
||||
fatalerror = false;
|
||||
prefs = new Prefs();
|
||||
if (prefs->palettemode == OPTIMAL_PALETTE) palette = new SavePalette(bitmap);
|
||||
else palette = new SavePalette(prefs->palettemode);
|
||||
if (palette->fatalerror) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
|
||||
width = bitmap->Bounds().IntegerWidth() + 1;
|
||||
height = bitmap->Bounds().IntegerHeight() + 1;
|
||||
if (debug) printf("GIFSave::GIFSave() - Image dimensions are %d by %d\n", width, height);
|
||||
|
||||
if (prefs->usedithering) {
|
||||
if (debug) printf("GIFSave::GIFSave() - Using dithering\n");
|
||||
red_error = new int32[width + 2];
|
||||
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
|
||||
blue_error = new int32[width + 2];
|
||||
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;
|
||||
green_error[x] = 0;
|
||||
blue_error[x] = 0;
|
||||
}
|
||||
} else {
|
||||
if (debug) printf("GIFSave::GIFSave() - Not using dithering\n");
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
if (prefs->interlaced) printf("GIFSave::GIFSave() - Interlaced, ");
|
||||
else printf("GIFSave::GIFSave() - Not interlaced, ");
|
||||
switch (prefs->palettemode) {
|
||||
case WEB_SAFE_PALETTE:
|
||||
printf("web safe palette\n");
|
||||
break;
|
||||
case BEOS_SYSTEM_PALETTE:
|
||||
printf("BeOS system palette\n");
|
||||
break;
|
||||
case GREYSCALE_PALETTE:
|
||||
printf("greyscale palette\n");
|
||||
break;
|
||||
case OPTIMAL_PALETTE:
|
||||
default:
|
||||
printf("optimal palette\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
palette->usetransparent = prefs->usetransparent;
|
||||
if (prefs->usetransparent) {
|
||||
if (prefs->usetransparentindex) {
|
||||
palette->transparentindex = prefs->transparentindex;
|
||||
if (debug) printf("GIFSave::GIFSave() - Using transparent index %d\n", palette->transparentindex);
|
||||
} else {
|
||||
palette->transparentindex = -1;
|
||||
for (int x = 0; x < palette->size; x++) {
|
||||
if (palette->pal[x].red == prefs->transparentred &&
|
||||
palette->pal[x].green == prefs->transparentgreen &&
|
||||
palette->pal[x].blue == prefs->transparentblue) {
|
||||
|
||||
palette->transparentindex = x;
|
||||
if (debug) printf("GIFSave::GIFSave() - Found transparent color %d,%d,%d at index %d\n", prefs->transparentred,
|
||||
prefs->transparentgreen, prefs->transparentblue, x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (palette->transparentindex == -1) {
|
||||
palette->usetransparent = false;
|
||||
palette->transparentindex = 0;
|
||||
if (debug) printf("GIFSave::GIFSave() - Did not find color %d,%d,%d - deactivating transparency\n",
|
||||
prefs->transparentred, prefs->transparentgreen, prefs->transparentblue);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (debug) printf("GIFSave::GIFSave() - Not using transparency\n");
|
||||
}
|
||||
|
||||
this->output = output;
|
||||
this->bitmap = bitmap;
|
||||
WriteGIFHeader();
|
||||
if (debug) printf("GIFSave::GIFSave() - Wrote gif header\n");
|
||||
|
||||
hash = new SFHash(1 << 16);
|
||||
WriteGIFControlBlock();
|
||||
if (debug) printf("GIFSave::GIFSave() - Wrote gif control block\n");
|
||||
WriteGIFImageHeader();
|
||||
if (debug) printf("GIFSave::GIFSave() - Wrote gif image header\n");
|
||||
WriteGIFImageData();
|
||||
if (debug) printf("GIFSave::GIFSave() - Wrote gif image data\n");
|
||||
|
||||
if (prefs->usedithering) {
|
||||
delete [] &red_error[-1];
|
||||
delete [] &green_error[-1];
|
||||
delete [] &blue_error[-1];
|
||||
}
|
||||
delete hash;
|
||||
|
||||
// Terminating character
|
||||
char t = 0x3b;
|
||||
output->Write(&t, 1);
|
||||
}
|
||||
|
||||
void GIFSave::WriteGIFHeader() {
|
||||
// Standard header
|
||||
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;
|
||||
header[9] = (height & 0xff00) >> 8;
|
||||
header[10] = 0xf0 | (palette->size_in_bits - 1);
|
||||
header[11] = palette->backgroundindex;
|
||||
output->Write(header, 13);
|
||||
|
||||
// Global palette
|
||||
int size = 1 << palette->size_in_bits;
|
||||
char c[256 * 3]; // can't be bigger than this
|
||||
for (int x = 0; x < size; x++) {
|
||||
c[x * 3] = palette->pal[x].red;
|
||||
c[x * 3 + 1] = palette->pal[x].green;
|
||||
c[x * 3 + 2] = palette->pal[x].blue;
|
||||
}
|
||||
output->Write(c, size * 3);
|
||||
}
|
||||
|
||||
void GIFSave::WriteGIFControlBlock() {
|
||||
unsigned char b[8] = {0x21, 0xf9, 0x04, 0, 0, 0, 0, 0x00};
|
||||
if (palette->usetransparent) {
|
||||
b[3] = b[3] | 1;
|
||||
b[6] = palette->transparentindex;
|
||||
}
|
||||
output->Write(b, 8);
|
||||
}
|
||||
|
||||
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;
|
||||
header[8] = (height & 0xff00) >> 8;
|
||||
|
||||
if (prefs->interlaced) header[9] = 0x40;
|
||||
else header[9] = 0x00;
|
||||
output->Write(header, 10);
|
||||
}
|
||||
|
||||
void GIFSave::WriteGIFImageData() {
|
||||
InitFrame();
|
||||
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) {
|
||||
string_code = y;
|
||||
} 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
|
||||
}
|
||||
max_code = (1 << BITS) - 1;
|
||||
}
|
||||
string_code = character;
|
||||
next_code++;
|
||||
}
|
||||
}
|
||||
OutputCode(string_code, BITS);
|
||||
OutputCode(end_code, BITS);
|
||||
OutputCode(0, BITS, true);
|
||||
char t = 0x00;
|
||||
output->Write(&t, 1);
|
||||
free(code_value);
|
||||
free(prefix_code);
|
||||
free(append_char);
|
||||
}
|
||||
|
||||
void GIFSave::OutputCode(short code, int BITS, bool flush) {
|
||||
if (!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;
|
||||
}
|
||||
if (byte_count >= 255) {
|
||||
byte_buffer[0] = 255;
|
||||
output->Write(byte_buffer, 256);
|
||||
if (byte_count == 256) {
|
||||
byte_buffer[1] = byte_buffer[256];
|
||||
byte_count = 1;
|
||||
} else byte_count = 0;
|
||||
}
|
||||
} else {
|
||||
bit_buffer |= (unsigned int) code << bit_count;
|
||||
bit_count += BITS;
|
||||
while (bit_count > 0) {
|
||||
byte_buffer[byte_count + 1] = (unsigned char)(bit_buffer & 0xff);
|
||||
byte_count++;
|
||||
bit_buffer >>= 8;
|
||||
bit_count -= 8;
|
||||
}
|
||||
if (byte_count > 0) {
|
||||
byte_buffer[0] = (unsigned char)byte_count;
|
||||
output->Write(byte_buffer, byte_count + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GIFSave::ResetHashtable() {
|
||||
for (int q = 0; q < HASHSIZE; q++) {
|
||||
code_value[q] = -1;
|
||||
prefix_code[q] = 0;
|
||||
append_char[q] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int GIFSave::CheckHashtable(int s, unsigned char c) {
|
||||
if (s == -1) return 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;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
unsigned char GIFSave::NextPixel(int pixel) {
|
||||
int bpr = bitmap->BytesPerRow();
|
||||
color_space cs = bitmap->ColorSpace();
|
||||
unsigned char r, g, b;
|
||||
|
||||
if (cs == B_RGB32 || cs == B_RGBA32) {
|
||||
b = gifbits[0];
|
||||
g = gifbits[1];
|
||||
r = gifbits[2];
|
||||
} else {
|
||||
r = gifbits[1];
|
||||
g = gifbits[2];
|
||||
b = gifbits[3];
|
||||
}
|
||||
gifbits += 4;
|
||||
pos += 4;
|
||||
|
||||
if (prefs->usedithering) {
|
||||
if (pixel % width == 0) {
|
||||
red_side_error = green_side_error = blue_side_error = 0;
|
||||
}
|
||||
b = min_c(255, max_c(0, b - blue_side_error));
|
||||
g = min_c(255, max_c(0, g - green_side_error));
|
||||
r = min_c(255, max_c(0, r - red_side_error));
|
||||
}
|
||||
|
||||
if (prefs->interlaced) {
|
||||
if (pos >= bpr) {
|
||||
pos = 0;
|
||||
row += gs_increment_pass_by[pass];
|
||||
while (row >= height) {
|
||||
pass++;
|
||||
row = gs_pass_starts_at[pass];
|
||||
}
|
||||
gifbits = (unsigned char *)bitmap->Bits() + (bpr * row);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int key = (r << 16) + (g << 8) + b;
|
||||
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);
|
||||
}
|
||||
|
||||
if (prefs->usedithering) {
|
||||
int x = pixel % width;
|
||||
// Don't carry error on to next line when interlaced because
|
||||
// that line won't be adjacent, hence error is meaningless
|
||||
if (prefs->interlaced && x == width - 1) {
|
||||
for (int32 y = -1; y < width + 1; y++) {
|
||||
red_error[y] = 0;
|
||||
green_error[y] = 0;
|
||||
blue_error[y] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int32 red_total_error = palette->pal[cc->index].red - r;
|
||||
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_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);
|
||||
|
||||
red_error[x] += (red_total_error * five_sixteenth);
|
||||
green_error[x] += (green_total_error * five_sixteenth);
|
||||
blue_error[x] += (blue_total_error * five_sixteenth);
|
||||
|
||||
red_error[x + 1] = (red_total_error * one_sixteenth);
|
||||
green_error[x + 1] = (green_total_error * one_sixteenth);
|
||||
blue_error[x + 1] = (blue_total_error * one_sixteenth);
|
||||
}
|
||||
|
||||
return cc->index;
|
||||
}
|
||||
|
||||
void GIFSave::InitFrame() {
|
||||
code_size = palette->size_in_bits;
|
||||
if (code_size == 1) code_size++;
|
||||
BITS = code_size + 1;
|
||||
clear_code = 1 << code_size;
|
||||
end_code = clear_code + 1;
|
||||
next_code = clear_code + 2;
|
||||
max_code = (1 << BITS) - 1;
|
||||
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();
|
||||
}
|
||||
|
||||
GIFSave::~GIFSave() {
|
||||
delete palette;
|
||||
delete prefs;
|
||||
}
|
||||
|
81
src/add-ons/translators/giftranslator/GIFSave.h
Normal file
81
src/add-ons/translators/giftranslator/GIFSave.h
Normal file
@ -0,0 +1,81 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: GIFSave.h
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GIFSAVE_H
|
||||
#define GIFSAVE_H
|
||||
|
||||
#include <DataIO.h>
|
||||
#include <Bitmap.h>
|
||||
#include "SavePalette.h"
|
||||
#include "SFHash.h"
|
||||
#include "Prefs.h"
|
||||
|
||||
#define HASHSIZE 9973
|
||||
#define HASHSTEP 2039
|
||||
|
||||
#define HASH(index, lastbyte) (((lastbyte << 8) ^ index) % HASHSIZE)
|
||||
|
||||
class GIFSave {
|
||||
public:
|
||||
GIFSave(BBitmap *bitmap, BPositionIO *output);
|
||||
~GIFSave();
|
||||
|
||||
bool fatalerror;
|
||||
|
||||
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;
|
||||
Prefs *prefs;
|
||||
|
||||
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 *gifbits;
|
||||
|
||||
int width, height;
|
||||
|
||||
// For dithering
|
||||
int32 *red_error, *green_error, *blue_error;
|
||||
int16 red_side_error, green_side_error, blue_side_error;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
214
src/add-ons/translators/giftranslator/GIFTranslator.cpp
Normal file
214
src/add-ons/translators/giftranslator/GIFTranslator.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: GIFTranslator.cpp
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "GIFTranslator.h"
|
||||
#include "GIFWindow.h"
|
||||
#include "GIFView.h"
|
||||
#include "GIFSave.h"
|
||||
#include "GIFLoad.h"
|
||||
#include <ByteOrder.h>
|
||||
#include <TypeConstants.h>
|
||||
#include <DataIO.h>
|
||||
#include <TranslatorAddOn.h>
|
||||
#include <TranslatorFormats.h>
|
||||
#include <InterfaceDefs.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef GIF_TYPE
|
||||
#define GIF_TYPE 'GIF '
|
||||
#endif
|
||||
|
||||
// This global will be externed in other files - set once here
|
||||
// for the entire translator
|
||||
bool debug = false;
|
||||
|
||||
bool DetermineType(BPositionIO *source, bool *is_gif);
|
||||
status_t GetBitmap(BPositionIO *in, BBitmap **out);
|
||||
|
||||
/* Required data */
|
||||
char translatorName[] = "GIF Images";
|
||||
char translatorInfo[] = "GIF image translator v1.3";
|
||||
int32 translatorVersion = 0x130;
|
||||
|
||||
translation_format inputFormats[] = {
|
||||
{ GIF_TYPE, B_TRANSLATOR_BITMAP, 0.8, 0.8, "image/gif", "GIF image" },
|
||||
{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.3, 0.3, "image/x-be-bitmap", "Be Bitmap image" },
|
||||
{ 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
translation_format outputFormats[] = {
|
||||
{ GIF_TYPE, B_TRANSLATOR_BITMAP, 0.8, 0.8, "image/gif", "GIF image" },
|
||||
{ B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.3, 0.3, "image/x-be-bitmap", "Be Bitmap image" },
|
||||
{ 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
/* Build a pretty view for DataTranslations */
|
||||
status_t MakeConfig(BMessage *ioExtension, BView **outView, BRect *outExtent) {
|
||||
outExtent->Set(0, 0, 239, 239);
|
||||
GIFView *gifview = new GIFView(*outExtent, "TranslatorView");
|
||||
*outView = gifview;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
bool DetermineType(BPositionIO *source, bool *is_gif) {
|
||||
unsigned char header[7];
|
||||
*is_gif = 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) + 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) return false;
|
||||
}
|
||||
|
||||
source->Seek(0, SEEK_SET);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Dump data from stream into a BBitmap */
|
||||
status_t GetBitmap(BPositionIO *in, BBitmap **out) {
|
||||
TranslatorBitmap header;
|
||||
|
||||
status_t err = in->Read(&header, sizeof(header));
|
||||
if (err != sizeof(header)) return B_IO_ERROR;
|
||||
|
||||
header.magic = B_BENDIAN_TO_HOST_INT32(header.magic);
|
||||
header.bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left);
|
||||
header.bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top);
|
||||
header.bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right);
|
||||
header.bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom);
|
||||
header.rowBytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes);
|
||||
header.colors = (color_space)B_BENDIAN_TO_HOST_INT32(header.colors);
|
||||
header.dataSize = B_BENDIAN_TO_HOST_INT32(header.dataSize);
|
||||
|
||||
BBitmap *bitmap = new BBitmap(header.bounds, header.colors);
|
||||
*out = bitmap;
|
||||
if (bitmap == NULL) return B_NO_MEMORY;
|
||||
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;
|
||||
else return B_IO_ERROR;
|
||||
}
|
||||
|
||||
/* Required Identify function - may need to read entire header, not sure */
|
||||
status_t Identify(BPositionIO *inSource, const translation_format *inFormat,
|
||||
BMessage *ioExtension, translator_info *outInfo, uint32 outType) {
|
||||
|
||||
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)) return B_NO_TRANSLATOR;
|
||||
if (!is_gif && inFormat != NULL && inFormat->type != B_TRANSLATOR_BITMAP)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
outInfo->group = B_TRANSLATOR_BITMAP;
|
||||
if (is_gif) {
|
||||
outInfo->type = GIF_TYPE;
|
||||
outInfo->quality = 0.8;
|
||||
outInfo->capability = 0.8;
|
||||
strcpy(outInfo->name, "GIF image");
|
||||
strcpy(outInfo->MIME, "image/gif");
|
||||
}
|
||||
else {
|
||||
outInfo->type = B_TRANSLATOR_BITMAP;
|
||||
outInfo->quality = 0.3;
|
||||
outInfo->capability = 0.3;
|
||||
strcpy(outInfo->name, "Be Bitmap image");
|
||||
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 */
|
||||
status_t Translate(BPositionIO *inSource, const translator_info *inInfo,
|
||||
BMessage *ioExtension, uint32 outType, BPositionIO *outDestination) {
|
||||
|
||||
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)) return B_NO_TRANSLATOR;
|
||||
if (!is_gif && 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 **b = (BBitmap **)malloc(4);
|
||||
*b = NULL;
|
||||
err = GetBitmap(inSource, b);
|
||||
if (err != B_OK) return err;
|
||||
GIFSave *gs = new GIFSave(*b, outDestination);
|
||||
if (gs->fatalerror) {
|
||||
delete gs;
|
||||
if (*b != NULL) delete *b;
|
||||
delete b;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
delete gs;
|
||||
delete *b;
|
||||
delete b;
|
||||
} else { // GIF to BBitmap
|
||||
GIFLoad *gl = new GIFLoad(inSource, outDestination);
|
||||
if (gl->fatalerror) {
|
||||
delete gl;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
delete gl;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
now = system_time() - now;
|
||||
printf("Translate() - Translation took %Ld microseconds\n", now);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
GIFTranslator::GIFTranslator() : BApplication("application/x-vnd.Jules-GIFTranslator") {
|
||||
BRect rect(100, 100, 339, 339);
|
||||
gifwindow = new GIFWindow(rect, "GIF Settings");
|
||||
gifwindow->Show();
|
||||
}
|
||||
|
||||
int main() {
|
||||
GIFTranslator myapp;
|
||||
myapp.Run();
|
||||
return 0;
|
||||
}
|
||||
|
29
src/add-ons/translators/giftranslator/GIFTranslator.h
Normal file
29
src/add-ons/translators/giftranslator/GIFTranslator.h
Normal file
@ -0,0 +1,29 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: GIFTranslator.h
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GIFTRANSLATOR_H
|
||||
#define GIFTRANSLATOR_H
|
||||
|
||||
#include <Application.h>
|
||||
class GIFWindow;
|
||||
|
||||
class GIFTranslator : public BApplication {
|
||||
public:
|
||||
GIFTranslator();
|
||||
GIFWindow *gifwindow;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
326
src/add-ons/translators/giftranslator/GIFView.cpp
Normal file
326
src/add-ons/translators/giftranslator/GIFView.cpp
Normal file
@ -0,0 +1,326 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: GIFView.cpp
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "GIFView.h"
|
||||
#include "SavePalette.h"
|
||||
#include "Prefs.h"
|
||||
#include <InterfaceKit.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern int32 translatorVersion;
|
||||
extern char translatorName[];
|
||||
|
||||
GIFView::GIFView(BRect rect, const char *name) :
|
||||
BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW) {
|
||||
|
||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
|
||||
font_height fh;
|
||||
be_bold_font->GetHeight(&fh);
|
||||
BRect r(10, 15, 10 + be_bold_font->StringWidth(translatorName), 15 + fh.ascent + fh.descent);
|
||||
|
||||
BStringView *title = new BStringView(r, "Title", translatorName);
|
||||
title->SetFont(be_bold_font);
|
||||
AddChild(title);
|
||||
|
||||
char version_string[100];
|
||||
sprintf(version_string, "v%d.%d.%d %s", (int)(translatorVersion >> 8), (int)((translatorVersion >> 4) & 0xf),
|
||||
(int)(translatorVersion & 0xf), __DATE__);
|
||||
r.top = r.bottom + 20;
|
||||
be_plain_font->GetHeight(&fh);
|
||||
r.bottom = r.top + fh.ascent + fh.descent;
|
||||
r.right = r.left + be_plain_font->StringWidth(version_string);
|
||||
|
||||
BStringView *version = new BStringView(r, "Version", version_string);
|
||||
version->SetFont(be_plain_font);
|
||||
AddChild(version);
|
||||
|
||||
const char *copyright_string = "© 2003 Daniel Switkin, software@switkin.com";
|
||||
r.top = r.bottom + 10;
|
||||
r.bottom = r.top + fh.ascent + fh.descent;
|
||||
r.right = r.left + be_plain_font->StringWidth(copyright_string);
|
||||
|
||||
BStringView *copyright = new BStringView(r, "Copyright", copyright_string);
|
||||
copyright->SetFont(be_plain_font);
|
||||
AddChild(copyright);
|
||||
|
||||
websafe = new BMenuItem("websafe", new BMessage(GV_WEB_SAFE), 0, 0);
|
||||
beossystem = new BMenuItem("BeOS system", new BMessage(GV_BEOS_SYSTEM), 0, 0);
|
||||
greyscale = new BMenuItem("greyscale", new BMessage(GV_GREYSCALE), 0, 0);
|
||||
optimal = new BMenuItem("optimal", new BMessage(GV_OPTIMAL), 0, 0);
|
||||
palettepopupmenu = new BPopUpMenu("PalettePopUpMenu", true, true, B_ITEMS_IN_COLUMN);
|
||||
palettepopupmenu->AddItem(websafe);
|
||||
palettepopupmenu->AddItem(beossystem);
|
||||
palettepopupmenu->AddItem(greyscale);
|
||||
palettepopupmenu->AddItem(optimal);
|
||||
|
||||
r.top = r.bottom + 10;
|
||||
r.bottom = r.top + 24;
|
||||
r.right = r.left + be_plain_font->StringWidth("Palette:") +
|
||||
be_plain_font->StringWidth("BeOS system") + 32;
|
||||
palettemenufield = new BMenuField(r, "PaletteMenuField", "Palette:",
|
||||
palettepopupmenu, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE);
|
||||
AddChild(palettemenufield);
|
||||
palettemenufield->SetDivider(be_plain_font->StringWidth("Palette:") + 7);
|
||||
|
||||
r.top = palettemenufield->Frame().bottom + 5;
|
||||
r.bottom = r.top + 10;
|
||||
r.right = r.left + be_plain_font->StringWidth("Use dithering") + 20;
|
||||
usedithering = new BCheckBox(r, "UseDithering", "Use dithering",
|
||||
new BMessage(GV_USE_DITHERING));
|
||||
AddChild(usedithering);
|
||||
|
||||
r.top = usedithering->Frame().bottom + 2;
|
||||
r.bottom = r.top + 10;
|
||||
r.right = r.left + be_plain_font->StringWidth("Write interlaced images") + 20;
|
||||
interlaced = new BCheckBox(r, "Interlaced", "Write interlaced images",
|
||||
new BMessage(GV_INTERLACED));
|
||||
AddChild(interlaced);
|
||||
|
||||
r.top = interlaced->Frame().bottom + 2;
|
||||
r.bottom = r.top + 10;
|
||||
r.right = r.left + be_plain_font->StringWidth("Write transparent images") + 20;
|
||||
usetransparent = new BCheckBox(r, "UseTransparent", "Write transparent images",
|
||||
new BMessage(GV_USE_TRANSPARENT));
|
||||
AddChild(usetransparent);
|
||||
|
||||
r.top = usetransparent->Frame().bottom + 2;
|
||||
r.bottom = r.top + 10;
|
||||
r.right = r.left + be_plain_font->StringWidth("Use index:") + 20;
|
||||
usetransparentindex = new BRadioButton(r, "UseTransparentIndex", "Use index:",
|
||||
new BMessage(GV_USE_TRANSPARENT_INDEX));
|
||||
AddChild(usetransparentindex);
|
||||
|
||||
r.left = r.right + 1;
|
||||
r.right = r.left + 30;
|
||||
transparentindex = new BTextControl(r, "TransparentIndex", "", "0",
|
||||
new BMessage(GV_TRANSPARENT_INDEX));
|
||||
AddChild(transparentindex);
|
||||
transparentindex->SetDivider(0);
|
||||
|
||||
r.top = usetransparentindex->Frame().bottom + 0;
|
||||
r.bottom = r.top + 10;
|
||||
r.left = 10;
|
||||
r.right = r.left + be_plain_font->StringWidth("Use rgb color:") + 20;
|
||||
usetransparentcolor = new BRadioButton(r, "UseTransparentColor", "Use rgb color:",
|
||||
new BMessage(GV_USE_TRANSPARENT_COLOR));
|
||||
AddChild(usetransparentcolor);
|
||||
|
||||
r.left = r.right + 1;
|
||||
r.right = r.left + 30;
|
||||
transparentred = new BTextControl(r, "TransparentRed", "", "0",
|
||||
new BMessage(GV_TRANSPARENT_RED));
|
||||
AddChild(transparentred);
|
||||
transparentred->SetDivider(0);
|
||||
|
||||
r.left = r.right + 5;
|
||||
r.right = r.left + 30;
|
||||
transparentgreen = new BTextControl(r, "TransparentGreen", "", "0",
|
||||
new BMessage(GV_TRANSPARENT_GREEN));
|
||||
AddChild(transparentgreen);
|
||||
transparentgreen->SetDivider(0);
|
||||
|
||||
r.left = r.right + 5;
|
||||
r.right = r.left + 30;
|
||||
transparentblue = new BTextControl(r, "TransparentBlue", "", "0",
|
||||
new BMessage(GV_TRANSPARENT_BLUE));
|
||||
AddChild(transparentblue);
|
||||
transparentblue->SetDivider(0);
|
||||
|
||||
BTextView *ti = transparentindex->TextView();
|
||||
BTextView *tr = transparentred->TextView();
|
||||
BTextView *tg = transparentgreen->TextView();
|
||||
BTextView *tb = transparentblue->TextView();
|
||||
|
||||
for (uint32 x = 0; x < 256; x++) {
|
||||
if (x < '0' || x > '9') {
|
||||
ti->DisallowChar(x);
|
||||
tr->DisallowChar(x);
|
||||
tg->DisallowChar(x);
|
||||
tb->DisallowChar(x);
|
||||
}
|
||||
}
|
||||
|
||||
RestorePrefs();
|
||||
}
|
||||
|
||||
void GIFView::RestorePrefs() {
|
||||
prefs = new Prefs();
|
||||
|
||||
switch (prefs->palettemode) {
|
||||
case WEB_SAFE_PALETTE:
|
||||
websafe->SetMarked(true);
|
||||
break;
|
||||
case BEOS_SYSTEM_PALETTE:
|
||||
beossystem->SetMarked(true);
|
||||
break;
|
||||
case GREYSCALE_PALETTE:
|
||||
greyscale->SetMarked(true);
|
||||
usedithering->SetEnabled(false);
|
||||
break;
|
||||
case OPTIMAL_PALETTE:
|
||||
optimal->SetMarked(true);
|
||||
break;
|
||||
default:
|
||||
prefs->palettemode = WEB_SAFE_PALETTE;
|
||||
websafe->SetMarked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
interlaced->SetValue(prefs->interlaced);
|
||||
|
||||
if (greyscale->IsMarked()) usedithering->SetValue(false);
|
||||
else usedithering->SetValue(prefs->usedithering);
|
||||
usetransparent->SetValue(prefs->usetransparent);
|
||||
usetransparentindex->SetValue(prefs->usetransparentindex);
|
||||
usetransparentcolor->SetValue(!prefs->usetransparentindex);
|
||||
if (prefs->usetransparent) {
|
||||
usetransparentindex->SetEnabled(true);
|
||||
usetransparentcolor->SetEnabled(true);
|
||||
transparentindex->SetEnabled(prefs->usetransparentindex);
|
||||
transparentred->SetEnabled(!prefs->usetransparentindex);
|
||||
transparentgreen->SetEnabled(!prefs->usetransparentindex);
|
||||
transparentblue->SetEnabled(!prefs->usetransparentindex);
|
||||
} else {
|
||||
usetransparentindex->SetEnabled(false);
|
||||
usetransparentcolor->SetEnabled(false);
|
||||
transparentindex->SetEnabled(false);
|
||||
transparentred->SetEnabled(false);
|
||||
transparentgreen->SetEnabled(false);
|
||||
transparentblue->SetEnabled(false);
|
||||
}
|
||||
|
||||
char temp[4];
|
||||
sprintf(temp, "%d", prefs->transparentindex);
|
||||
transparentindex->SetText(temp);
|
||||
sprintf(temp, "%d", prefs->transparentred);
|
||||
transparentred->SetText(temp);
|
||||
sprintf(temp, "%d", prefs->transparentgreen);
|
||||
transparentgreen->SetText(temp);
|
||||
sprintf(temp, "%d", prefs->transparentblue);
|
||||
transparentblue->SetText(temp);
|
||||
}
|
||||
|
||||
void GIFView::AllAttached() {
|
||||
BView::AllAttached();
|
||||
BMessenger msgr(this);
|
||||
interlaced->SetTarget(msgr);
|
||||
usedithering->SetTarget(msgr);
|
||||
usetransparent->SetTarget(msgr);
|
||||
usetransparentindex->SetTarget(msgr);
|
||||
transparentindex->SetTarget(msgr);
|
||||
usetransparentcolor->SetTarget(msgr);
|
||||
transparentred->SetTarget(msgr);
|
||||
transparentgreen->SetTarget(msgr);
|
||||
transparentblue->SetTarget(msgr);
|
||||
websafe->SetTarget(msgr);
|
||||
beossystem->SetTarget(msgr);
|
||||
greyscale->SetTarget(msgr);
|
||||
optimal->SetTarget(msgr);
|
||||
}
|
||||
|
||||
void GIFView::MessageReceived(BMessage *message) {
|
||||
switch (message->what) {
|
||||
case GV_WEB_SAFE:
|
||||
prefs->palettemode = WEB_SAFE_PALETTE;
|
||||
usedithering->SetEnabled(true);
|
||||
break;
|
||||
case GV_BEOS_SYSTEM:
|
||||
prefs->palettemode = BEOS_SYSTEM_PALETTE;
|
||||
usedithering->SetEnabled(true);
|
||||
break;
|
||||
case GV_GREYSCALE:
|
||||
prefs->palettemode = GREYSCALE_PALETTE;
|
||||
usedithering->SetEnabled(false);
|
||||
usedithering->SetValue(false);
|
||||
prefs->usedithering = false;
|
||||
break;
|
||||
case GV_OPTIMAL:
|
||||
prefs->palettemode = OPTIMAL_PALETTE;
|
||||
usedithering->SetEnabled(true);
|
||||
break;
|
||||
case GV_INTERLACED:
|
||||
prefs->interlaced = interlaced->Value();
|
||||
break;
|
||||
case GV_USE_DITHERING:
|
||||
prefs->usedithering = usedithering->Value();
|
||||
break;
|
||||
case GV_USE_TRANSPARENT:
|
||||
prefs->usetransparent = usetransparent->Value();
|
||||
if (prefs->usetransparent) {
|
||||
usetransparentindex->SetEnabled(true);
|
||||
usetransparentcolor->SetEnabled(true);
|
||||
transparentindex->SetEnabled(usetransparentindex->Value());
|
||||
transparentred->SetEnabled(usetransparentcolor->Value());
|
||||
transparentgreen->SetEnabled(usetransparentcolor->Value());
|
||||
transparentblue->SetEnabled(usetransparentcolor->Value());
|
||||
} else {
|
||||
usetransparentindex->SetEnabled(false);
|
||||
usetransparentcolor->SetEnabled(false);
|
||||
transparentindex->SetEnabled(false);
|
||||
transparentred->SetEnabled(false);
|
||||
transparentgreen->SetEnabled(false);
|
||||
transparentblue->SetEnabled(false);
|
||||
}
|
||||
break;
|
||||
case GV_USE_TRANSPARENT_INDEX:
|
||||
prefs->usetransparentindex = true;
|
||||
transparentindex->SetEnabled(true);
|
||||
transparentred->SetEnabled(false);
|
||||
transparentgreen->SetEnabled(false);
|
||||
transparentblue->SetEnabled(false);
|
||||
break;
|
||||
case GV_TRANSPARENT_INDEX:
|
||||
prefs->transparentindex = CheckInput(transparentindex);
|
||||
break;
|
||||
case GV_USE_TRANSPARENT_COLOR:
|
||||
prefs->usetransparentindex = false;
|
||||
transparentindex->SetEnabled(false);
|
||||
transparentred->SetEnabled(true);
|
||||
transparentgreen->SetEnabled(true);
|
||||
transparentblue->SetEnabled(true);
|
||||
break;
|
||||
case GV_TRANSPARENT_RED:
|
||||
prefs->transparentred = CheckInput(transparentred);
|
||||
break;
|
||||
case GV_TRANSPARENT_GREEN:
|
||||
prefs->transparentgreen = CheckInput(transparentgreen);
|
||||
break;
|
||||
case GV_TRANSPARENT_BLUE:
|
||||
prefs->transparentblue = CheckInput(transparentblue);
|
||||
break;
|
||||
default:
|
||||
BView::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
prefs->Save();
|
||||
}
|
||||
|
||||
int GIFView::CheckInput(BTextControl *control) {
|
||||
int value = atoi(control->Text());
|
||||
if (value < 0 || value > 255) {
|
||||
value = (value < 0) ? 0 : 255;
|
||||
char temp[4];
|
||||
sprintf(temp, "%d", value);
|
||||
control->SetText(temp);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
GIFView::~GIFView() {
|
||||
delete prefs;
|
||||
}
|
||||
|
64
src/add-ons/translators/giftranslator/GIFView.h
Normal file
64
src/add-ons/translators/giftranslator/GIFView.h
Normal file
@ -0,0 +1,64 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: GIFView.h
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GIFVIEW_H
|
||||
#define GIFVIEW_H
|
||||
|
||||
#include <View.h>
|
||||
class BMenuField;
|
||||
class BPopUpMenu;
|
||||
class BMenuItem;
|
||||
class BCheckBox;
|
||||
class BRadioButton;
|
||||
class BTextControl;
|
||||
class Prefs;
|
||||
|
||||
#define GV_WEB_SAFE 'gvws'
|
||||
#define GV_BEOS_SYSTEM 'gvbe'
|
||||
#define GV_GREYSCALE 'gvgr'
|
||||
#define GV_OPTIMAL 'gvop'
|
||||
#define GV_INTERLACED 'gvin'
|
||||
#define GV_USE_DITHERING 'gvud'
|
||||
#define GV_USE_TRANSPARENT 'gvut'
|
||||
#define GV_USE_TRANSPARENT_INDEX 'gvui'
|
||||
#define GV_TRANSPARENT_INDEX 'gvti'
|
||||
#define GV_USE_TRANSPARENT_COLOR 'gvuc'
|
||||
#define GV_TRANSPARENT_RED 'gvtr'
|
||||
#define GV_TRANSPARENT_GREEN 'gvtg'
|
||||
#define GV_TRANSPARENT_BLUE 'gvtb'
|
||||
|
||||
class GIFView : public BView {
|
||||
public:
|
||||
GIFView(BRect rect, const char *name);
|
||||
~GIFView();
|
||||
void MessageReceived(BMessage *message);
|
||||
void AllAttached();
|
||||
|
||||
Prefs *prefs;
|
||||
BMenuField *palettemenufield;
|
||||
BPopUpMenu *palettepopupmenu;
|
||||
BMenuItem *websafe, *beossystem, *greyscale, *optimal;
|
||||
BCheckBox *interlaced, *usetransparent, *usedithering;
|
||||
BRadioButton *usetransparentindex, *usetransparentcolor;
|
||||
BTextControl *transparentindex, *transparentred,
|
||||
*transparentgreen, *transparentblue;
|
||||
|
||||
private:
|
||||
void RestorePrefs();
|
||||
int CheckInput(BTextControl *control);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
33
src/add-ons/translators/giftranslator/GIFWindow.cpp
Normal file
33
src/add-ons/translators/giftranslator/GIFWindow.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: GIFWindow.cpp
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "GIFWindow.h"
|
||||
#include "GIFView.h"
|
||||
#include <Application.h>
|
||||
|
||||
GIFWindow::GIFWindow(BRect rect, const char *name) :
|
||||
BWindow(rect, name, B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE,
|
||||
B_CURRENT_WORKSPACE) {
|
||||
|
||||
BRect r(Bounds());
|
||||
gifview = new GIFView(r, "GIFView");
|
||||
AddChild(gifview);
|
||||
}
|
||||
|
||||
bool GIFWindow::QuitRequested() {
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
return true;
|
||||
}
|
||||
|
30
src/add-ons/translators/giftranslator/GIFWindow.h
Normal file
30
src/add-ons/translators/giftranslator/GIFWindow.h
Normal file
@ -0,0 +1,30 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: GIFWindow.h
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GIFWINDOW_H
|
||||
#define GIFWINDOW_H
|
||||
|
||||
#include <Window.h>
|
||||
class GIFView;
|
||||
|
||||
class GIFWindow : public BWindow {
|
||||
public:
|
||||
GIFWindow(BRect rect, const char *name);
|
||||
bool QuitRequested();
|
||||
GIFView *gifview;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
18
src/add-ons/translators/giftranslator/Jamfile
Normal file
18
src/add-ons/translators/giftranslator/Jamfile
Normal file
@ -0,0 +1,18 @@
|
||||
SubDir OBOS_TOP src add-ons translators giftranslator ;
|
||||
|
||||
Translator GIFTranslator :
|
||||
# Main Source
|
||||
GIFTranslator.cpp
|
||||
GIFView.cpp
|
||||
GIFWindow.cpp
|
||||
Prefs.cpp
|
||||
|
||||
# Real Work
|
||||
GIFLoad.cpp
|
||||
LoadPalette.cpp
|
||||
GIFSave.cpp
|
||||
SavePalette.cpp
|
||||
SFHash.cpp
|
||||
;
|
||||
|
||||
LinkSharedOSLibs GIFTranslator : be translation ;
|
42
src/add-ons/translators/giftranslator/LoadPalette.cpp
Normal file
42
src/add-ons/translators/giftranslator/LoadPalette.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: LoadPalette.cpp
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "LoadPalette.h"
|
||||
#include <GraphicsDefs.h>
|
||||
#include <ByteOrder.h>
|
||||
|
||||
LoadPalette::LoadPalette() {
|
||||
backgroundindex = 0;
|
||||
usetransparent = false;
|
||||
transparentindex = 0;
|
||||
size = size_in_bits = 0;
|
||||
}
|
||||
|
||||
// Never index into pal directly - this function is safe
|
||||
uint32 LoadPalette::ColorForIndex(int index) {
|
||||
if (index >= 0 && index <= size) {
|
||||
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;
|
||||
data[index] = (blue << 24) + (green << 16) + (red << 8) + 0xff;
|
||||
data[index] = B_BENDIAN_TO_HOST_INT32(data[index]);
|
||||
}
|
||||
|
36
src/add-ons/translators/giftranslator/LoadPalette.h
Normal file
36
src/add-ons/translators/giftranslator/LoadPalette.h
Normal file
@ -0,0 +1,36 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: LoadPalette.h
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#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:
|
||||
uint32 data[256];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
123
src/add-ons/translators/giftranslator/Prefs.cpp
Normal file
123
src/add-ons/translators/giftranslator/Prefs.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: Prefs.cpp
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Prefs.h"
|
||||
#include <File.h>
|
||||
#include <Path.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern bool debug;
|
||||
|
||||
Prefs::Prefs() {
|
||||
interlaced = usetransparent = usetransparentindex = false;
|
||||
usedithering = true;
|
||||
transparentindex = transparentred = transparentgreen =
|
||||
transparentblue = palettemode = 0;
|
||||
|
||||
BPath path;
|
||||
find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||
path.Append("GIFTranslator_settings");
|
||||
file = new BFile(path.Path(), B_READ_WRITE | B_CREATE_FILE);
|
||||
|
||||
if (file->InitCheck() != B_OK) {
|
||||
if (debug) printf("Bad filename for attributes\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bool db = false;
|
||||
if (!GetBool("interlaced", &interlaced, &db)) return;
|
||||
db = false;
|
||||
if (!GetBool("usetransparent", &usetransparent, &db)) return;
|
||||
db = false;
|
||||
if (!GetBool("usetransparentindex", &usetransparentindex, &db)) return;
|
||||
db = true;
|
||||
if (!GetBool("usedithering", &usedithering, &db)) return;
|
||||
int di = 0;
|
||||
if (!GetInt("palettemode", &palettemode, &di)) return;
|
||||
di = 0;
|
||||
if (!GetInt("transparentindex", &transparentindex, &di)) return;
|
||||
di = 0;
|
||||
if (!GetInt("transparentred", &transparentred, &di)) return;
|
||||
di = 0;
|
||||
if (!GetInt("transparentgreen", &transparentgreen, &di)) return;
|
||||
di = 0;
|
||||
if (!GetInt("transparentblue", &transparentblue, &di)) return;
|
||||
}
|
||||
|
||||
bool Prefs::GetInt(char *name, int *value, int *defaultvalue) {
|
||||
status_t err = file->ReadAttr(name, B_INT32_TYPE, 0, value, 4);
|
||||
if (err == B_ENTRY_NOT_FOUND) {
|
||||
*value = *defaultvalue;
|
||||
if (file->WriteAttr(name, B_INT32_TYPE, 0, defaultvalue, 4) < 0) {
|
||||
if (debug) printf("WriteAttr on %s died\n", name);
|
||||
return false;
|
||||
}
|
||||
} else if (err < 0) {
|
||||
if (debug) printf("Unknown error reading %s\n", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Prefs::GetBool(char *name, bool *value, bool *defaultvalue) {
|
||||
status_t err = file->ReadAttr(name, B_BOOL_TYPE, 0, value, 1);
|
||||
if (err == B_ENTRY_NOT_FOUND) {
|
||||
*value = *defaultvalue;
|
||||
if (file->WriteAttr(name, B_BOOL_TYPE, 0, defaultvalue, 1) < 0) {
|
||||
if (debug) printf("WriteAttr on %s died\n", name);
|
||||
return false;
|
||||
}
|
||||
} else if (err < 0) {
|
||||
if (debug) printf("Unknown error reading %s\n", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Prefs::PutInt(char *name, int *value) {
|
||||
status_t err = file->WriteAttr(name, B_INT32_TYPE, 0, value, 4);
|
||||
if (err < 0) {
|
||||
if (debug) printf("WriteAttr on %s died\n", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Prefs::PutBool(char *name, bool *value) {
|
||||
status_t err = file->WriteAttr(name, B_BOOL_TYPE, 0, value, 1);
|
||||
if (err < 0) {
|
||||
if (debug) printf("WriteAttr on %s died\n", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Prefs::Save() {
|
||||
if (!PutBool("interlaced", &interlaced)) return;
|
||||
if (!PutBool("usetransparent", &usetransparent)) return;
|
||||
if (!PutBool("usetransparentindex", &usetransparentindex)) return;
|
||||
if (!PutBool("usedithering", &usedithering)) return;
|
||||
if (!PutInt("palettemode", &palettemode)) return;
|
||||
if (!PutInt("transparentindex", &transparentindex)) return;
|
||||
if (!PutInt("transparentred", &transparentred)) return;
|
||||
if (!PutInt("transparentgreen", &transparentgreen)) return;
|
||||
if (!PutInt("transparentblue", &transparentblue)) return;
|
||||
}
|
||||
|
||||
Prefs::~Prefs() {
|
||||
delete file;
|
||||
}
|
||||
|
40
src/add-ons/translators/giftranslator/Prefs.h
Normal file
40
src/add-ons/translators/giftranslator/Prefs.h
Normal file
@ -0,0 +1,40 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: Prefs.h
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PREFS_H
|
||||
#define PREFS_H
|
||||
|
||||
class BNode;
|
||||
|
||||
class Prefs {
|
||||
public:
|
||||
Prefs();
|
||||
void Save();
|
||||
~Prefs();
|
||||
bool interlaced, usetransparent, usetransparentindex,
|
||||
usedithering;
|
||||
int transparentindex, transparentred, transparentgreen,
|
||||
transparentblue, palettemode;
|
||||
private:
|
||||
bool GetInt(char *name, int *value, int *defaultvalue);
|
||||
bool GetBool(char *name, bool *value, bool *defaultvalue);
|
||||
bool PutInt(char *name, int *value);
|
||||
bool PutBool(char *name, bool *value);
|
||||
|
||||
BNode *file;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
111
src/add-ons/translators/giftranslator/SFHash.cpp
Normal file
111
src/add-ons/translators/giftranslator/SFHash.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: SFHash.cpp
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SFHash.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
SFHash::SFHash(int size) {
|
||||
fatalerror = false;
|
||||
this->size = size;
|
||||
iterate_pos = iterate_depth = 0;
|
||||
main_array = (HashItem **)malloc(this->size * 4);
|
||||
|
||||
if (main_array == NULL) {
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
for (int x = 0; x < this->size; x++) {
|
||||
main_array[x] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SFHash::SFHash() {
|
||||
SFHash(4096);
|
||||
}
|
||||
|
||||
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];
|
||||
while (item != NULL) {
|
||||
HashItem *t = item->next;
|
||||
delete item;
|
||||
item = t;
|
||||
}
|
||||
}
|
||||
free(main_array);
|
||||
}
|
||||
|
46
src/add-ons/translators/giftranslator/SFHash.h
Normal file
46
src/add-ons/translators/giftranslator/SFHash.h
Normal file
@ -0,0 +1,46 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: SFHash.h
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFHASH_H
|
||||
#define SFHASH_H
|
||||
|
||||
class HashItem {
|
||||
friend class SFHash;
|
||||
public:
|
||||
unsigned int key;
|
||||
private:
|
||||
HashItem *next;
|
||||
};
|
||||
|
||||
class SFHash {
|
||||
public:
|
||||
SFHash();
|
||||
SFHash(int size);
|
||||
~SFHash();
|
||||
|
||||
void AddItem(HashItem *item);
|
||||
HashItem *GetItem(unsigned int key);
|
||||
unsigned int CountItems();
|
||||
HashItem *NextItem();
|
||||
void Rewind();
|
||||
|
||||
bool fatalerror;
|
||||
private:
|
||||
int size, iterate_pos, iterate_depth;
|
||||
HashItem **main_array;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
331
src/add-ons/translators/giftranslator/SavePalette.cpp
Normal file
331
src/add-ons/translators/giftranslator/SavePalette.cpp
Normal file
@ -0,0 +1,331 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: SavePalette.cpp
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SavePalette.h"
|
||||
#include <Bitmap.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
extern bool debug;
|
||||
|
||||
const rgb_color wsp[256] = {
|
||||
{0xff, 0xff, 0xff, 0xff}, {0xff, 0xff, 0xcc, 0xff},
|
||||
{0xff, 0xff, 0x99, 0xff}, {0xff, 0xff, 0x66, 0xff},
|
||||
{0xff, 0xff, 0x33, 0xff}, {0xff, 0xff, 0x00, 0xff},
|
||||
{0xff, 0xcc, 0xff, 0xff}, {0xff, 0xcc, 0xcc, 0xff},
|
||||
{0xff, 0xcc, 0x99, 0xff}, {0xff, 0xcc, 0x66, 0xff},
|
||||
{0xff, 0xcc, 0x33, 0xff}, {0xff, 0xcc, 0x00, 0xff},
|
||||
{0xff, 0x99, 0xff, 0xff}, {0xff, 0x99, 0xcc, 0xff},
|
||||
{0xff, 0x99, 0x99, 0xff}, {0xff, 0x99, 0x66, 0xff},
|
||||
{0xff, 0x99, 0x33, 0xff}, {0xff, 0x99, 0x00, 0xff},
|
||||
{0xff, 0x66, 0xff, 0xff}, {0xff, 0x66, 0xcc, 0xff},
|
||||
{0xff, 0x66, 0x99, 0xff}, {0xff, 0x66, 0x66, 0xff},
|
||||
{0xff, 0x66, 0x33, 0xff}, {0xff, 0x66, 0x00, 0xff},
|
||||
{0xff, 0x33, 0xff, 0xff}, {0xff, 0x33, 0xcc, 0xff},
|
||||
{0xff, 0x33, 0x99, 0xff}, {0xff, 0x33, 0x66, 0xff},
|
||||
{0xff, 0x33, 0x33, 0xff}, {0xff, 0x33, 0x00, 0xff},
|
||||
{0xff, 0x00, 0xff, 0xff}, {0xff, 0x00, 0xcc, 0xff},
|
||||
{0xff, 0x00, 0x99, 0xff}, {0xff, 0x00, 0x66, 0xff},
|
||||
{0xff, 0x00, 0x33, 0xff}, {0xff, 0x00, 0x00, 0xff},
|
||||
{0xcc, 0xff, 0xff, 0xff}, {0xcc, 0xff, 0xcc, 0xff},
|
||||
{0xcc, 0xff, 0x99, 0xff}, {0xcc, 0xff, 0x66, 0xff},
|
||||
{0xcc, 0xff, 0x33, 0xff}, {0xcc, 0xff, 0x00, 0xff},
|
||||
{0xcc, 0xcc, 0xff, 0xff}, {0xcc, 0xcc, 0xcc, 0xff},
|
||||
{0xcc, 0xcc, 0x99, 0xff}, {0xcc, 0xcc, 0x66, 0xff},
|
||||
{0xcc, 0xcc, 0x33, 0xff}, {0xcc, 0xcc, 0x00, 0xff},
|
||||
{0xcc, 0x99, 0xff, 0xff}, {0xcc, 0x99, 0xcc, 0xff},
|
||||
{0xcc, 0x99, 0x99, 0xff}, {0xcc, 0x99, 0x66, 0xff},
|
||||
{0xcc, 0x99, 0x33, 0xff}, {0xcc, 0x99, 0x00, 0xff},
|
||||
{0xcc, 0x66, 0xff, 0xff}, {0xcc, 0x66, 0xcc, 0xff},
|
||||
{0xcc, 0x66, 0x99, 0xff}, {0xcc, 0x66, 0x66, 0xff},
|
||||
{0xcc, 0x66, 0x33, 0xff}, {0xcc, 0x66, 0x00, 0xff},
|
||||
{0xcc, 0x33, 0xff, 0xff}, {0xcc, 0x33, 0xcc, 0xff},
|
||||
{0xcc, 0x33, 0x99, 0xff}, {0xcc, 0x33, 0x66, 0xff},
|
||||
{0xcc, 0x33, 0x33, 0xff}, {0xcc, 0x33, 0x00, 0xff},
|
||||
{0xcc, 0x00, 0xff, 0xff}, {0xcc, 0x00, 0xcc, 0xff},
|
||||
{0xcc, 0x00, 0x99, 0xff}, {0xcc, 0x00, 0x66, 0xff},
|
||||
{0xcc, 0x00, 0x33, 0xff}, {0xcc, 0x00, 0x00, 0xff},
|
||||
{0x99, 0xff, 0xff, 0xff}, {0x99, 0xff, 0xcc, 0xff},
|
||||
{0x99, 0xff, 0x99, 0xff}, {0x99, 0xff, 0x66, 0xff},
|
||||
{0x99, 0xff, 0x33, 0xff}, {0x99, 0xff, 0x00, 0xff},
|
||||
{0x99, 0xcc, 0xff, 0xff}, {0x99, 0xcc, 0xcc, 0xff},
|
||||
{0x99, 0xcc, 0x99, 0xff}, {0x99, 0xcc, 0x66, 0xff},
|
||||
{0x99, 0xcc, 0x33, 0xff}, {0x99, 0xcc, 0x00, 0xff},
|
||||
{0x99, 0x99, 0xff, 0xff}, {0x99, 0x99, 0xcc, 0xff},
|
||||
{0x99, 0x99, 0x99, 0xff}, {0x99, 0x99, 0x66, 0xff},
|
||||
{0x99, 0x99, 0x33, 0xff}, {0x99, 0x99, 0x00, 0xff},
|
||||
{0x99, 0x66, 0xff, 0xff}, {0x99, 0x66, 0xcc, 0xff},
|
||||
{0x99, 0x66, 0x99, 0xff}, {0x99, 0x66, 0x66, 0xff},
|
||||
{0x99, 0x66, 0x33, 0xff}, {0x99, 0x66, 0x00, 0xff},
|
||||
{0x99, 0x33, 0xff, 0xff}, {0x99, 0x33, 0xcc, 0xff},
|
||||
{0x99, 0x33, 0x99, 0xff}, {0x99, 0x33, 0x66, 0xff},
|
||||
{0x99, 0x33, 0x33, 0xff}, {0x99, 0x33, 0x00, 0xff},
|
||||
{0x99, 0x00, 0xff, 0xff}, {0x99, 0x00, 0xcc, 0xff},
|
||||
{0x99, 0x00, 0x99, 0xff}, {0x99, 0x00, 0x66, 0xff},
|
||||
{0x99, 0x00, 0x33, 0xff}, {0x99, 0x00, 0x00, 0xff},
|
||||
{0x66, 0xff, 0xff, 0xff}, {0x66, 0xff, 0xcc, 0xff},
|
||||
{0x66, 0xff, 0x99, 0xff}, {0x66, 0xff, 0x66, 0xff},
|
||||
{0x66, 0xff, 0x33, 0xff}, {0x66, 0xff, 0x00, 0xff},
|
||||
{0x66, 0xcc, 0xff, 0xff}, {0x66, 0xcc, 0xcc, 0xff},
|
||||
{0x66, 0xcc, 0x99, 0xff}, {0x66, 0xcc, 0x66, 0xff},
|
||||
{0x66, 0xcc, 0x33, 0xff}, {0x66, 0xcc, 0x00, 0xff},
|
||||
{0x66, 0x99, 0xff, 0xff}, {0x66, 0x99, 0xcc, 0xff},
|
||||
{0x66, 0x99, 0x99, 0xff}, {0x66, 0x99, 0x66, 0xff},
|
||||
{0x66, 0x99, 0x33, 0xff}, {0x66, 0x99, 0x00, 0xff},
|
||||
{0x66, 0x66, 0xff, 0xff}, {0x66, 0x66, 0xcc, 0xff},
|
||||
{0x66, 0x66, 0x99, 0xff}, {0x66, 0x66, 0x66, 0xff},
|
||||
{0x66, 0x66, 0x33, 0xff}, {0x66, 0x66, 0x00, 0xff},
|
||||
{0x66, 0x33, 0xff, 0xff}, {0x66, 0x33, 0xcc, 0xff},
|
||||
{0x66, 0x33, 0x99, 0xff}, {0x66, 0x33, 0x66, 0xff},
|
||||
{0x66, 0x33, 0x33, 0xff}, {0x66, 0x33, 0x00, 0xff},
|
||||
{0x66, 0x00, 0xff, 0xff}, {0x66, 0x00, 0xcc, 0xff},
|
||||
{0x66, 0x00, 0x99, 0xff}, {0x66, 0x00, 0x66, 0xff},
|
||||
{0x66, 0x00, 0x33, 0xff}, {0x66, 0x00, 0x00, 0xff},
|
||||
{0x33, 0xff, 0xff, 0xff}, {0x33, 0xff, 0xcc, 0xff},
|
||||
{0x33, 0xff, 0x99, 0xff}, {0x33, 0xff, 0x66, 0xff},
|
||||
{0x33, 0xff, 0x33, 0xff}, {0x33, 0xff, 0x00, 0xff},
|
||||
{0x33, 0xcc, 0xff, 0xff}, {0x33, 0xcc, 0xcc, 0xff},
|
||||
{0x33, 0xcc, 0x99, 0xff}, {0x33, 0xcc, 0x66, 0xff},
|
||||
{0x33, 0xcc, 0x33, 0xff}, {0x33, 0xcc, 0x00, 0xff},
|
||||
{0x33, 0x99, 0xff, 0xff}, {0x33, 0x99, 0xcc, 0xff},
|
||||
{0x33, 0x99, 0x99, 0xff}, {0x33, 0x99, 0x66, 0xff},
|
||||
{0x33, 0x99, 0x33, 0xff}, {0x33, 0x99, 0x00, 0xff},
|
||||
{0x33, 0x66, 0xff, 0xff}, {0x33, 0x66, 0xcc, 0xff},
|
||||
{0x33, 0x66, 0x99, 0xff}, {0x33, 0x66, 0x66, 0xff},
|
||||
{0x33, 0x66, 0x33, 0xff}, {0x33, 0x66, 0x00, 0xff},
|
||||
{0x33, 0x33, 0xff, 0xff}, {0x33, 0x33, 0xcc, 0xff},
|
||||
{0x33, 0x33, 0x99, 0xff}, {0x33, 0x33, 0x66, 0xff},
|
||||
{0x33, 0x33, 0x33, 0xff}, {0x33, 0x33, 0x00, 0xff},
|
||||
{0x33, 0x00, 0xff, 0xff}, {0x33, 0x00, 0xcc, 0xff},
|
||||
{0x33, 0x00, 0x99, 0xff}, {0x33, 0x00, 0x66, 0xff},
|
||||
{0x33, 0x00, 0x33, 0xff}, {0x33, 0x00, 0x00, 0xff},
|
||||
{0x00, 0xff, 0xff, 0xff}, {0x00, 0xff, 0xcc, 0xff},
|
||||
{0x00, 0xff, 0x99, 0xff}, {0x00, 0xff, 0x66, 0xff},
|
||||
{0x00, 0xff, 0x33, 0xff}, {0x00, 0xff, 0x00, 0xff},
|
||||
{0x00, 0xcc, 0xff, 0xff}, {0x00, 0xcc, 0xcc, 0xff},
|
||||
{0x00, 0xcc, 0x99, 0xff}, {0x00, 0xcc, 0x66, 0xff},
|
||||
{0x00, 0xcc, 0x33, 0xff}, {0x00, 0xcc, 0x00, 0xff},
|
||||
{0x00, 0x99, 0xff, 0xff}, {0x00, 0x99, 0xcc, 0xff},
|
||||
{0x00, 0x99, 0x99, 0xff}, {0x00, 0x99, 0x66, 0xff},
|
||||
{0x00, 0x99, 0x33, 0xff}, {0x00, 0x99, 0x00, 0xff},
|
||||
{0x00, 0x66, 0xff, 0xff}, {0x00, 0x66, 0xcc, 0xff},
|
||||
{0x00, 0x66, 0x99, 0xff}, {0x00, 0x66, 0x66, 0xff},
|
||||
{0x00, 0x66, 0x33, 0xff}, {0x00, 0x66, 0x00, 0xff},
|
||||
{0x00, 0x33, 0xff, 0xff}, {0x00, 0x33, 0xcc, 0xff},
|
||||
{0x00, 0x33, 0x99, 0xff}, {0x00, 0x33, 0x66, 0xff},
|
||||
{0x00, 0x33, 0x33, 0xff}, {0x00, 0x33, 0x00, 0xff},
|
||||
{0x00, 0x00, 0xff, 0xff}, {0x00, 0x00, 0xcc, 0xff},
|
||||
{0x00, 0x00, 0x99, 0xff}, {0x00, 0x00, 0x66, 0xff},
|
||||
{0x00, 0x00, 0x33, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
|
||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff}
|
||||
};
|
||||
|
||||
ColorItem::ColorItem(unsigned int k, unsigned int c) {
|
||||
key = k;
|
||||
count = c;
|
||||
}
|
||||
|
||||
SavePalette::SavePalette() {
|
||||
pal = new rgb_color[256];
|
||||
backgroundindex = 0;
|
||||
usetransparent = false;
|
||||
transparentindex = 0;
|
||||
size = size_in_bits = 0;
|
||||
fatalerror = false;
|
||||
mode = WEB_SAFE_PALETTE;
|
||||
}
|
||||
|
||||
SavePalette::SavePalette(int predefined) {
|
||||
pal = new rgb_color[256];
|
||||
backgroundindex = 0;
|
||||
usetransparent = false;
|
||||
transparentindex = 0;
|
||||
fatalerror = false;
|
||||
|
||||
mode = predefined;
|
||||
size_in_bits = 8;
|
||||
|
||||
if (predefined == WEB_SAFE_PALETTE) {
|
||||
memcpy(pal, wsp, sizeof(rgb_color) * 256);
|
||||
size = 216;
|
||||
} else if (predefined == BEOS_SYSTEM_PALETTE) {
|
||||
color_map *map = (color_map *)system_colors();
|
||||
memcpy(pal, map->color_list, sizeof(rgb_color) * 256);
|
||||
size = 256;
|
||||
} else if (predefined == GREYSCALE_PALETTE) {
|
||||
for (int x = 0; x < 256; x++) {
|
||||
pal[x].red = pal[x].green = pal[x].blue = x;
|
||||
pal[x].alpha = 0xff;
|
||||
}
|
||||
size = 256;
|
||||
}
|
||||
}
|
||||
|
||||
SavePalette::SavePalette(BBitmap *bitmap) {
|
||||
pal = new rgb_color[256];
|
||||
backgroundindex = 0;
|
||||
usetransparent = false;
|
||||
transparentindex = 0;
|
||||
fatalerror = false;
|
||||
mode = OPTIMAL_PALETTE;
|
||||
|
||||
SFHash *hash = new SFHash(1 << 16);
|
||||
if (hash == NULL || hash->fatalerror) {
|
||||
if (debug) printf("Out of memory in SavePalette(BBitmap *)\n");
|
||||
if (hash != NULL) delete hash;
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
unsigned char r, g, b;
|
||||
|
||||
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);
|
||||
}
|
||||
delete hash;
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
|
||||
BRect rect = bitmap->Bounds();
|
||||
int height = rect.IntegerHeight() + 1;
|
||||
int width = rect.IntegerWidth() + 1;
|
||||
unsigned char *bits = (unsigned char *)bitmap->Bits();
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
if (cs == B_RGB32 || cs == B_RGBA32) {
|
||||
b = bits[0];
|
||||
g = bits[1];
|
||||
r = bits[2];
|
||||
} else {
|
||||
r = bits[1];
|
||||
g = bits[2];
|
||||
b = bits[3];
|
||||
}
|
||||
bits += 4;
|
||||
|
||||
unsigned int key = (r << 16) + (g << 8) + b;
|
||||
ColorItem *ci = (ColorItem *)hash->GetItem(key);
|
||||
if (ci == NULL) {
|
||||
ci = new ColorItem(key, 1);
|
||||
if (ci == NULL) {
|
||||
if (debug) printf("Out of memory in SavePalette(BBitmap *)\n");
|
||||
delete hash;
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
hash->AddItem((HashItem *)ci);
|
||||
} else {
|
||||
ci->count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int unique_colors = hash->CountItems();
|
||||
size_in_bits = 1;
|
||||
while (((1 << size_in_bits) < unique_colors) && (size_in_bits < 8)) size_in_bits++;
|
||||
size = 1 << size_in_bits;
|
||||
|
||||
ColorItem **topcolors = (ColorItem **)malloc(size * 4);
|
||||
if (topcolors == NULL) {
|
||||
if (debug) printf("Out of memory in SavePalette(BBitmap *)\n");
|
||||
delete hash;
|
||||
fatalerror = true;
|
||||
return;
|
||||
}
|
||||
ColorItem *dummy = new ColorItem(0, 0);
|
||||
for (int x = 0; x < size; x++) topcolors[x] = dummy;
|
||||
|
||||
for (int x = 0; x < unique_colors; x++) {
|
||||
ColorItem *ci = (ColorItem *)hash->NextItem();
|
||||
for (int y = 0; y < size; y++) {
|
||||
if (ci->count > topcolors[y]->count) {
|
||||
for (int z = size - 1; z > y; z--) {
|
||||
topcolors[z] = topcolors[z-1];
|
||||
}
|
||||
topcolors[y] = ci;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x < size; x++) {
|
||||
pal[x].red = topcolors[x]->key >> 16;
|
||||
pal[x].green = (topcolors[x]->key & 0xff00) >> 8;
|
||||
pal[x].blue = topcolors[x]->key & 0xff;
|
||||
pal[x].alpha = 0xff;
|
||||
}
|
||||
|
||||
delete dummy;
|
||||
free(topcolors);
|
||||
delete hash;
|
||||
}
|
||||
|
||||
/* Standard mapping services once a palette is loaded */
|
||||
unsigned char SavePalette::IndexForColor(unsigned char red, unsigned char green,
|
||||
unsigned char blue) {
|
||||
|
||||
if (mode == GREYSCALE_PALETTE) {
|
||||
unsigned char result = (red + (green << 1) + blue) >> 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned char best = 0;
|
||||
int min = 255 * 3;
|
||||
|
||||
for (int x = 0; x < size && min != 0; x++) {
|
||||
int diff = abs(red - pal[x].red);
|
||||
diff += abs(green - pal[x].green);
|
||||
diff += abs(blue - pal[x].blue);
|
||||
if (diff < min) {
|
||||
min = diff;
|
||||
best = x;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
unsigned char SavePalette::IndexForColor(rgb_color color) {
|
||||
return IndexForColor(color.red, color.green, color.blue);
|
||||
}
|
||||
|
||||
SavePalette::~SavePalette() {
|
||||
delete [] pal;
|
||||
}
|
||||
|
60
src/add-ons/translators/giftranslator/SavePalette.h
Normal file
60
src/add-ons/translators/giftranslator/SavePalette.h
Normal file
@ -0,0 +1,60 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: SavePalette.h
|
||||
//
|
||||
// Date: December 1999
|
||||
//
|
||||
// Author: Daniel Switkin
|
||||
//
|
||||
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
|
||||
// under the BSD license, with the stipulations that this complete header must
|
||||
// remain at the top of the file indefinitely, and credit must be given to the
|
||||
// original author in any about box using this software.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SAVE_PALETTE_H
|
||||
#define SAVE_PALETTE_H
|
||||
|
||||
#include "SFHash.h"
|
||||
#include <GraphicsDefs.h>
|
||||
class BBitmap;
|
||||
|
||||
enum {
|
||||
WEB_SAFE_PALETTE = 0,
|
||||
BEOS_SYSTEM_PALETTE,
|
||||
GREYSCALE_PALETTE,
|
||||
OPTIMAL_PALETTE
|
||||
};
|
||||
|
||||
class ColorItem : public HashItem {
|
||||
public:
|
||||
ColorItem(unsigned int k, unsigned int c);
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
class ColorCache : public HashItem {
|
||||
public:
|
||||
unsigned char index;
|
||||
};
|
||||
|
||||
class SavePalette {
|
||||
public:
|
||||
SavePalette(int predefined);
|
||||
SavePalette(BBitmap *bitmap);
|
||||
SavePalette();
|
||||
~SavePalette();
|
||||
|
||||
unsigned char IndexForColor(unsigned char red, unsigned char green,
|
||||
unsigned char blue);
|
||||
unsigned char IndexForColor(rgb_color color);
|
||||
|
||||
rgb_color *pal;
|
||||
int size, size_in_bits, mode;
|
||||
bool usetransparent;
|
||||
int backgroundindex, transparentindex;
|
||||
bool fatalerror;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user