From c4ca69d3fa84dca98dce71c7a71b61413d6be165 Mon Sep 17 00:00:00 2001
From: scuri
Date: Tue, 27 Oct 2009 19:45:36 +0000
Subject: Fixed: compositing in IMAGERGB when canvas has a semi-transparent
alpha channel and a color with semi transparent alpha are used.
---
html/en/func/attributes.html | 4 ++--
html/en/func/color.html | 9 +++++----
html/en/history.html | 5 ++++-
src/drv/cdirgb.c | 35 ++++++++++++++++++++---------------
4 files changed, 31 insertions(+), 22 deletions(-)
diff --git a/html/en/func/attributes.html b/html/en/func/attributes.html
index 60768e4..984af01 100644
--- a/html/en/func/attributes.html
+++ b/html/en/func/attributes.html
@@ -17,7 +17,7 @@ canvas:SetForeground(color: lightuserdata) [in Lua]
color is used in all primitives (lines, areas, marks and text). Default value:
CD_BLACK. Value CD_QUERY simply returns the
current value.
- Notice that CD_QUERY conflicts with color RGBA=(255,255,255,255) (full
+
Notice that CD_QUERY conflicts with color RGBA=(255,255,255,0) (full
transparent white). Use SetForeground to avoid the
conflict. See also Color Coding.
long int cdCanvasBackground(cdCanvas* canvas, long int color); [in C]
@@ -31,7 +31,7 @@ canvas:SetBackground(color: lightuserdata) [in Lua]
background color only makes sense for Clear and for
primitives affected by the background opacity attribute. Default value: CD_WHITE.
Value CD_QUERY simply returns the current value.
- Notice that CD_QUERY conflicts with color RGBA=(255,255,255,255) (full
+
Notice that CD_QUERY conflicts with color RGBA=(255,255,255,0) (full
transparent white). Use SetBackground to avoid the
conflict. See also Color Coding.
int cdCanvasWriteMode(cdCanvas* canvas, int mode); [in C]
diff --git a/html/en/func/color.html b/html/en/func/color.html
index 9ec9928..8efd8a4 100644
--- a/html/en/func/color.html
+++ b/html/en/func/color.html
@@ -52,12 +52,13 @@ cd.DecodeColor(color: lightuserdata) -> (r, g, b: number) [in Lua]
cd.EncodeAlpha(color: lightuserdata, alpha: number) -> (color: lightuserdata) [in Lua]
Returns the given color coded with the alpha information. ATENTION: At the
- moment only the Win32 with GDI+ and the IMAGERGB drivers support alpha
- components in color coding. Se in Windows Using
- GDI+ Base Driver and IMAGERGB driver. The
+ moment only the Win32 with GDI+, the
+ XRender and the IMAGERGB
+ drivers support alpha components in color coding. The
internal representation of the component is inverted, because the default value
must be 0 and opaque for backward compatibility, so you should use the cdDecodeAlpha
- function ot the cdAlpha macro to retrieve the alpha component.
+ function or the cdAlpha macro to retrieve the alpha component.
+ 0 is transparent, 255 is opaque.
unsigned char cdDecodeAlpha(long int color) [in C]
cd.DecodeAlpha(color: lightuserdata) -> (a: number) [in Lua]
diff --git a/html/en/history.html b/html/en/history.html
index 8dd485a..81db388 100644
--- a/html/en/history.html
+++ b/html/en/history.html
@@ -19,7 +19,7 @@
History of Changes
-CVS (23/Oct/2009)
+CVS (27/Oct/2009)
- Changed:
Freetype updated to version 2.3.11.
@@ -37,6 +37,9 @@
objects in Lua.
- Fixed: CanvasText
for WD when using text with multiple lines.
+ - Fixed: compositing in IMAGERGB when
+ canvas has a semi-transparent alpha channel and a color with semi transparent alpha
+ are used.
diff --git a/src/drv/cdirgb.c b/src/drv/cdirgb.c
index 7f6f64b..d623abc 100644
--- a/src/drv/cdirgb.c
+++ b/src/drv/cdirgb.c
@@ -56,13 +56,13 @@ struct _cdCtxCanvas
#define _sNormX(_ctxcanvas, _x) (_x < 0? 0: _x < _ctxcanvas->canvas->w? _x: _ctxcanvas->canvas->w-1)
#define _sNormY(_ctxcanvas, _y) (_y < 0? 0: _y < _ctxcanvas->canvas->h? _y: _ctxcanvas->canvas->h-1)
-#define RGB_COMPOSE(_SRC, _SRC_ALPHA, _DST, _TMP_MULTI, _TMP_ALPHA) (unsigned char)(((_SRC_ALPHA)*(_SRC) + (_TMP_MULTI)*(_DST)) / (_TMP_ALPHA))
+#define RGB_COMPOSE_OVER(_SRC, _SRC_ALPHA, _DST, _TMP_MULTI, _TMP_ALPHA) (unsigned char)(((_SRC_ALPHA)*(_SRC) + (_TMP_MULTI)*(_DST)) / (_TMP_ALPHA))
#define RGBA_COLOR_COMBINE(_ctxcanvas, _pdst_red, _pdst_green, _pdst_blue, _pdst_alpha, _src_red, _src_green, _src_blue, _src_alpha) \
{ \
unsigned char _tmp_red = 0, _tmp_green = 0, _tmp_blue = 0; \
\
- if (_pdst_alpha) /* (_pdst_alpha != NULL) */ \
+ if (_pdst_alpha) /* destiny has alpha */ \
{ \
if (_src_alpha != 255) /* some transparency */ \
{ \
@@ -84,12 +84,17 @@ struct _cdCtxCanvas
} \
else /* (0<*_pdst_alpha<255 && 0<_src_alpha<255) destiny and source are semi-transparent */ \
{ \
- /* Closed Compositing Formulas for SRC over DST, Colors Not Premultiplied by Alpha: */ \
+ /* Closed Compositing SRC over DST (see smith95a.pdf) */ \
+ /* Colors NOT Premultiplied by Alpha */ \
+ /* DST = SRC * SRC_ALPHA + DST * DST_ALPHA * (1 - SRC_ALPHA) */ \
+ /* DST_ALPHA = SRC_ALPHA + DST_ALPHA * (1 - SRC_ALPHA) */ \
+ /* DST /= DST_ALPHA */ \
int _tmp_multi = *_pdst_alpha * (255 - _src_alpha); \
- int _tmp_alpha = _src_alpha + _tmp_multi; \
- _tmp_red = RGB_COMPOSE(_src_red, _src_alpha, *_pdst_red, _tmp_multi, _tmp_alpha); \
- _tmp_green = RGB_COMPOSE(_src_green, _src_alpha, *_pdst_green, _tmp_multi, _tmp_alpha); \
- _tmp_blue = RGB_COMPOSE(_src_blue, _src_alpha, *_pdst_blue, _tmp_multi, _tmp_alpha); \
+ int _tmp_src_alpha = _src_alpha*255; \
+ int _tmp_alpha = _tmp_src_alpha + _tmp_multi; \
+ _tmp_red = RGB_COMPOSE_OVER(_src_red, _tmp_src_alpha, *_pdst_red, _tmp_multi, _tmp_alpha); \
+ _tmp_green = RGB_COMPOSE_OVER(_src_green, _tmp_src_alpha, *_pdst_green, _tmp_multi, _tmp_alpha); \
+ _tmp_blue = RGB_COMPOSE_OVER(_src_blue, _tmp_src_alpha, *_pdst_blue, _tmp_multi, _tmp_alpha); \
*_pdst_alpha = (unsigned char)(_tmp_alpha / 255); \
} \
} \
@@ -109,7 +114,7 @@ struct _cdCtxCanvas
*_pdst_alpha = (unsigned char)255; /* set destiny as opaque */ \
} \
} \
- else /* (_pdst_alpha == NULL) */ \
+ else /* destiny does NOT have alpha */ \
{ \
if (_src_alpha != 255) /* source has some transparency */ \
{ \
@@ -147,9 +152,9 @@ struct _cdCtxCanvas
*_pdst_blue ^= _tmp_blue; \
break; \
case CD_NOT_XOR: \
- *_pdst_red = (unsigned char)~(_tmp_red ^ *_pdst_red); \
- *_pdst_green = (unsigned char)~(_tmp_green ^ *_pdst_green); \
- *_pdst_blue = (unsigned char)~(_tmp_blue ^ *_pdst_blue); \
+ *_pdst_red = (unsigned char)~(_tmp_red ^ *_pdst_red); \
+ *_pdst_green = (unsigned char)~(_tmp_green ^ *_pdst_green); \
+ *_pdst_blue = (unsigned char)~(_tmp_blue ^ *_pdst_blue); \
break; \
} \
}
@@ -406,7 +411,7 @@ static void cdclear(cdCtxCanvas* ctxcanvas)
memset(ctxcanvas->red, cdRed(ctxcanvas->canvas->background), size);
memset(ctxcanvas->green, cdGreen(ctxcanvas->canvas->background), size);
memset(ctxcanvas->blue, cdBlue(ctxcanvas->canvas->background), size);
- if (ctxcanvas->alpha) memset(ctxcanvas->alpha, cdAlpha(ctxcanvas->canvas->background), size);
+ if (ctxcanvas->alpha) memset(ctxcanvas->alpha, cdAlpha(ctxcanvas->canvas->background), size); /* here is the normal alpha coding */
}
static void irgPostProcessIntersect(unsigned char* clip, int size)
@@ -1525,8 +1530,8 @@ static cdCtxImage* cdcreateimage(cdCtxCanvas* ctxcanvas, int w, int h)
if (ctxcanvas->alpha)
ctximage->alpha = ctximage->red + 3*size;
- memset(ctximage->red, 0xFF, 3*size);
- if (ctximage->alpha) memset(ctximage->alpha, 0, size); /* transparent */
+ memset(ctximage->red, 0xFF, 3*size); /* white */
+ if (ctximage->alpha) memset(ctximage->alpha, 0, size); /* transparent, this is the normal alpha coding */
return ctximage;
}
@@ -1927,7 +1932,7 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data)
ctxcanvas->alpha = ctxcanvas->red + 3*size;
memset(ctxcanvas->red, 0xFF, 3*size); /* white */
- if (ctxcanvas->alpha) memset(ctxcanvas->alpha, 0, size); /* transparent */
+ if (ctxcanvas->alpha) memset(ctxcanvas->alpha, 0, size); /* transparent, this is the normal alpha coding */
}
ctxcanvas->clip = (unsigned char*)malloc(w*h);
--
cgit v1.2.3