* reworked GUI to have better layout and be more font-sensitive
* added option to specify max number of colors * improved palette creation (quite an improvement with my test images, but a better color reduction algorithm surely exist) * more to come with regards to transparency (for examply, being able to specify the transparent index seems like complete bogus to me) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14294 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -13,6 +13,8 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||||
|
|
||||||
#include "GIFSave.h"
|
#include "GIFSave.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -26,7 +28,14 @@ const int32 seven_sixteenth = (int32)((7.0 / 16.0) * 32768);
|
|||||||
|
|
||||||
extern bool debug;
|
extern bool debug;
|
||||||
|
|
||||||
GIFSave::GIFSave(BBitmap *bitmap, BPositionIO *output) {
|
class ColorCache : public HashItem {
|
||||||
|
public:
|
||||||
|
unsigned char index;
|
||||||
|
};
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
GIFSave::GIFSave(BBitmap *bitmap, BPositionIO *output)
|
||||||
|
{
|
||||||
color_space cs = bitmap->ColorSpace();
|
color_space cs = bitmap->ColorSpace();
|
||||||
if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG && cs != B_RGBA32_BIG) {
|
if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG && cs != B_RGBA32_BIG) {
|
||||||
if (debug) printf("GIFSave::GIFSave() - Unknown color space\n");
|
if (debug) printf("GIFSave::GIFSave() - Unknown color space\n");
|
||||||
@@ -36,9 +45,11 @@ GIFSave::GIFSave(BBitmap *bitmap, BPositionIO *output) {
|
|||||||
|
|
||||||
fatalerror = false;
|
fatalerror = false;
|
||||||
prefs = new Prefs();
|
prefs = new Prefs();
|
||||||
if (prefs->palettemode == OPTIMAL_PALETTE) palette = new SavePalette(bitmap);
|
if (prefs->palettemode == OPTIMAL_PALETTE)
|
||||||
else palette = new SavePalette(prefs->palettemode);
|
palette = new SavePalette(bitmap, prefs->palette_size_in_bits);
|
||||||
if (palette->fatalerror) {
|
else
|
||||||
|
palette = new SavePalette(prefs->palettemode);
|
||||||
|
if (!palette->IsValid()) {
|
||||||
fatalerror = true;
|
fatalerror = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -86,33 +97,32 @@ GIFSave::GIFSave(BBitmap *bitmap, BPositionIO *output) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
palette->usetransparent = prefs->usetransparent;
|
palette->SetUseTransparent(prefs->usetransparent);
|
||||||
if (prefs->usetransparent) {
|
if (prefs->usetransparent) {
|
||||||
if (prefs->usetransparentindex) {
|
if (prefs->usetransparentindex) {
|
||||||
palette->transparentindex = prefs->transparentindex;
|
palette->SetTransparentIndex(prefs->transparentindex);
|
||||||
if (debug) printf("GIFSave::GIFSave() - Using transparent index %d\n", palette->transparentindex);
|
if (debug)
|
||||||
|
printf("GIFSave::GIFSave() - Using transparent index %d\n", palette->TransparentIndex());
|
||||||
} else {
|
} else {
|
||||||
palette->transparentindex = -1;
|
bool found = palette->SetTransparentColor((uint8)prefs->transparentred,
|
||||||
for (int x = 0; x < palette->size; x++) {
|
(uint8)prefs->transparentred,
|
||||||
if (palette->pal[x].red == prefs->transparentred &&
|
(uint8)prefs->transparentblue);
|
||||||
palette->pal[x].green == prefs->transparentgreen &&
|
if (found) {
|
||||||
palette->pal[x].blue == prefs->transparentblue) {
|
if (debug) {
|
||||||
|
printf("GIFSave::GIFSave() - Found transparent color %d,%d,%d at index %d\n",
|
||||||
palette->transparentindex = x;
|
prefs->transparentred, prefs->transparentgreen, prefs->transparentblue,
|
||||||
if (debug) printf("GIFSave::GIFSave() - Found transparent color %d,%d,%d at index %d\n", prefs->transparentred,
|
palette->TransparentIndex());
|
||||||
prefs->transparentgreen, prefs->transparentblue, x);
|
}
|
||||||
break;
|
} else {
|
||||||
|
if (debug) {
|
||||||
|
printf("GIFSave::GIFSave() - Did not find color %d,%d,%d - deactivating transparency\n",
|
||||||
|
prefs->transparentred, prefs->transparentgreen, prefs->transparentblue);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
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 {
|
} else {
|
||||||
if (debug) printf("GIFSave::GIFSave() - Not using transparency\n");
|
if (debug)
|
||||||
|
printf("GIFSave::GIFSave() - Not using transparency\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
this->output = output;
|
this->output = output;
|
||||||
@@ -140,38 +150,50 @@ GIFSave::GIFSave(BBitmap *bitmap, BPositionIO *output) {
|
|||||||
output->Write(&t, 1);
|
output->Write(&t, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIFSave::WriteGIFHeader() {
|
// destructor
|
||||||
|
GIFSave::~GIFSave()
|
||||||
|
{
|
||||||
|
delete palette;
|
||||||
|
delete prefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteGIFHeader
|
||||||
|
void
|
||||||
|
GIFSave::WriteGIFHeader()
|
||||||
|
{
|
||||||
// Standard header
|
// Standard header
|
||||||
unsigned char header[] = {'G', 'I', 'F', '8', '9', 'a', 0, 0, 0, 0, 0, 0, 0};
|
unsigned char header[] = {'G', 'I', 'F', '8', '9', 'a', 0, 0, 0, 0, 0, 0, 0};
|
||||||
header[6] = width & 0xff;
|
header[6] = width & 0xff;
|
||||||
header[7] = (width & 0xff00) >> 8;
|
header[7] = (width & 0xff00) >> 8;
|
||||||
header[8] = height & 0xff;
|
header[8] = height & 0xff;
|
||||||
header[9] = (height & 0xff00) >> 8;
|
header[9] = (height & 0xff00) >> 8;
|
||||||
header[10] = 0xf0 | (palette->size_in_bits - 1);
|
header[10] = 0xf0 | (palette->SizeInBits() - 1);
|
||||||
header[11] = palette->backgroundindex;
|
header[11] = palette->BackgroundIndex();
|
||||||
output->Write(header, 13);
|
output->Write(header, 13);
|
||||||
|
|
||||||
// Global palette
|
// Global palette
|
||||||
int size = 1 << palette->size_in_bits;
|
int size = (1 << palette->SizeInBits()) * 3;
|
||||||
char c[256 * 3]; // can't be bigger than this
|
uint8* buffer = new uint8[size]; // can't be bigger than this
|
||||||
for (int x = 0; x < size; x++) {
|
palette->GetColors(buffer, size);
|
||||||
c[x * 3] = palette->pal[x].red;
|
output->Write(buffer, size);
|
||||||
c[x * 3 + 1] = palette->pal[x].green;
|
delete[] buffer;
|
||||||
c[x * 3 + 2] = palette->pal[x].blue;
|
|
||||||
}
|
|
||||||
output->Write(c, size * 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIFSave::WriteGIFControlBlock() {
|
// 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) {
|
if (palette->UseTransparent()) {
|
||||||
b[3] = b[3] | 1;
|
b[3] = b[3] | 1;
|
||||||
b[6] = palette->transparentindex;
|
b[6] = palette->TransparentIndex();
|
||||||
}
|
}
|
||||||
output->Write(b, 8);
|
output->Write(b, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIFSave::WriteGIFImageHeader() {
|
// WriteGIFImageHeader
|
||||||
|
void GIFSave::WriteGIFImageHeader()
|
||||||
|
{
|
||||||
unsigned char header[10];
|
unsigned char header[10];
|
||||||
header[0] = 0x2c;
|
header[0] = 0x2c;
|
||||||
header[1] = header[2] = 0;
|
header[1] = header[2] = 0;
|
||||||
@@ -187,7 +209,9 @@ void GIFSave::WriteGIFImageHeader() {
|
|||||||
output->Write(header, 10);
|
output->Write(header, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIFSave::WriteGIFImageData() {
|
// WriteGIFImageData
|
||||||
|
void GIFSave::WriteGIFImageData()
|
||||||
|
{
|
||||||
InitFrame();
|
InitFrame();
|
||||||
code_value = (short *)malloc(HASHSIZE * 2);
|
code_value = (short *)malloc(HASHSIZE * 2);
|
||||||
prefix_code = (short *)malloc(HASHSIZE * 2);
|
prefix_code = (short *)malloc(HASHSIZE * 2);
|
||||||
@@ -232,7 +256,10 @@ void GIFSave::WriteGIFImageData() {
|
|||||||
free(append_char);
|
free(append_char);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIFSave::OutputCode(short code, int BITS, bool flush) {
|
// OutputCode
|
||||||
|
void
|
||||||
|
GIFSave::OutputCode(short code, int BITS, bool flush)
|
||||||
|
{
|
||||||
if (!flush) {
|
if (!flush) {
|
||||||
bit_buffer |= (unsigned int) code << bit_count;
|
bit_buffer |= (unsigned int) code << bit_count;
|
||||||
bit_count += BITS;
|
bit_count += BITS;
|
||||||
@@ -266,7 +293,10 @@ void GIFSave::OutputCode(short code, int BITS, bool flush) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIFSave::ResetHashtable() {
|
// ResetHashtable
|
||||||
|
void
|
||||||
|
GIFSave::ResetHashtable()
|
||||||
|
{
|
||||||
for (int q = 0; q < HASHSIZE; q++) {
|
for (int q = 0; q < HASHSIZE; q++) {
|
||||||
code_value[q] = -1;
|
code_value[q] = -1;
|
||||||
prefix_code[q] = 0;
|
prefix_code[q] = 0;
|
||||||
@@ -274,7 +304,10 @@ void GIFSave::ResetHashtable() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int GIFSave::CheckHashtable(int s, unsigned char c) {
|
// CheckHashtable
|
||||||
|
int
|
||||||
|
GIFSave::CheckHashtable(int s, unsigned char c)
|
||||||
|
{
|
||||||
if (s == -1) return c;
|
if (s == -1) return c;
|
||||||
int hashindex = HASH(s, c);
|
int hashindex = HASH(s, c);
|
||||||
int nextindex;
|
int nextindex;
|
||||||
@@ -286,7 +319,10 @@ int GIFSave::CheckHashtable(int s, unsigned char c) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIFSave::AddToHashtable(int s, unsigned char c) {
|
// AddToHashtable
|
||||||
|
void
|
||||||
|
GIFSave::AddToHashtable(int s, unsigned char c)
|
||||||
|
{
|
||||||
int hashindex = HASH(s, c);
|
int hashindex = HASH(s, c);
|
||||||
while (code_value[hashindex] != -1) hashindex = (hashindex + HASHSTEP) % HASHSIZE;
|
while (code_value[hashindex] != -1) hashindex = (hashindex + HASHSTEP) % HASHSIZE;
|
||||||
code_value[hashindex] = next_code;
|
code_value[hashindex] = next_code;
|
||||||
@@ -294,7 +330,10 @@ void GIFSave::AddToHashtable(int s, unsigned char c) {
|
|||||||
append_char[next_code] = c;
|
append_char[next_code] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char GIFSave::NextPixel(int pixel) {
|
// NextPixel
|
||||||
|
unsigned char
|
||||||
|
GIFSave::NextPixel(int pixel)
|
||||||
|
{
|
||||||
int bpr = bitmap->BytesPerRow();
|
int bpr = bitmap->BytesPerRow();
|
||||||
color_space cs = bitmap->ColorSpace();
|
color_space cs = bitmap->ColorSpace();
|
||||||
unsigned char r, g, b;
|
unsigned char r, g, b;
|
||||||
@@ -340,7 +379,7 @@ unsigned char GIFSave::NextPixel(int pixel) {
|
|||||||
cc->index = palette->IndexForColor(r, g, b);
|
cc->index = palette->IndexForColor(r, g, b);
|
||||||
hash->AddItem((HashItem *)cc);
|
hash->AddItem((HashItem *)cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefs->usedithering) {
|
if (prefs->usedithering) {
|
||||||
int x = pixel % width;
|
int x = pixel % width;
|
||||||
// Don't carry error on to next line when interlaced because
|
// Don't carry error on to next line when interlaced because
|
||||||
@@ -352,10 +391,10 @@ unsigned char GIFSave::NextPixel(int pixel) {
|
|||||||
blue_error[y] = 0;
|
blue_error[y] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 red_total_error = palette->pal[cc->index].red - r;
|
int32 red_total_error = palette->pal[cc->index].red - r;
|
||||||
int32 green_total_error = palette->pal[cc->index].green - g;
|
int32 green_total_error = palette->pal[cc->index].green - g;
|
||||||
int32 blue_total_error = palette->pal[cc->index].blue - b;
|
int32 blue_total_error = palette->pal[cc->index].blue - b;
|
||||||
|
|
||||||
red_side_error = (red_error[x + 1] + (red_total_error * seven_sixteenth)) >> 15;
|
red_side_error = (red_error[x + 1] + (red_total_error * seven_sixteenth)) >> 15;
|
||||||
blue_side_error = (blue_error[x + 1] + (blue_total_error * seven_sixteenth)) >> 15;
|
blue_side_error = (blue_error[x + 1] + (blue_total_error * seven_sixteenth)) >> 15;
|
||||||
@@ -368,7 +407,7 @@ unsigned char GIFSave::NextPixel(int pixel) {
|
|||||||
red_error[x] += (red_total_error * five_sixteenth);
|
red_error[x] += (red_total_error * five_sixteenth);
|
||||||
green_error[x] += (green_total_error * five_sixteenth);
|
green_error[x] += (green_total_error * five_sixteenth);
|
||||||
blue_error[x] += (blue_total_error * five_sixteenth);
|
blue_error[x] += (blue_total_error * five_sixteenth);
|
||||||
|
|
||||||
red_error[x + 1] = (red_total_error * one_sixteenth);
|
red_error[x + 1] = (red_total_error * one_sixteenth);
|
||||||
green_error[x + 1] = (green_total_error * one_sixteenth);
|
green_error[x + 1] = (green_total_error * one_sixteenth);
|
||||||
blue_error[x + 1] = (blue_total_error * one_sixteenth);
|
blue_error[x + 1] = (blue_total_error * one_sixteenth);
|
||||||
@@ -377,9 +416,13 @@ unsigned char GIFSave::NextPixel(int pixel) {
|
|||||||
return cc->index;
|
return cc->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIFSave::InitFrame() {
|
// InitFrame
|
||||||
code_size = palette->size_in_bits;
|
void
|
||||||
if (code_size == 1) code_size++;
|
GIFSave::InitFrame()
|
||||||
|
{
|
||||||
|
code_size = palette->SizeInBits();
|
||||||
|
if (code_size == 1)
|
||||||
|
code_size++;
|
||||||
BITS = code_size + 1;
|
BITS = code_size + 1;
|
||||||
clear_code = 1 << code_size;
|
clear_code = 1 << code_size;
|
||||||
end_code = clear_code + 1;
|
end_code = clear_code + 1;
|
||||||
@@ -398,9 +441,3 @@ void GIFSave::InitFrame() {
|
|||||||
|
|
||||||
gifbits = (unsigned char *)bitmap->Bits();
|
gifbits = (unsigned char *)bitmap->Bits();
|
||||||
}
|
}
|
||||||
|
|
||||||
GIFSave::~GIFSave() {
|
|
||||||
delete palette;
|
|
||||||
delete prefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ status_t GetBitmap(BPositionIO *in, BBitmap **out);
|
|||||||
|
|
||||||
/* Required data */
|
/* Required data */
|
||||||
char translatorName[] = "GIF Images";
|
char translatorName[] = "GIF Images";
|
||||||
char translatorInfo[] = "GIF image translator v1.3";
|
char translatorInfo[] = "GIF image translator v1.4";
|
||||||
int32 translatorVersion = 0x130;
|
int32 translatorVersion = 0x140;
|
||||||
|
|
||||||
translation_format inputFormats[] = {
|
translation_format inputFormats[] = {
|
||||||
{ GIF_TYPE, B_TRANSLATOR_BITMAP, 0.8, 0.8, "image/gif", "GIF image" },
|
{ GIF_TYPE, B_TRANSLATOR_BITMAP, 0.8, 0.8, "image/gif", "GIF image" },
|
||||||
|
|||||||
@@ -13,19 +13,26 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "GIFView.h"
|
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||||
#include "SavePalette.h"
|
|
||||||
#include "Prefs.h"
|
|
||||||
#include <InterfaceKit.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <InterfaceKit.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "Prefs.h"
|
||||||
|
#include "SavePalette.h"
|
||||||
|
|
||||||
|
#include "GIFView.h"
|
||||||
|
|
||||||
extern int32 translatorVersion;
|
extern int32 translatorVersion;
|
||||||
extern char translatorName[];
|
extern char translatorName[];
|
||||||
|
|
||||||
GIFView::GIFView(BRect rect, const char *name) :
|
// constructor
|
||||||
BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW) {
|
GIFView::GIFView(BRect rect, const char *name)
|
||||||
|
: BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW)
|
||||||
|
{
|
||||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
|
||||||
font_height fh;
|
font_height fh;
|
||||||
@@ -39,111 +46,146 @@ GIFView::GIFView(BRect rect, const char *name) :
|
|||||||
char version_string[100];
|
char version_string[100];
|
||||||
sprintf(version_string, "v%d.%d.%d %s", (int)(translatorVersion >> 8), (int)((translatorVersion >> 4) & 0xf),
|
sprintf(version_string, "v%d.%d.%d %s", (int)(translatorVersion >> 8), (int)((translatorVersion >> 4) & 0xf),
|
||||||
(int)(translatorVersion & 0xf), __DATE__);
|
(int)(translatorVersion & 0xf), __DATE__);
|
||||||
r.top = r.bottom + 20;
|
|
||||||
be_plain_font->GetHeight(&fh);
|
be_plain_font->GetHeight(&fh);
|
||||||
r.bottom = r.top + fh.ascent + fh.descent;
|
r.bottom = r.top + fh.ascent + fh.descent;
|
||||||
|
r.left = r.right + 2.0 * r.Height();
|
||||||
r.right = r.left + be_plain_font->StringWidth(version_string);
|
r.right = r.left + be_plain_font->StringWidth(version_string);
|
||||||
|
|
||||||
BStringView *version = new BStringView(r, "Version", version_string);
|
BStringView *version = new BStringView(r, "Version", version_string);
|
||||||
version->SetFont(be_plain_font);
|
version->SetFont(be_plain_font);
|
||||||
AddChild(version);
|
AddChild(version);
|
||||||
|
|
||||||
|
BFont small(be_plain_font);
|
||||||
|
small.SetSize(max_c(7.0, small.Size() * 0.7));
|
||||||
const char *copyright_string = "© 2003 Daniel Switkin, [email protected]";
|
const char *copyright_string = "© 2003 Daniel Switkin, [email protected]";
|
||||||
r.top = r.bottom + 10;
|
r.top = r.bottom + 5;
|
||||||
|
r.left = 10;
|
||||||
r.bottom = r.top + fh.ascent + fh.descent;
|
r.bottom = r.top + fh.ascent + fh.descent;
|
||||||
r.right = r.left + be_plain_font->StringWidth(copyright_string);
|
r.right = rect.right - 10;
|
||||||
|
|
||||||
BStringView *copyright = new BStringView(r, "Copyright", copyright_string);
|
BStringView *copyright = new BStringView(r, "Copyright", copyright_string);
|
||||||
copyright->SetFont(be_plain_font);
|
copyright->SetFont(&small);
|
||||||
AddChild(copyright);
|
AddChild(copyright);
|
||||||
|
|
||||||
|
//menu fields (Palette & Colors)
|
||||||
|
fWebSafeMI = new BMenuItem("Websafe", new BMessage(GV_WEB_SAFE), 0, 0);
|
||||||
|
fBeOSSystemMI = new BMenuItem("BeOS System", new BMessage(GV_BEOS_SYSTEM), 0, 0);
|
||||||
|
fGreyScaleMI = new BMenuItem("Greyscale", new BMessage(GV_GREYSCALE), 0, 0);
|
||||||
|
fOptimalMI = new BMenuItem("Optimal", new BMessage(GV_OPTIMAL), 0, 0);
|
||||||
|
fPaletteM = new BPopUpMenu("PalettePopUpMenu", true, true, B_ITEMS_IN_COLUMN);
|
||||||
|
fPaletteM->AddItem(fWebSafeMI);
|
||||||
|
fPaletteM->AddItem(fBeOSSystemMI);
|
||||||
|
fPaletteM->AddItem(fGreyScaleMI);
|
||||||
|
fPaletteM->AddItem(fOptimalMI);
|
||||||
|
|
||||||
|
fColorCountM = new BPopUpMenu("ColorCountPopUpMenu", true, true, B_ITEMS_IN_COLUMN);
|
||||||
|
int32 count = 2;
|
||||||
|
for (int32 i = 0; i < 8; i++) {
|
||||||
|
BMessage* message = new BMessage(GV_SET_COLOR_COUNT);
|
||||||
|
message->AddInt32("size in bits", i + 1);
|
||||||
|
BString label;
|
||||||
|
label << count;
|
||||||
|
fColorCountMI[i] = new BMenuItem(label.String(), message, 0, 0);
|
||||||
|
fColorCountM->AddItem(fColorCountMI[i]);
|
||||||
|
count *= 2;
|
||||||
|
}
|
||||||
|
fColorCount256MI = fColorCountMI[7];
|
||||||
|
|
||||||
websafe = new BMenuItem("websafe", new BMessage(GV_WEB_SAFE), 0, 0);
|
r.top = r.bottom + 5;
|
||||||
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.bottom = r.top + 24;
|
||||||
r.right = r.left + be_plain_font->StringWidth("Palette:") +
|
fPaletteMF = new BMenuField(r, "PaletteMenuField", "Palette",
|
||||||
be_plain_font->StringWidth("BeOS system") + 32;
|
fPaletteM, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE);
|
||||||
palettemenufield = new BMenuField(r, "PaletteMenuField", "Palette:",
|
AddChild(fPaletteMF);
|
||||||
palettepopupmenu, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE);
|
|
||||||
AddChild(palettemenufield);
|
r.top = r.bottom + 5;
|
||||||
palettemenufield->SetDivider(be_plain_font->StringWidth("Palette:") + 7);
|
r.bottom = r.top + 24;
|
||||||
|
fColorCountMF = new BMenuField(r, "ColorCountMenuField", "Colors",
|
||||||
|
fColorCountM, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE);
|
||||||
|
AddChild(fColorCountMF);
|
||||||
|
|
||||||
r.top = palettemenufield->Frame().bottom + 5;
|
// align menu fields
|
||||||
|
float maxLabelWidth = ceilf(max_c(be_plain_font->StringWidth("Colors"),
|
||||||
|
be_plain_font->StringWidth("Palette")));
|
||||||
|
fPaletteMF->SetDivider(maxLabelWidth + 7);
|
||||||
|
fColorCountMF->SetDivider(maxLabelWidth + 7);
|
||||||
|
|
||||||
|
// check boxen
|
||||||
|
r.top = fColorCountMF->Frame().bottom + 5;
|
||||||
r.bottom = r.top + 10;
|
r.bottom = r.top + 10;
|
||||||
r.right = r.left + be_plain_font->StringWidth("Use dithering") + 20;
|
fUseDitheringCB = new BCheckBox(r, "UseDithering", "Use dithering",
|
||||||
usedithering = new BCheckBox(r, "UseDithering", "Use dithering",
|
|
||||||
new BMessage(GV_USE_DITHERING));
|
new BMessage(GV_USE_DITHERING));
|
||||||
AddChild(usedithering);
|
AddChild(fUseDitheringCB);
|
||||||
|
|
||||||
r.top = usedithering->Frame().bottom + 2;
|
r.top = fUseDitheringCB->Frame().bottom + 2;
|
||||||
r.bottom = r.top + 10;
|
r.bottom = r.top + 10;
|
||||||
r.right = r.left + be_plain_font->StringWidth("Write interlaced images") + 20;
|
fInterlacedCB = new BCheckBox(r, "Interlaced", "Write interlaced images",
|
||||||
interlaced = new BCheckBox(r, "Interlaced", "Write interlaced images",
|
|
||||||
new BMessage(GV_INTERLACED));
|
new BMessage(GV_INTERLACED));
|
||||||
AddChild(interlaced);
|
AddChild(fInterlacedCB);
|
||||||
|
|
||||||
r.top = interlaced->Frame().bottom + 2;
|
r.top = fInterlacedCB->Frame().bottom + 2;
|
||||||
r.bottom = r.top + 10;
|
r.bottom = r.top + 10;
|
||||||
r.right = r.left + be_plain_font->StringWidth("Write transparent images") + 20;
|
fUseTransparentCB = new BCheckBox(r, "UseTransparent", "Write transparent images",
|
||||||
usetransparent = new BCheckBox(r, "UseTransparent", "Write transparent images",
|
|
||||||
new BMessage(GV_USE_TRANSPARENT));
|
new BMessage(GV_USE_TRANSPARENT));
|
||||||
AddChild(usetransparent);
|
AddChild(fUseTransparentCB);
|
||||||
|
|
||||||
r.top = usetransparent->Frame().bottom + 2;
|
// radio buttons
|
||||||
|
r.top = fUseTransparentCB->Frame().bottom + 2;
|
||||||
r.bottom = r.top + 10;
|
r.bottom = r.top + 10;
|
||||||
r.right = r.left + be_plain_font->StringWidth("Use index:") + 20;
|
r.right = r.left + be_plain_font->StringWidth("Use index") + 20;
|
||||||
usetransparentindex = new BRadioButton(r, "UseTransparentIndex", "Use index:",
|
fUseTransparentIndexRB = new BRadioButton(r, "UseTransparentIndex", "Use index",
|
||||||
new BMessage(GV_USE_TRANSPARENT_INDEX));
|
new BMessage(GV_USE_TRANSPARENT_INDEX));
|
||||||
AddChild(usetransparentindex);
|
AddChild(fUseTransparentIndexRB);
|
||||||
|
|
||||||
r.left = r.right + 1;
|
r.left = r.right + 1;
|
||||||
r.right = r.left + 30;
|
r.right = r.left + 30;
|
||||||
transparentindex = new BTextControl(r, "TransparentIndex", "", "0",
|
fTransparentIndexTC = new BTextControl(r, "TransparentIndex", "", "0",
|
||||||
new BMessage(GV_TRANSPARENT_INDEX));
|
new BMessage(GV_TRANSPARENT_INDEX));
|
||||||
AddChild(transparentindex);
|
AddChild(fTransparentIndexTC);
|
||||||
transparentindex->SetDivider(0);
|
fTransparentIndexTC->SetDivider(0);
|
||||||
|
|
||||||
r.top = usetransparentindex->Frame().bottom + 0;
|
r.top = fUseTransparentIndexRB->Frame().bottom + 0;
|
||||||
r.bottom = r.top + 10;
|
r.bottom = r.top + 10;
|
||||||
r.left = 10;
|
r.left = 10;
|
||||||
r.right = r.left + be_plain_font->StringWidth("Use rgb color:") + 20;
|
r.right = r.left + be_plain_font->StringWidth("Use rgb color") + 20;
|
||||||
usetransparentcolor = new BRadioButton(r, "UseTransparentColor", "Use rgb color:",
|
fUseTransparentColorRB = new BRadioButton(r, "UseTransparentColor", "Use rgb color",
|
||||||
new BMessage(GV_USE_TRANSPARENT_COLOR));
|
new BMessage(GV_USE_TRANSPARENT_COLOR));
|
||||||
AddChild(usetransparentcolor);
|
AddChild(fUseTransparentColorRB);
|
||||||
|
|
||||||
r.left = r.right + 1;
|
r.left = r.right + 1;
|
||||||
r.right = r.left + 30;
|
r.right = r.left + 30;
|
||||||
transparentred = new BTextControl(r, "TransparentRed", "", "0",
|
fTransparentRedTC = new BTextControl(r, "TransparentRed", "", "0",
|
||||||
new BMessage(GV_TRANSPARENT_RED));
|
new BMessage(GV_TRANSPARENT_RED));
|
||||||
AddChild(transparentred);
|
AddChild(fTransparentRedTC);
|
||||||
transparentred->SetDivider(0);
|
fTransparentRedTC->SetDivider(0);
|
||||||
|
|
||||||
r.left = r.right + 5;
|
r.left = r.right + 5;
|
||||||
r.right = r.left + 30;
|
r.right = r.left + 30;
|
||||||
transparentgreen = new BTextControl(r, "TransparentGreen", "", "0",
|
fTransparentGreenTC = new BTextControl(r, "TransparentGreen", "", "0",
|
||||||
new BMessage(GV_TRANSPARENT_GREEN));
|
new BMessage(GV_TRANSPARENT_GREEN));
|
||||||
AddChild(transparentgreen);
|
AddChild(fTransparentGreenTC);
|
||||||
transparentgreen->SetDivider(0);
|
fTransparentGreenTC->SetDivider(0);
|
||||||
|
|
||||||
r.left = r.right + 5;
|
r.left = r.right + 5;
|
||||||
r.right = r.left + 30;
|
r.right = r.left + 30;
|
||||||
transparentblue = new BTextControl(r, "TransparentBlue", "", "0",
|
fTransparentBlueTC = new BTextControl(r, "TransparentBlue", "", "0",
|
||||||
new BMessage(GV_TRANSPARENT_BLUE));
|
new BMessage(GV_TRANSPARENT_BLUE));
|
||||||
AddChild(transparentblue);
|
AddChild(fTransparentBlueTC);
|
||||||
transparentblue->SetDivider(0);
|
fTransparentBlueTC->SetDivider(0);
|
||||||
|
|
||||||
BTextView *ti = transparentindex->TextView();
|
// align text controls
|
||||||
BTextView *tr = transparentred->TextView();
|
float diff = fTransparentRedTC->Frame().left - fTransparentIndexTC->Frame().left;
|
||||||
BTextView *tg = transparentgreen->TextView();
|
if (diff > 0) {
|
||||||
BTextView *tb = transparentblue->TextView();
|
fTransparentIndexTC->MoveBy(diff, 0);
|
||||||
|
} else {
|
||||||
|
fTransparentRedTC->MoveBy(-diff, 0);
|
||||||
|
fTransparentGreenTC->MoveBy(-diff, 0);
|
||||||
|
fTransparentBlueTC->MoveBy(-diff, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BTextView *ti = fTransparentIndexTC->TextView();
|
||||||
|
BTextView *tr = fTransparentRedTC->TextView();
|
||||||
|
BTextView *tg = fTransparentGreenTC->TextView();
|
||||||
|
BTextView *tb = fTransparentBlueTC->TextView();
|
||||||
|
|
||||||
for (uint32 x = 0; x < 256; x++) {
|
for (uint32 x = 0; x < 256; x++) {
|
||||||
if (x < '0' || x > '9') {
|
if (x < '0' || x > '9') {
|
||||||
@@ -157,156 +199,201 @@ GIFView::GIFView(BRect rect, const char *name) :
|
|||||||
RestorePrefs();
|
RestorePrefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIFView::RestorePrefs() {
|
// destructor
|
||||||
prefs = new Prefs();
|
GIFView::~GIFView()
|
||||||
|
{
|
||||||
switch (prefs->palettemode) {
|
delete fPrefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RestorePrefs
|
||||||
|
void
|
||||||
|
GIFView::RestorePrefs()
|
||||||
|
{
|
||||||
|
fPrefs = new Prefs();
|
||||||
|
|
||||||
|
fColorCountMF->SetEnabled(false);
|
||||||
|
fUseDitheringCB->SetEnabled(true);
|
||||||
|
|
||||||
|
switch (fPrefs->palettemode) {
|
||||||
case WEB_SAFE_PALETTE:
|
case WEB_SAFE_PALETTE:
|
||||||
websafe->SetMarked(true);
|
fWebSafeMI->SetMarked(true);
|
||||||
break;
|
break;
|
||||||
case BEOS_SYSTEM_PALETTE:
|
case BEOS_SYSTEM_PALETTE:
|
||||||
beossystem->SetMarked(true);
|
fBeOSSystemMI->SetMarked(true);
|
||||||
break;
|
break;
|
||||||
case GREYSCALE_PALETTE:
|
case GREYSCALE_PALETTE:
|
||||||
greyscale->SetMarked(true);
|
fGreyScaleMI->SetMarked(true);
|
||||||
usedithering->SetEnabled(false);
|
fUseDitheringCB->SetEnabled(false);
|
||||||
break;
|
break;
|
||||||
case OPTIMAL_PALETTE:
|
case OPTIMAL_PALETTE:
|
||||||
optimal->SetMarked(true);
|
fOptimalMI->SetMarked(true);
|
||||||
|
fColorCountMF->SetEnabled(true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
prefs->palettemode = WEB_SAFE_PALETTE;
|
fPrefs->palettemode = WEB_SAFE_PALETTE;
|
||||||
websafe->SetMarked(true);
|
fWebSafeMI->SetMarked(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
interlaced->SetValue(prefs->interlaced);
|
if (fColorCountMF->IsEnabled() &&
|
||||||
|
fPrefs->palette_size_in_bits > 0 &&
|
||||||
if (greyscale->IsMarked()) usedithering->SetValue(false);
|
fPrefs->palette_size_in_bits <= 8) {
|
||||||
else usedithering->SetValue(prefs->usedithering);
|
// display the stored color count
|
||||||
usetransparent->SetValue(prefs->usetransparent);
|
fColorCountMI[fPrefs->palette_size_in_bits - 1]->SetMarked(true);
|
||||||
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 {
|
} else {
|
||||||
usetransparentindex->SetEnabled(false);
|
// display 256 colors
|
||||||
usetransparentcolor->SetEnabled(false);
|
fColorCount256MI->SetMarked(true);
|
||||||
transparentindex->SetEnabled(false);
|
fPrefs->palette_size_in_bits = 8;
|
||||||
transparentred->SetEnabled(false);
|
}
|
||||||
transparentgreen->SetEnabled(false);
|
|
||||||
transparentblue->SetEnabled(false);
|
fInterlacedCB->SetValue(fPrefs->interlaced);
|
||||||
|
|
||||||
|
if (fGreyScaleMI->IsMarked()) fUseDitheringCB->SetValue(false);
|
||||||
|
else fUseDitheringCB->SetValue(fPrefs->usedithering);
|
||||||
|
fUseTransparentCB->SetValue(fPrefs->usetransparent);
|
||||||
|
fUseTransparentIndexRB->SetValue(fPrefs->usetransparentindex);
|
||||||
|
fUseTransparentColorRB->SetValue(!fPrefs->usetransparentindex);
|
||||||
|
if (fPrefs->usetransparent) {
|
||||||
|
fUseTransparentIndexRB->SetEnabled(true);
|
||||||
|
fUseTransparentColorRB->SetEnabled(true);
|
||||||
|
fTransparentIndexTC->SetEnabled(fPrefs->usetransparentindex);
|
||||||
|
fTransparentRedTC->SetEnabled(!fPrefs->usetransparentindex);
|
||||||
|
fTransparentGreenTC->SetEnabled(!fPrefs->usetransparentindex);
|
||||||
|
fTransparentBlueTC->SetEnabled(!fPrefs->usetransparentindex);
|
||||||
|
} else {
|
||||||
|
fUseTransparentIndexRB->SetEnabled(false);
|
||||||
|
fUseTransparentColorRB->SetEnabled(false);
|
||||||
|
fTransparentIndexTC->SetEnabled(false);
|
||||||
|
fTransparentRedTC->SetEnabled(false);
|
||||||
|
fTransparentGreenTC->SetEnabled(false);
|
||||||
|
fTransparentBlueTC->SetEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
char temp[4];
|
char temp[4];
|
||||||
sprintf(temp, "%d", prefs->transparentindex);
|
sprintf(temp, "%d", fPrefs->transparentindex);
|
||||||
transparentindex->SetText(temp);
|
fTransparentIndexTC->SetText(temp);
|
||||||
sprintf(temp, "%d", prefs->transparentred);
|
sprintf(temp, "%d", fPrefs->transparentred);
|
||||||
transparentred->SetText(temp);
|
fTransparentRedTC->SetText(temp);
|
||||||
sprintf(temp, "%d", prefs->transparentgreen);
|
sprintf(temp, "%d", fPrefs->transparentgreen);
|
||||||
transparentgreen->SetText(temp);
|
fTransparentGreenTC->SetText(temp);
|
||||||
sprintf(temp, "%d", prefs->transparentblue);
|
sprintf(temp, "%d", fPrefs->transparentblue);
|
||||||
transparentblue->SetText(temp);
|
fTransparentBlueTC->SetText(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIFView::AllAttached() {
|
// AllAttached
|
||||||
|
void
|
||||||
|
GIFView::AllAttached()
|
||||||
|
{
|
||||||
BView::AllAttached();
|
BView::AllAttached();
|
||||||
BMessenger msgr(this);
|
BMessenger msgr(this);
|
||||||
interlaced->SetTarget(msgr);
|
fInterlacedCB->SetTarget(msgr);
|
||||||
usedithering->SetTarget(msgr);
|
fUseDitheringCB->SetTarget(msgr);
|
||||||
usetransparent->SetTarget(msgr);
|
fUseTransparentCB->SetTarget(msgr);
|
||||||
usetransparentindex->SetTarget(msgr);
|
fUseTransparentIndexRB->SetTarget(msgr);
|
||||||
transparentindex->SetTarget(msgr);
|
fTransparentIndexTC->SetTarget(msgr);
|
||||||
usetransparentcolor->SetTarget(msgr);
|
fUseTransparentColorRB->SetTarget(msgr);
|
||||||
transparentred->SetTarget(msgr);
|
fTransparentRedTC->SetTarget(msgr);
|
||||||
transparentgreen->SetTarget(msgr);
|
fTransparentGreenTC->SetTarget(msgr);
|
||||||
transparentblue->SetTarget(msgr);
|
fTransparentBlueTC->SetTarget(msgr);
|
||||||
websafe->SetTarget(msgr);
|
fPaletteM->SetTargetForItems(msgr);
|
||||||
beossystem->SetTarget(msgr);
|
fColorCountM->SetTargetForItems(msgr);
|
||||||
greyscale->SetTarget(msgr);
|
|
||||||
optimal->SetTarget(msgr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIFView::MessageReceived(BMessage *message) {
|
// MessageReceived
|
||||||
|
void
|
||||||
|
GIFView::MessageReceived(BMessage *message)
|
||||||
|
{
|
||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
case GV_WEB_SAFE:
|
case GV_WEB_SAFE:
|
||||||
prefs->palettemode = WEB_SAFE_PALETTE;
|
fPrefs->palettemode = WEB_SAFE_PALETTE;
|
||||||
usedithering->SetEnabled(true);
|
fUseDitheringCB->SetEnabled(true);
|
||||||
|
fColorCountMF->SetEnabled(false);
|
||||||
|
fColorCount256MI->SetMarked(true);
|
||||||
break;
|
break;
|
||||||
case GV_BEOS_SYSTEM:
|
case GV_BEOS_SYSTEM:
|
||||||
prefs->palettemode = BEOS_SYSTEM_PALETTE;
|
fPrefs->palettemode = BEOS_SYSTEM_PALETTE;
|
||||||
usedithering->SetEnabled(true);
|
fUseDitheringCB->SetEnabled(true);
|
||||||
|
fColorCountMF->SetEnabled(false);
|
||||||
|
fColorCount256MI->SetMarked(true);
|
||||||
break;
|
break;
|
||||||
case GV_GREYSCALE:
|
case GV_GREYSCALE:
|
||||||
prefs->palettemode = GREYSCALE_PALETTE;
|
fPrefs->palettemode = GREYSCALE_PALETTE;
|
||||||
usedithering->SetEnabled(false);
|
fUseDitheringCB->SetEnabled(false);
|
||||||
usedithering->SetValue(false);
|
fUseDitheringCB->SetValue(false);
|
||||||
prefs->usedithering = false;
|
fColorCountMF->SetEnabled(false);
|
||||||
|
fColorCount256MI->SetMarked(true);
|
||||||
|
fPrefs->usedithering = false;
|
||||||
break;
|
break;
|
||||||
case GV_OPTIMAL:
|
case GV_OPTIMAL:
|
||||||
prefs->palettemode = OPTIMAL_PALETTE;
|
fPrefs->palettemode = OPTIMAL_PALETTE;
|
||||||
usedithering->SetEnabled(true);
|
fUseDitheringCB->SetEnabled(true);
|
||||||
|
fColorCountMF->SetEnabled(true);
|
||||||
|
fColorCountMI[fPrefs->palette_size_in_bits - 1]->SetMarked(true);
|
||||||
|
break;
|
||||||
|
case GV_SET_COLOR_COUNT:
|
||||||
|
if (fColorCountMF->IsEnabled()) {
|
||||||
|
int32 sizeInBits;
|
||||||
|
if (message->FindInt32("size in bits", &sizeInBits) >= B_OK) {
|
||||||
|
if (sizeInBits > 0 && sizeInBits <= 8)
|
||||||
|
fPrefs->palette_size_in_bits = sizeInBits;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GV_INTERLACED:
|
case GV_INTERLACED:
|
||||||
prefs->interlaced = interlaced->Value();
|
fPrefs->interlaced = fInterlacedCB->Value();
|
||||||
break;
|
break;
|
||||||
case GV_USE_DITHERING:
|
case GV_USE_DITHERING:
|
||||||
prefs->usedithering = usedithering->Value();
|
fPrefs->usedithering = fUseDitheringCB->Value();
|
||||||
break;
|
break;
|
||||||
case GV_USE_TRANSPARENT:
|
case GV_USE_TRANSPARENT:
|
||||||
prefs->usetransparent = usetransparent->Value();
|
fPrefs->usetransparent = fUseTransparentCB->Value();
|
||||||
if (prefs->usetransparent) {
|
if (fPrefs->usetransparent) {
|
||||||
usetransparentindex->SetEnabled(true);
|
fUseTransparentIndexRB->SetEnabled(true);
|
||||||
usetransparentcolor->SetEnabled(true);
|
fUseTransparentColorRB->SetEnabled(true);
|
||||||
transparentindex->SetEnabled(usetransparentindex->Value());
|
fTransparentIndexTC->SetEnabled(fUseTransparentIndexRB->Value());
|
||||||
transparentred->SetEnabled(usetransparentcolor->Value());
|
fTransparentRedTC->SetEnabled(fUseTransparentColorRB->Value());
|
||||||
transparentgreen->SetEnabled(usetransparentcolor->Value());
|
fTransparentGreenTC->SetEnabled(fUseTransparentColorRB->Value());
|
||||||
transparentblue->SetEnabled(usetransparentcolor->Value());
|
fTransparentBlueTC->SetEnabled(fUseTransparentColorRB->Value());
|
||||||
} else {
|
} else {
|
||||||
usetransparentindex->SetEnabled(false);
|
fUseTransparentIndexRB->SetEnabled(false);
|
||||||
usetransparentcolor->SetEnabled(false);
|
fUseTransparentColorRB->SetEnabled(false);
|
||||||
transparentindex->SetEnabled(false);
|
fTransparentIndexTC->SetEnabled(false);
|
||||||
transparentred->SetEnabled(false);
|
fTransparentRedTC->SetEnabled(false);
|
||||||
transparentgreen->SetEnabled(false);
|
fTransparentGreenTC->SetEnabled(false);
|
||||||
transparentblue->SetEnabled(false);
|
fTransparentBlueTC->SetEnabled(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GV_USE_TRANSPARENT_INDEX:
|
case GV_USE_TRANSPARENT_INDEX:
|
||||||
prefs->usetransparentindex = true;
|
fPrefs->usetransparentindex = true;
|
||||||
transparentindex->SetEnabled(true);
|
fTransparentIndexTC->SetEnabled(true);
|
||||||
transparentred->SetEnabled(false);
|
fTransparentRedTC->SetEnabled(false);
|
||||||
transparentgreen->SetEnabled(false);
|
fTransparentGreenTC->SetEnabled(false);
|
||||||
transparentblue->SetEnabled(false);
|
fTransparentBlueTC->SetEnabled(false);
|
||||||
break;
|
break;
|
||||||
case GV_TRANSPARENT_INDEX:
|
case GV_TRANSPARENT_INDEX:
|
||||||
prefs->transparentindex = CheckInput(transparentindex);
|
fPrefs->transparentindex = CheckInput(fTransparentIndexTC);
|
||||||
break;
|
break;
|
||||||
case GV_USE_TRANSPARENT_COLOR:
|
case GV_USE_TRANSPARENT_COLOR:
|
||||||
prefs->usetransparentindex = false;
|
fPrefs->usetransparentindex = false;
|
||||||
transparentindex->SetEnabled(false);
|
fTransparentIndexTC->SetEnabled(false);
|
||||||
transparentred->SetEnabled(true);
|
fTransparentRedTC->SetEnabled(true);
|
||||||
transparentgreen->SetEnabled(true);
|
fTransparentGreenTC->SetEnabled(true);
|
||||||
transparentblue->SetEnabled(true);
|
fTransparentBlueTC->SetEnabled(true);
|
||||||
break;
|
break;
|
||||||
case GV_TRANSPARENT_RED:
|
case GV_TRANSPARENT_RED:
|
||||||
prefs->transparentred = CheckInput(transparentred);
|
fPrefs->transparentred = CheckInput(fTransparentRedTC);
|
||||||
break;
|
break;
|
||||||
case GV_TRANSPARENT_GREEN:
|
case GV_TRANSPARENT_GREEN:
|
||||||
prefs->transparentgreen = CheckInput(transparentgreen);
|
fPrefs->transparentgreen = CheckInput(fTransparentGreenTC);
|
||||||
break;
|
break;
|
||||||
case GV_TRANSPARENT_BLUE:
|
case GV_TRANSPARENT_BLUE:
|
||||||
prefs->transparentblue = CheckInput(transparentblue);
|
fPrefs->transparentblue = CheckInput(fTransparentBlueTC);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BView::MessageReceived(message);
|
BView::MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
prefs->Save();
|
fPrefs->Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
int GIFView::CheckInput(BTextControl *control) {
|
int GIFView::CheckInput(BTextControl *control) {
|
||||||
@@ -320,7 +407,3 @@ int GIFView::CheckInput(BTextControl *control) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
GIFView::~GIFView() {
|
|
||||||
delete prefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,13 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||||
|
|
||||||
#ifndef GIFVIEW_H
|
#ifndef GIFVIEW_H
|
||||||
#define GIFVIEW_H
|
#define GIFVIEW_H
|
||||||
|
|
||||||
#include <View.h>
|
#include <View.h>
|
||||||
|
|
||||||
class BMenuField;
|
class BMenuField;
|
||||||
class BPopUpMenu;
|
class BPopUpMenu;
|
||||||
class BMenuItem;
|
class BMenuItem;
|
||||||
@@ -38,26 +41,45 @@ class Prefs;
|
|||||||
#define GV_TRANSPARENT_RED 'gvtr'
|
#define GV_TRANSPARENT_RED 'gvtr'
|
||||||
#define GV_TRANSPARENT_GREEN 'gvtg'
|
#define GV_TRANSPARENT_GREEN 'gvtg'
|
||||||
#define GV_TRANSPARENT_BLUE 'gvtb'
|
#define GV_TRANSPARENT_BLUE 'gvtb'
|
||||||
|
#define GV_SET_COLOR_COUNT 'gvcc'
|
||||||
|
|
||||||
class GIFView : public BView {
|
class GIFView : public BView {
|
||||||
public:
|
public:
|
||||||
GIFView(BRect rect, const char *name);
|
GIFView(BRect rect, const char* name);
|
||||||
~GIFView();
|
virtual ~GIFView();
|
||||||
void MessageReceived(BMessage *message);
|
|
||||||
void AllAttached();
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
virtual void AllAttached();
|
||||||
|
|
||||||
Prefs *prefs;
|
private:
|
||||||
BMenuField *palettemenufield;
|
void RestorePrefs();
|
||||||
BPopUpMenu *palettepopupmenu;
|
int CheckInput(BTextControl* control);
|
||||||
BMenuItem *websafe, *beossystem, *greyscale, *optimal;
|
|
||||||
BCheckBox *interlaced, *usetransparent, *usedithering;
|
Prefs* fPrefs;
|
||||||
BRadioButton *usetransparentindex, *usetransparentcolor;
|
|
||||||
BTextControl *transparentindex, *transparentred,
|
BMenuField* fPaletteMF;
|
||||||
*transparentgreen, *transparentblue;
|
BPopUpMenu* fPaletteM;
|
||||||
|
BMenuItem* fWebSafeMI;
|
||||||
private:
|
BMenuItem* fBeOSSystemMI;
|
||||||
void RestorePrefs();
|
BMenuItem* fGreyScaleMI;
|
||||||
int CheckInput(BTextControl *control);
|
BMenuItem* fOptimalMI;
|
||||||
|
|
||||||
|
BMenuField* fColorCountMF;
|
||||||
|
BPopUpMenu* fColorCountM;
|
||||||
|
BMenuItem* fColorCountMI[8];
|
||||||
|
BMenuItem* fColorCount256MI;
|
||||||
|
|
||||||
|
BCheckBox* fInterlacedCB;
|
||||||
|
BCheckBox* fUseTransparentCB;
|
||||||
|
BCheckBox* fUseDitheringCB;
|
||||||
|
|
||||||
|
BRadioButton* fUseTransparentIndexRB;
|
||||||
|
BRadioButton* fUseTransparentColorRB;
|
||||||
|
|
||||||
|
BTextControl* fTransparentIndexTC;
|
||||||
|
BTextControl* fTransparentRedTC;
|
||||||
|
BTextControl* fTransparentGreenTC;
|
||||||
|
BTextControl* fTransparentBlueTC;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||||
|
|
||||||
#include "Prefs.h"
|
#include "Prefs.h"
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
@@ -26,7 +28,8 @@ Prefs::Prefs() {
|
|||||||
usedithering = true;
|
usedithering = true;
|
||||||
transparentindex = transparentred = transparentgreen =
|
transparentindex = transparentred = transparentgreen =
|
||||||
transparentblue = palettemode = 0;
|
transparentblue = palettemode = 0;
|
||||||
|
palette_size_in_bits = 8;
|
||||||
|
|
||||||
BPath path;
|
BPath path;
|
||||||
find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||||
path.Append("GIFTranslator_settings");
|
path.Append("GIFTranslator_settings");
|
||||||
@@ -47,6 +50,8 @@ Prefs::Prefs() {
|
|||||||
if (!GetBool("usedithering", &usedithering, &db)) return;
|
if (!GetBool("usedithering", &usedithering, &db)) return;
|
||||||
int di = 0;
|
int di = 0;
|
||||||
if (!GetInt("palettemode", &palettemode, &di)) return;
|
if (!GetInt("palettemode", &palettemode, &di)) return;
|
||||||
|
di = 8;
|
||||||
|
if (!GetInt("palettesize", &palette_size_in_bits, &di)) return;
|
||||||
di = 0;
|
di = 0;
|
||||||
if (!GetInt("transparentindex", &transparentindex, &di)) return;
|
if (!GetInt("transparentindex", &transparentindex, &di)) return;
|
||||||
di = 0;
|
di = 0;
|
||||||
@@ -111,6 +116,7 @@ void Prefs::Save() {
|
|||||||
if (!PutBool("usetransparentindex", &usetransparentindex)) return;
|
if (!PutBool("usetransparentindex", &usetransparentindex)) return;
|
||||||
if (!PutBool("usedithering", &usedithering)) return;
|
if (!PutBool("usedithering", &usedithering)) return;
|
||||||
if (!PutInt("palettemode", &palettemode)) return;
|
if (!PutInt("palettemode", &palettemode)) return;
|
||||||
|
if (!PutInt("palettesize", &palette_size_in_bits)) return;
|
||||||
if (!PutInt("transparentindex", &transparentindex)) return;
|
if (!PutInt("transparentindex", &transparentindex)) return;
|
||||||
if (!PutInt("transparentred", &transparentred)) return;
|
if (!PutInt("transparentred", &transparentred)) return;
|
||||||
if (!PutInt("transparentgreen", &transparentgreen)) return;
|
if (!PutInt("transparentgreen", &transparentgreen)) return;
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||||
|
|
||||||
#ifndef PREFS_H
|
#ifndef PREFS_H
|
||||||
#define PREFS_H
|
#define PREFS_H
|
||||||
|
|
||||||
@@ -26,7 +28,7 @@ class Prefs {
|
|||||||
bool interlaced, usetransparent, usetransparentindex,
|
bool interlaced, usetransparent, usetransparentindex,
|
||||||
usedithering;
|
usedithering;
|
||||||
int transparentindex, transparentred, transparentgreen,
|
int transparentindex, transparentred, transparentgreen,
|
||||||
transparentblue, palettemode;
|
transparentblue, palettemode, palette_size_in_bits;
|
||||||
private:
|
private:
|
||||||
bool GetInt(char *name, int *value, int *defaultvalue);
|
bool GetInt(char *name, int *value, int *defaultvalue);
|
||||||
bool GetBool(char *name, bool *value, bool *defaultvalue);
|
bool GetBool(char *name, bool *value, bool *defaultvalue);
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||||
|
|
||||||
#include "SFHash.h"
|
#include "SFHash.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -46,7 +48,9 @@ void SFHash::AddItem(HashItem *item) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HashItem *SFHash::GetItem(unsigned int key) {
|
HashItem*
|
||||||
|
SFHash::GetItem(unsigned int key)
|
||||||
|
{
|
||||||
int pos = key % size;
|
int pos = key % size;
|
||||||
HashItem *item = main_array[pos];
|
HashItem *item = main_array[pos];
|
||||||
|
|
||||||
@@ -57,7 +61,9 @@ HashItem *SFHash::GetItem(unsigned int key) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int SFHash::CountItems() {
|
unsigned int
|
||||||
|
SFHash::CountItems()
|
||||||
|
{
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
for (int x = 0; x < this->size; x++) {
|
for (int x = 0; x < this->size; x++) {
|
||||||
HashItem *item = main_array[x];
|
HashItem *item = main_array[x];
|
||||||
@@ -69,7 +75,9 @@ unsigned int SFHash::CountItems() {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
HashItem *SFHash::NextItem() {
|
HashItem*
|
||||||
|
SFHash::NextItem()
|
||||||
|
{
|
||||||
if (iterate_pos >= size) {
|
if (iterate_pos >= size) {
|
||||||
Rewind();
|
Rewind();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||||
|
|
||||||
#ifndef SFHASH_H
|
#ifndef SFHASH_H
|
||||||
#define SFHASH_H
|
#define SFHASH_H
|
||||||
|
|
||||||
@@ -26,16 +28,17 @@ class HashItem {
|
|||||||
|
|
||||||
class SFHash {
|
class SFHash {
|
||||||
public:
|
public:
|
||||||
SFHash(int size = 4096);
|
SFHash(int size = 4096);
|
||||||
~SFHash();
|
~SFHash();
|
||||||
|
|
||||||
void AddItem(HashItem *item);
|
void AddItem(HashItem *item);
|
||||||
HashItem *GetItem(unsigned int key);
|
HashItem* GetItem(unsigned int key);
|
||||||
unsigned int CountItems();
|
unsigned int CountItems();
|
||||||
HashItem *NextItem();
|
HashItem* NextItem();
|
||||||
void Rewind();
|
void Rewind();
|
||||||
|
|
||||||
bool fatalerror;
|
bool fatalerror;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int size, iterate_pos, iterate_depth;
|
int size, iterate_pos, iterate_depth;
|
||||||
HashItem **main_array;
|
HashItem **main_array;
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Additional authors: Stephan Aßmus, <[email protected]>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
#include "SavePalette.h"
|
#include "SavePalette.h"
|
||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -21,6 +25,7 @@
|
|||||||
|
|
||||||
extern bool debug;
|
extern bool debug;
|
||||||
|
|
||||||
|
// "web safe palette"
|
||||||
const rgb_color wsp[256] = {
|
const rgb_color wsp[256] = {
|
||||||
{0xff, 0xff, 0xff, 0xff}, {0xff, 0xff, 0xcc, 0xff},
|
{0xff, 0xff, 0xff, 0xff}, {0xff, 0xff, 0xcc, 0xff},
|
||||||
{0xff, 0xff, 0x99, 0xff}, {0xff, 0xff, 0x66, 0xff},
|
{0xff, 0xff, 0x99, 0xff}, {0xff, 0xff, 0x66, 0xff},
|
||||||
@@ -152,64 +157,109 @@ const rgb_color wsp[256] = {
|
|||||||
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff}
|
{0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff}
|
||||||
};
|
};
|
||||||
|
|
||||||
ColorItem::ColorItem(unsigned int k, unsigned int c) {
|
class ColorItem : public HashItem {
|
||||||
key = k;
|
public:
|
||||||
count = c;
|
ColorItem(unsigned int k, unsigned int c,
|
||||||
}
|
uint8 r, uint8 g, uint8 b)
|
||||||
|
: count(c),
|
||||||
SavePalette::SavePalette() {
|
red(r),
|
||||||
pal = new rgb_color[256];
|
green(g),
|
||||||
backgroundindex = 0;
|
blue(b)
|
||||||
usetransparent = false;
|
{
|
||||||
transparentindex = 0;
|
key = k;
|
||||||
size = size_in_bits = 0;
|
}
|
||||||
fatalerror = false;
|
unsigned int count;
|
||||||
mode = WEB_SAFE_PALETTE;
|
uint8 red;
|
||||||
}
|
uint8 green;
|
||||||
|
uint8 blue;
|
||||||
SavePalette::SavePalette(int predefined) {
|
};
|
||||||
pal = new rgb_color[256];
|
|
||||||
backgroundindex = 0;
|
// constructor
|
||||||
usetransparent = false;
|
SavePalette::SavePalette(int mode)
|
||||||
transparentindex = 0;
|
: pal(new(nothrow) rgb_color[256]),
|
||||||
fatalerror = false;
|
fSize(0),
|
||||||
|
fSizeInBits(8),
|
||||||
mode = predefined;
|
fMode(mode),
|
||||||
size_in_bits = 8;
|
fUseTransparent(false),
|
||||||
|
fTransparentIndex(0),
|
||||||
if (predefined == WEB_SAFE_PALETTE) {
|
fBackgroundIndex(0),
|
||||||
memcpy(pal, wsp, sizeof(rgb_color) * 256);
|
fFatalError(pal == NULL)
|
||||||
size = 216;
|
{
|
||||||
} else if (predefined == BEOS_SYSTEM_PALETTE) {
|
if (IsValid()) {
|
||||||
color_map *map = (color_map *)system_colors();
|
if (fMode == WEB_SAFE_PALETTE) {
|
||||||
memcpy(pal, map->color_list, sizeof(rgb_color) * 256);
|
memcpy(pal, wsp, sizeof(rgb_color) * 256);
|
||||||
size = 256;
|
fSize = 216;
|
||||||
} else if (predefined == GREYSCALE_PALETTE) {
|
} else if (fMode == BEOS_SYSTEM_PALETTE) {
|
||||||
for (int x = 0; x < 256; x++) {
|
color_map *map = (color_map *)system_colors();
|
||||||
pal[x].red = pal[x].green = pal[x].blue = x;
|
memcpy(pal, map->color_list, sizeof(rgb_color) * 256);
|
||||||
pal[x].alpha = 0xff;
|
fSize = 256;
|
||||||
|
} else if (fMode == GREYSCALE_PALETTE) {
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
pal[i].red = pal[i].green = pal[i].blue = i;
|
||||||
|
pal[i].alpha = 0xff;
|
||||||
|
}
|
||||||
|
fSize = 256;
|
||||||
}
|
}
|
||||||
size = 256;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SavePalette::SavePalette(BBitmap *bitmap) {
|
// make_key
|
||||||
pal = new rgb_color[256];
|
static int
|
||||||
backgroundindex = 0;
|
make_key(uint8 r, uint8 g, uint8 b, uint8 bits)
|
||||||
usetransparent = false;
|
{
|
||||||
transparentindex = 0;
|
r = r >> (8 - bits);
|
||||||
fatalerror = false;
|
g = g >> (8 - bits);
|
||||||
mode = OPTIMAL_PALETTE;
|
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)
|
||||||
|
{
|
||||||
|
ColorItem* ci = (ColorItem*)hash.GetItem(key);
|
||||||
|
if (ci == NULL) {
|
||||||
|
ci = new(nothrow) ColorItem(key, 1, r, g, b);
|
||||||
|
if (ci == NULL) {
|
||||||
|
if (debug)
|
||||||
|
printf("Out of memory in touch_color_item()\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
hash.AddItem((HashItem *)ci);
|
||||||
|
} else {
|
||||||
|
ci->count++;
|
||||||
|
// use brightest color
|
||||||
|
ci->red = max_c(ci->red, r);
|
||||||
|
ci->green = max_c(ci->green, g);
|
||||||
|
ci->blue = max_c(ci->blue, b);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
SavePalette::SavePalette(BBitmap *bitmap, int32 maxSizeInBits)
|
||||||
|
: pal(new(nothrow) rgb_color[256]),
|
||||||
|
fSize(0),
|
||||||
|
fSizeInBits(0),
|
||||||
|
fMode(OPTIMAL_PALETTE),
|
||||||
|
fUseTransparent(false),
|
||||||
|
fTransparentIndex(0),
|
||||||
|
fBackgroundIndex(0),
|
||||||
|
fFatalError(pal == NULL)
|
||||||
|
{
|
||||||
|
if (!IsValid())
|
||||||
|
return;
|
||||||
|
|
||||||
SFHash hash(1 << 16);
|
SFHash hash(1 << 16);
|
||||||
if (hash.fatalerror) {
|
if (hash.fatalerror) {
|
||||||
if (debug)
|
if (debug)
|
||||||
printf("Out of memory in SavePalette(BBitmap *)\n");
|
printf("Out of memory in SavePalette(BBitmap *)\n");
|
||||||
fatalerror = true;
|
fFatalError = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unsigned char r, g, b;
|
|
||||||
|
// reject unsupported color spaces
|
||||||
|
// TODO: B_CMAP8 and B_GRAY8 should be really easy to support as well!!
|
||||||
color_space cs = bitmap->ColorSpace();
|
color_space cs = bitmap->ColorSpace();
|
||||||
if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG && cs != B_RGBA32_BIG) {
|
if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG && cs != B_RGBA32_BIG) {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
@@ -217,111 +267,177 @@ SavePalette::SavePalette(BBitmap *bitmap) {
|
|||||||
printf("%d %d %d %d or 0x%x\n", (cs & 0xff000000) >> 24, (cs & 0xff0000) >> 16,
|
printf("%d %d %d %d or 0x%x\n", (cs & 0xff000000) >> 24, (cs & 0xff0000) >> 16,
|
||||||
(cs & 0xff00) >> 8, cs & 0xff, cs);
|
(cs & 0xff00) >> 8, cs & 0xff, cs);
|
||||||
}
|
}
|
||||||
fatalerror = true;
|
fFatalError = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BRect rect = bitmap->Bounds();
|
BRect rect = bitmap->Bounds();
|
||||||
int height = rect.IntegerHeight() + 1;
|
uint32 height = rect.IntegerHeight() + 1;
|
||||||
int width = rect.IntegerWidth() + 1;
|
uint32 width = rect.IntegerWidth() + 1;
|
||||||
unsigned char *bits = (unsigned char *)bitmap->Bits();
|
uint8* bits = (uint8*)bitmap->Bits();
|
||||||
|
uint32 bpr = bitmap->BytesPerRow();
|
||||||
|
|
||||||
for (int y = 0; y < height; y++) {
|
uint8 r, g, b;
|
||||||
for (int x = 0; x < width; x++) {
|
uint8 useBits = 3 + maxSizeInBits / 2;
|
||||||
if (cs == B_RGB32 || cs == B_RGBA32) {
|
if (cs == B_RGB32 || cs == B_RGBA32) {
|
||||||
b = bits[0];
|
for (uint32 y = 0; y < height; y++) {
|
||||||
g = bits[1];
|
uint8* handle = bits;
|
||||||
r = bits[2];
|
for (uint32 x = 0; x < width; x++) {
|
||||||
} else {
|
b = handle[0];
|
||||||
r = bits[1];
|
g = handle[1];
|
||||||
g = bits[2];
|
r = handle[2];
|
||||||
b = bits[3];
|
handle += 4;
|
||||||
}
|
|
||||||
bits += 4;
|
uint32 key = make_key(r, g, b, useBits);
|
||||||
|
if (!touch_color_item(hash, key, r, g, b)) {
|
||||||
unsigned int key = (r << 16) + (g << 8) + b;
|
if (debug) printf("Out of memory in SavePalette(BBitmap *)\n");
|
||||||
ColorItem *ci = (ColorItem *)hash.GetItem(key);
|
fFatalError = true;
|
||||||
if (ci == NULL) {
|
|
||||||
ci = new ColorItem(key, 1);
|
|
||||||
if (ci == NULL) {
|
|
||||||
if (debug) printf("Out of memory in SavePalette(BBitmap *)\n");
|
|
||||||
fatalerror = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hash.AddItem((HashItem *)ci);
|
}
|
||||||
} else {
|
bits += bpr;
|
||||||
ci->count++;
|
}
|
||||||
}
|
} else if ((cs == B_RGB32_BIG || cs == B_RGBA32_BIG)) {
|
||||||
}
|
for (uint32 y = 0; y < height; y++) {
|
||||||
}
|
uint8* handle = bits;
|
||||||
|
for (uint32 x = 0; x < width; x++) {
|
||||||
|
b = handle[2];
|
||||||
|
g = handle[1];
|
||||||
|
r = handle[0];
|
||||||
|
handle += 4;
|
||||||
|
|
||||||
|
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");
|
||||||
|
fFatalError = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bits += bpr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int unique_colors = hash.CountItems();
|
int unique_colors = hash.CountItems();
|
||||||
size_in_bits = 1;
|
while (((1 << fSizeInBits) < unique_colors) && (fSizeInBits < maxSizeInBits))
|
||||||
while (((1 << size_in_bits) < unique_colors) && (size_in_bits < 8)) size_in_bits++;
|
fSizeInBits++;
|
||||||
size = 1 << size_in_bits;
|
fSize = 1 << fSizeInBits;
|
||||||
|
|
||||||
ColorItem **topcolors = (ColorItem **)malloc(size * 4);
|
ColorItem **topcolors = (ColorItem **)malloc(fSize * 4);
|
||||||
if (topcolors == NULL) {
|
if (topcolors == NULL) {
|
||||||
if (debug) printf("Out of memory in SavePalette(BBitmap *)\n");
|
if (debug) printf("Out of memory in SavePalette(BBitmap *)\n");
|
||||||
fatalerror = true;
|
fFatalError = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ColorItem *dummy = new ColorItem(0, 0);
|
ColorItem *dummy = new ColorItem(0, 0, 0, 0, 0);
|
||||||
for (int x = 0; x < size; x++) topcolors[x] = dummy;
|
for (int i = 0; i < fSize; i++)
|
||||||
|
topcolors[i] = dummy;
|
||||||
|
|
||||||
for (int x = 0; x < unique_colors; x++) {
|
for (int i = 0; i < unique_colors; i++) {
|
||||||
ColorItem *ci = (ColorItem *)hash.NextItem();
|
ColorItem *ci = (ColorItem *)hash.NextItem();
|
||||||
for (int y = 0; y < size; y++) {
|
for (int j = 0; j < fSize; j++) {
|
||||||
if (ci->count > topcolors[y]->count) {
|
if (ci->count > topcolors[j]->count) {
|
||||||
for (int z = size - 1; z > y; z--) {
|
for (int k = fSize - 1; k > j; k--) {
|
||||||
topcolors[z] = topcolors[z-1];
|
topcolors[k] = topcolors[k - 1];
|
||||||
}
|
}
|
||||||
topcolors[y] = ci;
|
topcolors[j] = ci;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int x = 0; x < size; x++) {
|
for (int i = 0; i < fSize; i++) {
|
||||||
pal[x].red = topcolors[x]->key >> 16;
|
pal[i].red = topcolors[i]->red;
|
||||||
pal[x].green = (topcolors[x]->key & 0xff00) >> 8;
|
pal[i].green = topcolors[i]->green;
|
||||||
pal[x].blue = topcolors[x]->key & 0xff;
|
pal[i].blue = topcolors[i]->blue;
|
||||||
pal[x].alpha = 0xff;
|
pal[i].alpha = 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete dummy;
|
delete dummy;
|
||||||
free(topcolors);
|
free(topcolors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Standard mapping services once a palette is loaded */
|
// destructor
|
||||||
unsigned char SavePalette::IndexForColor(unsigned char red, unsigned char green,
|
SavePalette::~SavePalette()
|
||||||
unsigned char blue) {
|
{
|
||||||
|
delete[] pal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexForColor
|
||||||
|
//
|
||||||
|
// standard mapping services once a palette is loaded
|
||||||
|
uint8
|
||||||
|
SavePalette::IndexForColor(uint8 red, uint8 green, uint8 blue)
|
||||||
|
{
|
||||||
|
uint8 index = 0;
|
||||||
|
|
||||||
|
if (fMode == GREYSCALE_PALETTE) {
|
||||||
|
index = (308 * red + 600 * green + 116 * blue) / 1024;
|
||||||
|
} else {
|
||||||
|
int closestDistance = 255 * 255 * 3;
|
||||||
|
|
||||||
if (mode == GREYSCALE_PALETTE) {
|
for (int i = 0; i < fSize && closestDistance != 0; i++) {
|
||||||
unsigned char result = (red + (green << 1) + blue) >> 2;
|
int rd = (int)red - (int)pal[i].red;
|
||||||
return result;
|
int gd = (int)green - (int)pal[i].green;
|
||||||
}
|
int bd = (int)blue - (int)pal[i].blue;
|
||||||
|
int distanceAtIndex = rd * rd + gd * gd + bd * bd;
|
||||||
unsigned char best = 0;
|
if (distanceAtIndex < closestDistance) {
|
||||||
int min = 255 * 3;
|
closestDistance = distanceAtIndex;
|
||||||
|
index = i;
|
||||||
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;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char SavePalette::IndexForColor(rgb_color color) {
|
// SetUseTransparent
|
||||||
return IndexForColor(color.red, color.green, color.blue);
|
void
|
||||||
|
SavePalette::SetUseTransparent(bool use)
|
||||||
|
{
|
||||||
|
fUseTransparent = use;
|
||||||
}
|
}
|
||||||
|
|
||||||
SavePalette::~SavePalette() {
|
// SetTransparentIndex
|
||||||
delete [] pal;
|
void
|
||||||
|
SavePalette::SetTransparentIndex(int index)
|
||||||
|
{
|
||||||
|
fTransparentIndex = max_c(fSize - 1, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTransparentColor
|
||||||
|
bool
|
||||||
|
SavePalette::SetTransparentColor(uint8 red, uint8 green, uint8 blue)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < fSize; i++) {
|
||||||
|
if (pal[i].red == red &&
|
||||||
|
pal[i].green == green &&
|
||||||
|
pal[i].blue == blue) {
|
||||||
|
|
||||||
|
fTransparentIndex = i;
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
fTransparentIndex = 0;
|
||||||
|
fUseTransparent = false;
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetColors
|
||||||
|
void
|
||||||
|
SavePalette::GetColors(uint8* buffer, int size) const
|
||||||
|
{
|
||||||
|
int maxIndex = max_c(size / 3, fSize) - 1;
|
||||||
|
for (int i = 0; i <= maxIndex; i++) {
|
||||||
|
*buffer++ = pal[i].red;
|
||||||
|
*buffer++ = pal[i].green;
|
||||||
|
*buffer++ = pal[i].blue;
|
||||||
|
}
|
||||||
|
int rest = (maxIndex + 1) * 3;
|
||||||
|
if (rest < size)
|
||||||
|
memset(buffer, 0, size - rest);
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,34 +27,58 @@ enum {
|
|||||||
OPTIMAL_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 {
|
class SavePalette {
|
||||||
public:
|
public:
|
||||||
SavePalette(int predefined);
|
SavePalette(int mode);
|
||||||
SavePalette(BBitmap *bitmap);
|
SavePalette(BBitmap *bitmap,
|
||||||
SavePalette();
|
int32 maxSizeInBits = 8);
|
||||||
~SavePalette();
|
virtual ~SavePalette();
|
||||||
|
|
||||||
unsigned char IndexForColor(unsigned char red, unsigned char green,
|
inline bool IsValid() const
|
||||||
unsigned char blue);
|
{ return !fFatalError; }
|
||||||
unsigned char IndexForColor(rgb_color color);
|
|
||||||
|
|
||||||
rgb_color *pal;
|
uint8 IndexForColor(uint8 red, uint8 green, uint8 blue);
|
||||||
int size, size_in_bits, mode;
|
inline uint8 IndexForColor(const rgb_color& color);
|
||||||
bool usetransparent;
|
|
||||||
int backgroundindex, transparentindex;
|
void SetUseTransparent(bool use);
|
||||||
bool fatalerror;
|
inline bool UseTransparent() const
|
||||||
|
{ return fUseTransparent; }
|
||||||
|
|
||||||
|
void SetTransparentIndex(int index);
|
||||||
|
inline int TransparentIndex() const
|
||||||
|
{ return fTransparentIndex; }
|
||||||
|
bool SetTransparentColor(uint8 red,
|
||||||
|
uint8 green,
|
||||||
|
uint8 blue);
|
||||||
|
|
||||||
|
inline int SizeInBits() const
|
||||||
|
{ return fSizeInBits; }
|
||||||
|
|
||||||
|
inline int BackgroundIndex() const
|
||||||
|
{ return fBackgroundIndex; }
|
||||||
|
|
||||||
|
void GetColors(uint8* buffer, int size) const;
|
||||||
|
|
||||||
|
rgb_color* pal;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fSize;
|
||||||
|
int fSizeInBits;
|
||||||
|
int fMode;
|
||||||
|
bool fUseTransparent;
|
||||||
|
int fTransparentIndex;
|
||||||
|
int fBackgroundIndex;
|
||||||
|
bool fFatalError;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// IndexForColor
|
||||||
|
inline uint8
|
||||||
|
SavePalette::IndexForColor(const rgb_color& color)
|
||||||
|
{
|
||||||
|
return IndexForColor(color.red, color.green, color.blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user