#include "RGBColor.h"
#include "SystemPalette.h"
#include <stdio.h>
#include <stdlib.h>
#define RATIO_8_TO_5_BIT .121568627451
#define RATIO_8_TO_6_BIT .247058823529
#define RATIO_5_TO_8_BIT 8.22580645161
#define RATIO_6_TO_8_BIT 4.04761904762
#if 0
void
SetRGBColor16(rgb_color *col,uint16 color)
{
if(!col)
return;
uint16 r16,g16,b16;
col->alpha=0;
r16= (color >> 11) & 31;
g16= (color >> 5) & 63;
b16= color & 31;
col->red=uint8(r16 * RATIO_5_TO_8_BIT);
col->green=uint8(g16 * RATIO_6_TO_8_BIT);
col->blue=uint8(b16 * RATIO_5_TO_8_BIT);
}
#endif
static uint8
FindClosestColor(const rgb_color *palette, rgb_color color)
{
if (!palette)
return 0;
uint16 cindex = 0, cdelta = 765, delta = 765;
for (uint16 i = 0; i < 256; i++) {
const rgb_color *c = &(palette[i]);
delta = abs(c->red-color.red) + abs(c->green-color.green)
+ abs(c->blue-color.blue);
if (delta == 0) {
cindex = i;
break;
}
if (delta < cdelta) {
cindex = i;
cdelta = delta;
}
}
return (uint8)cindex;
}
static uint16
FindClosestColor15(rgb_color color)
{
uint16 r16 = uint16(color.red * RATIO_8_TO_5_BIT);
uint16 g16 = uint16(color.green * RATIO_8_TO_5_BIT);
uint16 b16 = uint16(color.blue * RATIO_8_TO_5_BIT);
uint16 color16 = color.alpha > 127 ? 0x8000 : 0;
color16 |= r16 << 10;
color16 |= g16 << 5;
color16 |= b16;
return color16;
}
static uint16
FindClosestColor16(rgb_color color)
{
uint16 r16 = uint16(color.red * RATIO_8_TO_5_BIT);
uint16 g16 = uint16(color.green * RATIO_8_TO_6_BIT);
uint16 b16 = uint16(color.blue * RATIO_8_TO_5_BIT);
uint16 color16 = r16 << 11;
color16 |= g16 << 5;
color16 |= b16;
return color16;
}
RGBColor::RGBColor(uint8 r, uint8 g, uint8 b, uint8 a)
{
SetColor(r,g,b,a);
}
RGBColor::RGBColor(int r, int g, int b, int a)
{
SetColor(r, g, b, a);
}
RGBColor::RGBColor(const rgb_color &color)
{
SetColor(color);
}
#if 0
RGBColor::RGBColor(uint16 color)
{
SetColor(color);
}
#endif
RGBColor::RGBColor(uint8 color)
{
SetColor(color);
}
RGBColor::RGBColor(const RGBColor &color)
{
fColor32 = color.fColor32;
fColor16 = color.fColor16;
fColor15 = color.fColor15;
fColor8 = color.fColor8;
fUpdate8 = color.fUpdate8;
fUpdate15 = color.fUpdate15;
fUpdate16 = color.fUpdate16;
}
RGBColor::RGBColor()
{
SetColor(0, 0, 0, 0);
}
uint8
RGBColor::GetColor8() const
{
if (fUpdate8) {
fColor8 = FindClosestColor(SystemPalette(), fColor32);
fUpdate8 = false;
}
return fColor8;
}
uint16
RGBColor::GetColor15() const
{
if (fUpdate15) {
fColor15 = FindClosestColor15(fColor32);
fUpdate15 = false;
}
return fColor15;
}
uint16
RGBColor::GetColor16() const
{
if (fUpdate16) {
fColor16 = FindClosestColor16(fColor32);
fUpdate16 = false;
}
return fColor16;
}
rgb_color
RGBColor::GetColor32() const
{
return fColor32;
}
void
RGBColor::SetColor(uint8 r, uint8 g, uint8 b, uint8 a)
{
fColor32.red = r;
fColor32.green = g;
fColor32.blue = b;
fColor32.alpha = a;
fUpdate8 = fUpdate15 = fUpdate16 = true;
}
void
RGBColor::SetColor(int r, int g, int b, int a)
{
fColor32.red = (uint8)r;
fColor32.green = (uint8)g;
fColor32.blue = (uint8)b;
fColor32.alpha = (uint8)a;
fUpdate8 = fUpdate15 = fUpdate16 = true;
}
#if 0
void
RGBColor::SetColor(uint16 col16)
{
fColor16 = col16;
SetRGBColor(&fColor32, col16);
fUpdate8 = true;
fUpdate15 = true;
fUpdate16 = false;
}
#endif
void
RGBColor::SetColor(uint8 col8)
{
fColor8 = col8;
fColor32 = SystemPalette()[col8];
fUpdate8 = false;
fUpdate15 = true;
fUpdate16 = true;
}
void
RGBColor::SetColor(const rgb_color &color)
{
fColor32 = color;
fUpdate8 = fUpdate15 = fUpdate16 = true;
}
void
RGBColor::SetColor(const RGBColor &color)
{
fColor32 = color.fColor32;
fColor16 = color.fColor16;
fColor15 = color.fColor15;
fColor8 = color.fColor8;
fUpdate8 = color.fUpdate8;
fUpdate15 = color.fUpdate15;
fUpdate16 = color.fUpdate16;
}
const RGBColor&
RGBColor::operator=(const RGBColor &color)
{
fColor32 = color.fColor32;
fColor16 = color.fColor16;
fColor15 = color.fColor15;
fColor8 = color.fColor8;
fUpdate8 = color.fUpdate8;
fUpdate15 = color.fUpdate15;
fUpdate16 = color.fUpdate16;
return *this;
}
const RGBColor&
RGBColor::operator=(const rgb_color &color)
{
fColor32 = color;
fUpdate8 = fUpdate15 = fUpdate16 = true;
return *this;
}
void
RGBColor::PrintToStream(void) const
{
printf("RGBColor(%u,%u,%u,%u)\n",
fColor32.red, fColor32.green, fColor32.blue, fColor32.alpha);
}
bool
RGBColor::operator==(const rgb_color &color) const
{
return fColor32.red == color.red
&& fColor32.green == color.green
&& fColor32.blue == color.blue
&& fColor32.alpha == color.alpha;
}
bool
RGBColor::operator==(const RGBColor &color) const
{
return fColor32.red == color.fColor32.red
&& fColor32.green == color.fColor32.green
&& fColor32.blue == color.fColor32.blue
&& fColor32.alpha == color.fColor32.alpha;
}
bool
RGBColor::operator!=(const rgb_color &color) const
{
return fColor32.red != color.red
|| fColor32.green != color.green
|| fColor32.blue != color.blue
|| fColor32.alpha != color.alpha;
}
bool
RGBColor::operator!=(const RGBColor &color) const
{
return fColor32.red != color.fColor32.red
|| fColor32.green != color.fColor32.green
|| fColor32.blue != color.fColor32.blue
|| fColor32.alpha != color.fColor32.alpha;
}
bool
RGBColor::IsTransparentMagic() const
{
return *this == B_TRANSPARENT_COLOR;
}