mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-04 06:40:07 +00:00
Fix ReplaceInkProcessing to work correctly with transparent colors (fix #435)
Now we can replace a solid color with transparent in RGBA and Grayscale images.
This commit is contained in:
parent
ef25706ed2
commit
8a9ea26811
@ -119,31 +119,44 @@ raster::color_t color_utils::color_for_layer(const app::Color& color, Layer* lay
|
|||||||
|
|
||||||
raster::color_t color_utils::color_for_target(const app::Color& color, const ColorTarget& colorTarget)
|
raster::color_t color_utils::color_for_target(const app::Color& color, const ColorTarget& colorTarget)
|
||||||
{
|
{
|
||||||
if (color.getType() == app::Color::MaskType)
|
|
||||||
return colorTarget.maskColor();
|
|
||||||
|
|
||||||
raster::color_t c = -1;
|
raster::color_t c = -1;
|
||||||
|
|
||||||
|
if (color.getType() == app::Color::MaskType) {
|
||||||
|
c = colorTarget.maskColor();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (colorTarget.pixelFormat()) {
|
||||||
|
case IMAGE_RGB:
|
||||||
|
c = raster::rgba(color.getRed(), color.getGreen(), color.getBlue(), 255);
|
||||||
|
break;
|
||||||
|
case IMAGE_GRAYSCALE:
|
||||||
|
c = raster::graya(color.getGray(), 255);
|
||||||
|
break;
|
||||||
|
case IMAGE_INDEXED:
|
||||||
|
if (color.getType() == app::Color::IndexType) {
|
||||||
|
c = color.getIndex();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c = get_current_palette()->findBestfit(
|
||||||
|
color.getRed(),
|
||||||
|
color.getGreen(),
|
||||||
|
color.getBlue(),
|
||||||
|
colorTarget.isTransparent() ?
|
||||||
|
colorTarget.maskColor(): // Don't return the mask color
|
||||||
|
-1); // Return any color, we are in a background layer.
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (colorTarget.pixelFormat()) {
|
switch (colorTarget.pixelFormat()) {
|
||||||
case IMAGE_RGB:
|
case IMAGE_RGB:
|
||||||
c = raster::rgba(color.getRed(), color.getGreen(), color.getBlue(), 255);
|
if (colorTarget.isBackground())
|
||||||
|
c |= raster::rgba(0, 0, 0, 255);
|
||||||
break;
|
break;
|
||||||
case IMAGE_GRAYSCALE:
|
case IMAGE_GRAYSCALE:
|
||||||
c = raster::graya(color.getGray(), 255);
|
if (colorTarget.isBackground())
|
||||||
break;
|
c |= raster::graya(0, 255);
|
||||||
case IMAGE_INDEXED:
|
|
||||||
if (color.getType() == app::Color::IndexType) {
|
|
||||||
c = color.getIndex();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
c = get_current_palette()->findBestfit(
|
|
||||||
color.getRed(),
|
|
||||||
color.getGreen(),
|
|
||||||
color.getBlue(),
|
|
||||||
colorTarget.isTransparent() ?
|
|
||||||
colorTarget.maskColor(): // Don't return the mask color
|
|
||||||
-1); // Return any color, we are in a background layer.
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "app/tools/shading_options.h"
|
#include "app/tools/shading_options.h"
|
||||||
#include "filters/neighboring_pixels.h"
|
#include "filters/neighboring_pixels.h"
|
||||||
#include "raster/palette.h"
|
#include "raster/palette.h"
|
||||||
|
#include "raster/raster.h"
|
||||||
#include "raster/rgbmap.h"
|
#include "raster/rgbmap.h"
|
||||||
#include "raster/sprite.h"
|
#include "raster/sprite.h"
|
||||||
|
|
||||||
@ -475,14 +476,27 @@ private:
|
|||||||
|
|
||||||
template<>
|
template<>
|
||||||
void ReplaceInkProcessing<RgbTraits>::processPixel(int x, int y) {
|
void ReplaceInkProcessing<RgbTraits>::processPixel(int x, int y) {
|
||||||
if (*m_srcAddress == m_color1)
|
color_t src = (*m_srcAddress);
|
||||||
*m_dstAddress = rgba_blend_normal(*m_srcAddress, m_color2, m_opacity);
|
|
||||||
|
// Colors (m_srcAddress and m_color1) match if:
|
||||||
|
// * They are both completelly transparent (alpha == 0)
|
||||||
|
// * Or they are not transparent and the RGB values are the same
|
||||||
|
if ((rgba_geta(src) == 0 && rgba_geta(m_color1) == 0) ||
|
||||||
|
(rgba_geta(src) > 0 && rgba_geta(m_color1) > 0 &&
|
||||||
|
((src & rgba_rgb_mask) == (m_color1 & rgba_rgb_mask)))) {
|
||||||
|
*m_dstAddress = rgba_blend_merge(src, m_color2, m_opacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void ReplaceInkProcessing<GrayscaleTraits>::processPixel(int x, int y) {
|
void ReplaceInkProcessing<GrayscaleTraits>::processPixel(int x, int y) {
|
||||||
if (*m_srcAddress == m_color1)
|
color_t src = (*m_srcAddress);
|
||||||
*m_dstAddress = graya_blend_normal(*m_srcAddress, m_color2, m_opacity);
|
|
||||||
|
if ((graya_geta(src) == 0 && graya_geta(m_color1) == 0) ||
|
||||||
|
(graya_geta(src) > 0 && graya_geta(m_color1) > 0 &&
|
||||||
|
((src & graya_v_mask) == (m_color1 & graya_v_mask)))) {
|
||||||
|
*m_dstAddress = graya_blend_merge(src, m_color2, m_opacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -109,6 +109,7 @@ int rgba_blend_merge(int back, int front, int opacity)
|
|||||||
int B_r, B_g, B_b, B_a;
|
int B_r, B_g, B_b, B_a;
|
||||||
int F_r, F_g, F_b, F_a;
|
int F_r, F_g, F_b, F_a;
|
||||||
int D_r, D_g, D_b, D_a;
|
int D_r, D_g, D_b, D_a;
|
||||||
|
int t;
|
||||||
|
|
||||||
B_r = rgba_getr(back);
|
B_r = rgba_getr(back);
|
||||||
B_g = rgba_getg(back);
|
B_g = rgba_getg(back);
|
||||||
@ -131,11 +132,13 @@ int rgba_blend_merge(int back, int front, int opacity)
|
|||||||
D_b = B_b;
|
D_b = B_b;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
D_r = B_r + (F_r-B_r) * opacity / 255;
|
D_r = B_r + INT_MULT((F_r - B_r), opacity, t);
|
||||||
D_g = B_g + (F_g-B_g) * opacity / 255;
|
D_g = B_g + INT_MULT((F_g - B_g), opacity, t);
|
||||||
D_b = B_b + (F_b-B_b) * opacity / 255;
|
D_b = B_b + INT_MULT((F_b - B_b), opacity, t);
|
||||||
}
|
}
|
||||||
D_a = B_a + (F_a-B_a) * opacity / 255;
|
D_a = B_a + INT_MULT((F_a - B_a), opacity, t);
|
||||||
|
if (D_a == 0)
|
||||||
|
D_r = D_g = D_b = 0;
|
||||||
|
|
||||||
return rgba(D_r, D_g, D_b, D_a);
|
return rgba(D_r, D_g, D_b, D_a);
|
||||||
}
|
}
|
||||||
@ -274,6 +277,7 @@ int graya_blend_merge(int back, int front, int opacity)
|
|||||||
int B_k, B_a;
|
int B_k, B_a;
|
||||||
int F_k, F_a;
|
int F_k, F_a;
|
||||||
int D_k, D_a;
|
int D_k, D_a;
|
||||||
|
int t;
|
||||||
|
|
||||||
B_k = graya_getv(back);
|
B_k = graya_getv(back);
|
||||||
B_a = graya_geta(back);
|
B_a = graya_geta(back);
|
||||||
@ -288,9 +292,11 @@ int graya_blend_merge(int back, int front, int opacity)
|
|||||||
D_k = B_k;
|
D_k = B_k;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
D_k = B_k + (F_k-B_k) * opacity / 255;
|
D_k = B_k + INT_MULT((F_k-B_k), opacity, t);
|
||||||
}
|
}
|
||||||
D_a = B_a + (F_a-B_a) * opacity / 255;
|
D_a = B_a + INT_MULT((F_a-B_a), opacity, t);
|
||||||
|
if (D_a == 0)
|
||||||
|
D_k = 0;
|
||||||
|
|
||||||
return graya(D_k, D_a);
|
return graya(D_k, D_a);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user