Add alpha channel to palette/color bar/color selector (issue #286)

This commit is contained in:
David Capello 2015-06-30 17:36:37 -03:00
parent 78918c0df8
commit 318bc2e2f9
18 changed files with 217 additions and 118 deletions

View File

@ -35,30 +35,33 @@ Color Color::fromMask()
}
// static
Color Color::fromRgb(int r, int g, int b)
Color Color::fromRgb(int r, int g, int b, int a)
{
Color color(Color::RgbType);
color.m_value.rgb.r = r;
color.m_value.rgb.g = g;
color.m_value.rgb.b = b;
color.m_value.rgb.a = a;
return color;
}
// static
Color Color::fromHsv(int h, int s, int v)
Color Color::fromHsv(int h, int s, int v, int a)
{
Color color(Color::HsvType);
color.m_value.hsv.h = h;
color.m_value.hsv.s = s;
color.m_value.hsv.v = v;
color.m_value.hsv.a = a;
return color;
}
// static
Color Color::fromGray(int g)
Color Color::fromGray(int g, int a)
{
Color color(Color::GrayType);
color.m_value.gray = g;
color.m_value.gray.g = g;
color.m_value.gray.a = a;
return color;
}
@ -83,13 +86,15 @@ Color Color::fromImage(PixelFormat pixelFormat, color_t c)
if (rgba_geta(c) > 0) {
color = Color::fromRgb(rgba_getr(c),
rgba_getg(c),
rgba_getb(c));
rgba_getb(c),
rgba_geta(c));
}
break;
case IMAGE_GRAYSCALE:
if (graya_geta(c) > 0) {
color = Color::fromGray(graya_getv(c));
color = Color::fromGray(graya_getv(c),
graya_geta(c));
}
break;
@ -117,26 +122,26 @@ Color Color::fromString(const std::string& str)
if (str != "mask") {
if (str.find("rgb{") == 0 ||
str.find("hsv{") == 0) {
int c = 0, table[3] = { 0, 0, 0 };
str.find("hsv{") == 0 ||
str.find("gray{") == 0) {
int c = 0, table[4] = { 0, 0, 0, 255 };
std::string::size_type i = 4, j;
while ((j = str.find_first_of(",}", i)) != std::string::npos) {
std::string element = str.substr(i, j - i);
if (c < 3)
if (c < 4)
table[c++] = std::strtol(element.c_str(), NULL, 10);
if (c >= 3)
if (c >= 4)
break;
i = j+1;
}
if (str[0] == 'r')
color = Color::fromRgb(table[0], table[1], table[2]);
else
color = Color::fromHsv(table[0], table[1], table[2]);
}
else if (str.find("gray{") == 0) {
color = Color::fromGray(std::strtol(str.c_str()+5, NULL, 10));
color = Color::fromRgb(table[0], table[1], table[2], table[3]);
else if (str[0] == 'h')
color = Color::fromHsv(table[0], table[1], table[2], table[3]);
else if (str[0] == 'g')
color = Color::fromGray(table[0], c >= 2 ? table[1]: 255);
}
else if (str.find("index{") == 0) {
color = Color::fromIndex(std::strtol(str.c_str()+6, NULL, 10));
@ -160,18 +165,22 @@ std::string Color::toString() const
result << "rgb{"
<< m_value.rgb.r << ","
<< m_value.rgb.g << ","
<< m_value.rgb.b << "}";
<< m_value.rgb.b << ","
<< m_value.rgb.a << "}";
break;
case Color::HsvType:
result << "hsv{"
<< m_value.hsv.h << ","
<< m_value.hsv.s << ","
<< m_value.hsv.v << "}";
<< m_value.hsv.v << ","
<< m_value.hsv.a << "}";
break;
case Color::GrayType:
result << "gray{" << m_value.gray << "}";
result << "gray{"
<< m_value.gray.g << ","
<< m_value.gray.a << "}";
break;
case Color::IndexType:
@ -226,7 +235,7 @@ std::string Color::toHumanReadableString(PixelFormat pixelFormat, HumanReadableS
break;
case Color::GrayType:
result << "Gray " << m_value.gray;
result << "Gray " << m_value.gray.g;
break;
case Color::IndexType: {
@ -288,7 +297,7 @@ std::string Color::toHumanReadableString(PixelFormat pixelFormat, HumanReadableS
break;
case Color::GrayType:
result << "Gry-" << m_value.gray;
result << "Gry-" << m_value.gray.g;
break;
case Color::IndexType:
@ -318,16 +327,20 @@ bool Color::operator==(const Color& other) const
return
m_value.rgb.r == other.m_value.rgb.r &&
m_value.rgb.g == other.m_value.rgb.g &&
m_value.rgb.b == other.m_value.rgb.b;
m_value.rgb.b == other.m_value.rgb.b &&
m_value.rgb.a == other.m_value.rgb.a;
case Color::HsvType:
return
m_value.hsv.h == other.m_value.hsv.h &&
m_value.hsv.s == other.m_value.hsv.s &&
m_value.hsv.v == other.m_value.hsv.v;
m_value.hsv.v == other.m_value.hsv.v &&
m_value.hsv.a == other.m_value.hsv.a;
case Color::GrayType:
return m_value.gray == other.m_value.gray;
return
m_value.gray.g == other.m_value.gray.g &&
m_value.gray.a == other.m_value.gray.a;
case Color::IndexType:
return m_value.index == other.m_value.index;
@ -370,7 +383,7 @@ int Color::getRed() const
double(m_value.hsv.v) / 100.0)).red();
case Color::GrayType:
return m_value.gray;
return m_value.gray.g;
case Color::IndexType: {
int i = m_value.index;
@ -402,7 +415,7 @@ int Color::getGreen() const
double(m_value.hsv.v) / 100.0)).green();
case Color::GrayType:
return m_value.gray;
return m_value.gray.g;
case Color::IndexType: {
int i = m_value.index;
@ -434,7 +447,7 @@ int Color::getBlue() const
double(m_value.hsv.v) / 100.0)).blue();
case Color::GrayType:
return m_value.gray;
return m_value.gray.g;
case Color::IndexType: {
int i = m_value.index;
@ -538,7 +551,7 @@ int Color::getValue() const
return m_value.hsv.v;
case Color::GrayType:
return 100 * m_value.gray / 255;
return 100 * m_value.gray.g / 255;
case Color::IndexType: {
int i = m_value.index;
@ -574,7 +587,7 @@ int Color::getGray() const
return 255 * m_value.hsv.v / 100;
case Color::GrayType:
return m_value.gray;
return m_value.gray.g;
case Color::IndexType: {
int i = m_value.index;
@ -602,13 +615,9 @@ int Color::getIndex() const
return 0;
case Color::RgbType:
return get_current_palette()->findBestfit(getRed(), getGreen(), getBlue());
case Color::HsvType:
return get_current_palette()->findBestfit(getRed(), getGreen(), getBlue());
case Color::GrayType:
return m_value.gray;
return get_current_palette()->findBestfit(getRed(), getGreen(), getBlue(), getAlpha(), 0);
case Color::IndexType:
return m_value.index;
@ -619,4 +628,34 @@ int Color::getIndex() const
return -1;
}
int Color::getAlpha() const
{
switch (getType()) {
case Color::MaskType:
return 0;
case Color::RgbType:
return m_value.rgb.a;
case Color::HsvType:
return m_value.hsv.a;
case Color::GrayType:
return m_value.gray.a;
case Color::IndexType: {
int i = m_value.index;
if (i >= 0 && i < get_current_palette()->size())
return rgba_geta(get_current_palette()->getEntry(i));
else
return 0;
}
}
ASSERT(false);
return -1;
}
} // namespace app

View File

@ -42,9 +42,9 @@ namespace app {
Color() : m_type(MaskType) { }
static Color fromMask();
static Color fromRgb(int r, int g, int b);
static Color fromHsv(int h, int s, int v); // h=[0,360], s=[0,100], v=[0,100]
static Color fromGray(int g);
static Color fromRgb(int r, int g, int b, int a = 255);
static Color fromHsv(int h, int s, int v, int a = 255); // h=[0,360], s=[0,100], v=[0,100]
static Color fromGray(int g, int a = 255);
static Color fromIndex(int index);
static Color fromImage(PixelFormat pixelFormat, color_t c);
@ -74,6 +74,7 @@ namespace app {
int getValue() const;
int getGray() const;
int getIndex() const;
int getAlpha() const;
private:
Color(Type type) : m_type(type) { }
@ -84,12 +85,14 @@ namespace app {
// Color value
union {
struct {
int r, g, b;
int r, g, b, a;
} rgb;
struct {
int h, s, v;
int h, s, v, a;
} hsv;
int gray;
struct {
int g, a;
} gray;
int index;
} m_value;
};

View File

@ -52,14 +52,16 @@ gfx::Color color_utils::color_for_ui(const app::Color& color)
c = gfx::rgba(
color.getRed(),
color.getGreen(),
color.getBlue(), 255);
color.getBlue(),
color.getAlpha());
break;
case app::Color::GrayType:
c = gfx::rgba(
color.getGray(),
color.getGray(),
color.getGray(), 255);
color.getGray(),
color.getAlpha());
break;
case app::Color::IndexType: {
@ -70,7 +72,8 @@ gfx::Color color_utils::color_for_ui(const app::Color& color)
c = gfx::rgba(
rgba_getr(_c),
rgba_getg(_c),
rgba_getb(_c), 255);
rgba_getb(_c),
color.getAlpha());
break;
}
@ -116,10 +119,10 @@ doc::color_t color_utils::color_for_target_mask(const app::Color& color, const C
else {
switch (colorTarget.pixelFormat()) {
case IMAGE_RGB:
c = doc::rgba(color.getRed(), color.getGreen(), color.getBlue(), 255);
c = doc::rgba(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
break;
case IMAGE_GRAYSCALE:
c = doc::graya(color.getGray(), 255);
c = doc::graya(color.getGray(), color.getAlpha());
break;
case IMAGE_INDEXED:
if (color.getType() == app::Color::IndexType) {
@ -130,6 +133,7 @@ doc::color_t color_utils::color_for_target_mask(const app::Color& color, const C
color.getRed(),
color.getGreen(),
color.getBlue(),
color.getAlpha(),
colorTarget.isTransparent() ?
colorTarget.maskColor(): // Don't return the mask color
-1); // Return any color, we are in a background layer.

View File

@ -497,7 +497,7 @@ void PaletteEntryEditor::setAbsolutePaletteEntryChannel(ColorSliders::Channel ch
int picksCount = entries.picks();
uint32_t src_color;
int r, g, b;
int r, g, b, a;
Palette* palette = get_current_palette();
for (int c=0; c<palette->size(); c++) {
@ -509,6 +509,7 @@ void PaletteEntryEditor::setAbsolutePaletteEntryChannel(ColorSliders::Channel ch
r = rgba_getr(src_color);
g = rgba_getg(src_color);
b = rgba_getb(src_color);
a = rgba_geta(src_color);
switch (m_type) {
@ -518,6 +519,7 @@ void PaletteEntryEditor::setAbsolutePaletteEntryChannel(ColorSliders::Channel ch
r = color.getRed();
g = color.getGreen();
b = color.getBlue();
a = color.getAlpha();
}
// Modify one channel a set of entries
else {
@ -531,6 +533,9 @@ void PaletteEntryEditor::setAbsolutePaletteEntryChannel(ColorSliders::Channel ch
case ColorSliders::Blue:
b = color.getBlue();
break;
case ColorSliders::Alpha:
a = color.getAlpha();
break;
}
}
break;
@ -561,6 +566,9 @@ void PaletteEntryEditor::setAbsolutePaletteEntryChannel(ColorSliders::Channel ch
case ColorSliders::Value:
hsv.value(double(color.getValue()) / 100.0);
break;
case ColorSliders::Alpha:
a = color.getAlpha();
break;
}
}
@ -573,7 +581,7 @@ void PaletteEntryEditor::setAbsolutePaletteEntryChannel(ColorSliders::Channel ch
break;
}
palette->setEntry(c, doc::rgba(r, g, b, 255));
palette->setEntry(c, doc::rgba(r, g, b, a));
}
}
@ -586,7 +594,7 @@ void PaletteEntryEditor::setRelativePaletteEntryChannel(ColorSliders::Channel ch
m_relDeltas[channel] = delta;
uint32_t src_color;
int r, g, b;
int r, g, b, a;
Palette* palette = get_current_palette();
for (int c=0; c<palette->size(); c++) {
@ -598,6 +606,7 @@ void PaletteEntryEditor::setRelativePaletteEntryChannel(ColorSliders::Channel ch
r = rgba_getr(src_color);
g = rgba_getg(src_color);
b = rgba_getb(src_color);
a = rgba_geta(src_color);
switch (m_type) {
@ -605,6 +614,7 @@ void PaletteEntryEditor::setRelativePaletteEntryChannel(ColorSliders::Channel ch
r = MID(0, r+m_relDeltas[ColorSliders::Red], 255);
g = MID(0, g+m_relDeltas[ColorSliders::Green], 255);
b = MID(0, b+m_relDeltas[ColorSliders::Blue], 255);
a = MID(0, a+m_relDeltas[ColorSliders::Alpha], 255);
break;
case app::Color::HsvType: {
@ -627,12 +637,13 @@ void PaletteEntryEditor::setRelativePaletteEntryChannel(ColorSliders::Channel ch
r = rgb.red();
g = rgb.green();
b = rgb.blue();
a = MID(0, a+m_relDeltas[ColorSliders::Alpha], 255);
break;
}
}
palette->setEntry(c, doc::rgba(r, g, b, 255));
palette->setEntry(c, doc::rgba(r, g, b, a));
}
}

View File

@ -666,9 +666,7 @@ static Palette* ase_file_read_palette_chunk(FILE* f, Palette* prevPal, frame_t f
int g = fgetc(f);
int b = fgetc(f);
int a = fgetc(f);
// TODO don't ignore alpha
pal->setEntry(c, rgba(r, g, b, 255));
pal->setEntry(c, rgba(r, g, b, a));
// Skip name
if (flags & 1) {

View File

@ -62,18 +62,23 @@ static void rectgrid(ui::Graphics* g, const gfx::Rect& rc, const gfx::Size& tile
}
}
static void draw_color(ui::Graphics* g, const Rect& rc, const app::Color& color)
void draw_color(ui::Graphics* g, const Rect& rc, const app::Color& color)
{
if (rc.w < 1 || rc.h < 1)
return;
app::Color::Type type = color.getType();
int alpha = color.getAlpha();
if (type == app::Color::MaskType) {
if (alpha < 255) {
if (rc.w == rc.h)
rectgrid(g, rc, gfx::Size(rc.w/2, rc.h/2));
else
rectgrid(g, rc, gfx::Size(rc.w/4, rc.h/2));
return;
}
else if (type == app::Color::IndexType) {
if (alpha > 0) {
if (type == app::Color::IndexType) {
int index = color.getIndex();
if (index >= 0 && index < get_current_palette()->size()) {
@ -85,11 +90,11 @@ static void draw_color(ui::Graphics* g, const Rect& rc, const app::Color& color)
gfx::Point(rc.x+rc.w-2, rc.y+1),
gfx::Point(rc.x+1, rc.y+rc.h-2));
}
return;
}
else
g->fillRect(color_utils::color_for_ui(color), rc);
}
}
void draw_color_button(ui::Graphics* g,
const Rect& rc, const app::Color& color,

View File

@ -18,6 +18,9 @@
namespace app {
using namespace doc;
void draw_color(ui::Graphics* g,
const gfx::Rect& rc, const app::Color& color);
void draw_color_button(ui::Graphics* g,
const gfx::Rect& rc, const app::Color& color,
bool hot, bool drag);

View File

@ -819,7 +819,7 @@ void BrushInkProcessing<IndexedTraits>::processPixel(int x, int y) {
switch (m_brushImage->pixelFormat()) {
case IMAGE_RGB: {
c = get_pixel_fast<RgbTraits>(m_brushImage, x, y);
c = m_palette->findBestfit(rgba_getr(c), rgba_getg(c), rgba_getb(c));
c = m_palette->findBestfit(rgba_getr(c), rgba_getg(c), rgba_getb(c), rgba_geta(c), 0);
break;
}
case IMAGE_INDEXED: {
@ -828,8 +828,7 @@ void BrushInkProcessing<IndexedTraits>::processPixel(int x, int y) {
}
case IMAGE_GRAYSCALE: {
c = get_pixel_fast<GrayscaleTraits>(m_brushImage, x, y);
c = graya_getv(c);
c = m_palette->findBestfit(c, c, c);
c = m_palette->findBestfit(graya_getv(c), graya_getv(c), graya_getv(c), graya_geta(c), 0);
break;
}
case IMAGE_BITMAP: {

View File

@ -805,11 +805,13 @@ void ColorBar::onFixWarningClick(ColorButton* colorButton, ui::Button* warningIc
color_t color = doc::rgba(
appColor.getRed(),
appColor.getGreen(),
appColor.getBlue(), 255);
appColor.getBlue(),
appColor.getAlpha());
int index = newPalette->findExactMatch(
appColor.getRed(),
appColor.getGreen(),
appColor.getBlue());
appColor.getBlue(),
appColor.getAlpha());
// It should be -1, because the user has pressed the warning
// button that is available only when the color isn't in the
@ -853,7 +855,8 @@ void ColorBar::updateWarningIcon(const app::Color& color, ui::Button* warningIco
int index = get_current_palette()->findExactMatch(
color.getRed(),
color.getGreen(),
color.getBlue());
color.getBlue(),
color.getAlpha());
warningIcon->setVisible(index < 0);
warningIcon->getParent()->layout();

View File

@ -159,20 +159,27 @@ void ColorSelector::onColorHexEntryChange(const app::Color& color)
void ColorSelector::onColorTypeClick()
{
app::Color newColor;
app::Color newColor = getColor();
switch (m_colorType.selectedItem()) {
case INDEX_MODE:
newColor = app::Color::fromIndex(getColor().getIndex());
newColor = app::Color::fromIndex(newColor.getIndex());
break;
case RGB_MODE:
newColor = app::Color::fromRgb(getColor().getRed(), getColor().getGreen(), getColor().getBlue());
newColor = app::Color::fromRgb(newColor.getRed(),
newColor.getGreen(),
newColor.getBlue(),
newColor.getAlpha());
break;
case HSB_MODE:
newColor = app::Color::fromHsv(getColor().getHue(), getColor().getSaturation(), getColor().getValue());
newColor = app::Color::fromHsv(newColor.getHue(),
newColor.getSaturation(),
newColor.getValue(),
newColor.getAlpha());
break;
case GRAY_MODE:
newColor = app::Color::fromGray(getColor().getGray());
newColor = app::Color::fromGray(newColor.getGray(),
newColor.getAlpha());
break;
case MASK_MODE:
newColor = app::Color::fromMask();
@ -194,10 +201,11 @@ void ColorSelector::findBestfitIndex(const app::Color& color)
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
int a = color.getAlpha();
// Search for the closest color to the RGB values
int i = get_current_palette()->findBestfit(r, g, b);
if (i >= 0 && i < 256) {
int i = get_current_palette()->findBestfit(r, g, b, a, 0);
if (i >= 0) {
m_colorPalette.deselect();
m_colorPalette.selectColor(i);
}

View File

@ -237,6 +237,7 @@ RgbSliders::RgbSliders()
addSlider(Red, "R", 0, 255);
addSlider(Green, "G", 0, 255);
addSlider(Blue, "B", 0, 255);
addSlider(Alpha, "A", 0, 255);
}
void RgbSliders::onSetColor(const app::Color& color)
@ -244,13 +245,15 @@ void RgbSliders::onSetColor(const app::Color& color)
setAbsSliderValue(0, color.getRed());
setAbsSliderValue(1, color.getGreen());
setAbsSliderValue(2, color.getBlue());
setAbsSliderValue(3, color.getAlpha());
}
app::Color RgbSliders::getColorFromSliders()
{
return app::Color::fromRgb(getAbsSliderValue(0),
getAbsSliderValue(1),
getAbsSliderValue(2));
getAbsSliderValue(2),
getAbsSliderValue(3));
}
//////////////////////////////////////////////////////////////////////
@ -262,6 +265,7 @@ HsvSliders::HsvSliders()
addSlider(Hue, "H", 0, 360);
addSlider(Saturation, "S", 0, 100);
addSlider(Value, "B", 0, 100);
addSlider(Alpha, "A", 0, 255);
}
void HsvSliders::onSetColor(const app::Color& color)
@ -269,13 +273,15 @@ void HsvSliders::onSetColor(const app::Color& color)
setAbsSliderValue(0, color.getHue());
setAbsSliderValue(1, color.getSaturation());
setAbsSliderValue(2, color.getValue());
setAbsSliderValue(3, color.getAlpha());
}
app::Color HsvSliders::getColorFromSliders()
{
return app::Color::fromHsv(getAbsSliderValue(0),
getAbsSliderValue(1),
getAbsSliderValue(2));
getAbsSliderValue(2),
getAbsSliderValue(3));
}
//////////////////////////////////////////////////////////////////////
@ -285,17 +291,19 @@ GraySlider::GraySlider()
: ColorSliders()
{
addSlider(Gray, "V", 0, 255);
addSlider(Alpha, "A", 0, 255);
}
void GraySlider::onSetColor(const app::Color& color)
{
setAbsSliderValue(0, color.getGray());
setAbsSliderValue(1, color.getAlpha());
}
app::Color GraySlider::getColorFromSliders()
{
return app::Color::fromGray(getAbsSliderValue(0));
return app::Color::fromGray(getAbsSliderValue(0),
getAbsSliderValue(1));
}
} // namespace app

View File

@ -31,7 +31,8 @@ namespace app {
public:
enum Channel { Red, Green, Blue,
Hue, Saturation, Value,
Gray };
Gray,
Alpha };
enum Mode { Absolute, Relative };
ColorSliders();

View File

@ -14,6 +14,7 @@
#include "app/color_utils.h"
#include "app/commands/commands.h"
#include "app/modules/editors.h"
#include "app/modules/gfx.h"
#include "app/modules/gui.h"
#include "app/modules/palettes.h"
#include "app/ui/editor/editor.h"
@ -422,37 +423,44 @@ void PaletteView::onPaint(ui::PaintEvent& ev)
// Draw palette entries
for (int i=0; i<palette->size(); ++i) {
gfx::Rect box = getPaletteEntryBounds(i);
gfx::Color color = gfx::rgba(
rgba_getr(palette->getEntry(i)),
rgba_getg(palette->getEntry(i)),
rgba_getb(palette->getEntry(i)));
doc::color_t palColor = palette->getEntry(i);
app::Color appColor = app::Color::fromRgb(
rgba_getr(palColor),
rgba_getg(palColor),
rgba_getb(palColor),
rgba_geta(palColor));
gfx::Color gfxColor = gfx::rgba(
rgba_getr(palColor),
rgba_getg(palColor),
rgba_getb(palColor),
rgba_geta(palColor));
g->drawRect(gfx::rgba(0, 0, 0), gfx::Rect(box).enlarge(guiscale()));
g->fillRect(color, box);
draw_color(g, box, appColor);
switch (m_style) {
case SelectOneColor:
if (m_currentEntry == i)
g->fillRect(color_utils::blackandwhite_neg(color),
g->fillRect(color_utils::blackandwhite_neg(gfxColor),
gfx::Rect(box.getCenter(), gfx::Size(1, 1)));
break;
case FgBgColors:
if (fgIndex == i) {
gfx::Color neg = color_utils::blackandwhite_neg(color);
gfx::Color neg = color_utils::blackandwhite_neg(gfxColor);
for (int i=0; i<m_boxsize/2; ++i)
g->drawHLine(neg, box.x, box.y+i, m_boxsize/2-i);
}
if (bgIndex == i) {
gfx::Color neg = color_utils::blackandwhite_neg(color);
gfx::Color neg = color_utils::blackandwhite_neg(gfxColor);
for (int i=0; i<m_boxsize/4; ++i)
g->drawHLine(neg, box.x+box.w-(i+1), box.y+box.h-m_boxsize/4+i, i+1);
}
if (transparentIndex == i)
g->fillRect(color_utils::blackandwhite_neg(color),
g->fillRect(color_utils::blackandwhite_neg(gfxColor),
gfx::Rect(box.getCenter(), gfx::Size(1, 1)));
break;
}
@ -804,7 +812,7 @@ int PaletteView::findExactIndex(const app::Color& color) const
case Color::RgbType:
case Color::HsvType:
case Color::GrayType:
return currentPalette()->findExactMatch(color.getRed(), color.getGreen(), color.getBlue());
return currentPalette()->findExactMatch(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
case Color::IndexType:
return color.getIndex();

View File

@ -142,9 +142,9 @@ void Palette::makeBlack()
// Creates a linear ramp in the palette.
void Palette::makeGradient(int from, int to)
{
int r, g, b;
int r1, g1, b1;
int r2, g2, b2;
int r, g, b, a;
int r1, g1, b1, a1;
int r2, g2, b2, a2;
int i, n;
ASSERT(from >= 0 && from <= 255);
@ -160,22 +160,27 @@ void Palette::makeGradient(int from, int to)
r1 = rgba_getr(getEntry(from));
g1 = rgba_getg(getEntry(from));
b1 = rgba_getb(getEntry(from));
a1 = rgba_geta(getEntry(from));
r2 = rgba_getr(getEntry(to));
g2 = rgba_getg(getEntry(to));
b2 = rgba_getb(getEntry(to));
a2 = rgba_geta(getEntry(to));
for (i=from+1; i<to; ++i) {
r = r1 + (r2-r1) * (i-from) / n;
g = g1 + (g2-g1) * (i-from) / n;
b = b1 + (b2-b1) * (i-from) / n;
setEntry(i, rgba(r, g, b, 255));
a = a1 + (a2-a1) * (i-from) / n;
setEntry(i, rgba(r, g, b, a));
}
}
int Palette::findExactMatch(int r, int g, int b) const
int Palette::findExactMatch(int r, int g, int b, int a) const
{
for (int i=0; i<(int)m_colors.size(); ++i)
if (getEntry(i) == rgba(r, g, b, 255))
if (getEntry(i) == rgba(r, g, b, a))
return i;
return -1;
@ -198,18 +203,14 @@ static void bestfit_init()
}
}
int Palette::findBestfit(int r, int g, int b, int mask_index) const
int Palette::findBestfit(int r, int g, int b, int a, int mask_index) const
{
#ifdef __GNUC__
register int bestfit asm("%eax");
#else
register int bestfit;
#endif
int i, coldiff, lowest;
int i, bestfit, coldiff, lowest;
ASSERT(r >= 0 && r <= 255);
ASSERT(g >= 0 && g <= 255);
ASSERT(b >= 0 && b <= 255);
ASSERT(a >= 0 && a <= 255);
if (col_diff[1] == 0)
bestfit_init();

View File

@ -77,8 +77,8 @@ namespace doc {
void makeGradient(int from, int to);
int findExactMatch(int r, int g, int b) const;
int findBestfit(int r, int g, int b, int mask_index = 0) const;
int findExactMatch(int r, int g, int b, int a) const;
int findBestfit(int r, int g, int b, int a, int mask_index) const;
private:
frame_t m_frame;

View File

@ -44,7 +44,7 @@ void RgbMap::regenerate(const Palette* palette, int mask_index)
palette->findBestfit(
scale_5bits_to_8bits(r),
scale_5bits_to_8bits(g),
scale_5bits_to_8bits(b), mask_index);
scale_5bits_to_8bits(b), 255, mask_index);
}
}
}

View File

@ -90,7 +90,7 @@ namespace render {
int b = doc::rgba_getb(color);
doc::color_t nearest1idx =
(rgbmap ? rgbmap->mapColor(r, g, b):
palette->findBestfit(r, g, b, m_transparentIndex));
palette->findBestfit(r, g, b, 255, m_transparentIndex));
doc::color_t nearest1rgb = palette->getEntry(nearest1idx);
int r1 = doc::rgba_getr(nearest1rgb);
@ -109,7 +109,7 @@ namespace render {
b2 = MID(0, b2, 255);
doc::color_t nearest2idx =
(rgbmap ? rgbmap->mapColor(r2, g2, b2):
palette->findBestfit(r2, g2, b2, m_transparentIndex));
palette->findBestfit(r2, g2, b2, 255, m_transparentIndex));
// If both possible RGB colors use the same index, we cannot
// make any dither with these two colors.

View File

@ -492,10 +492,18 @@ void Render::renderSprite(
switch (m_bgType) {
case BgType::CHECKED:
if (bgLayer && bgLayer->isVisible())
if (bgLayer && bgLayer->isVisible() && rgba_geta(bg_color) == 255) {
fill_rect(dstImage, area.dstBounds(), bg_color);
else
}
else {
renderBackground(dstImage, area, zoom);
if (bgLayer && bgLayer->isVisible() && rgba_geta(bg_color) > 0) {
blend_rect(dstImage, area.dst.x, area.dst.y,
area.dst.x+area.size.w-1,
area.dst.y+area.size.h-1,
bg_color, 255);
}
}
break;
case BgType::TRANSPARENT: