Add overlay and multiply effects to gdImageSetPixel

master
Tim Toohey 2014-04-21 16:17:03 +10:00
parent 4b86e06937
commit b39f92b195
2 changed files with 70 additions and 6 deletions

View File

@ -1061,10 +1061,20 @@ BGD_DECLARE(void) gdImageSetPixel (gdImagePtr im, int x, int y, int color)
default:
if (gdImageBoundsSafeMacro (im, x, y)) {
if (im->trueColor) {
if (im->alphaBlendingFlag) {
im->tpixels[y][x] = gdAlphaBlend (im->tpixels[y][x], color);
} else {
im->tpixels[y][x] = color;
switch (im->alphaBlendingFlag) {
default:
case gdEffectReplace:
im->tpixels[y][x] = color;
break;
case gdEffectNormal:
im->tpixels[y][x] = gdAlphaBlend(im->tpixels[y][x], color);
break;
case gdEffectOverlay :
im->tpixels[y][x] = gdLayerOverlay(im->tpixels[y][x], color);
break;
case gdEffectMultiply :
im->tpixels[y][x] = gdLayerMultiply(im->tpixels[y][x], color);
break;
}
} else {
im->pixels[y][x] = color;
@ -3330,6 +3340,55 @@ BGD_DECLARE(int) gdAlphaBlend (int dst, int src)
return ((alpha << 24) + (red << 16) + (green << 8) + blue);
}
static int gdAlphaOverlayColor (int src, int dst, int max );
BGD_DECLARE(int) gdLayerOverlay (int dst, int src)
{
int a1, a2;
a1 = gdAlphaMax - gdTrueColorGetAlpha(dst);
a2 = gdAlphaMax - gdTrueColorGetAlpha(src);
return ( ((gdAlphaMax - a1*a2/gdAlphaMax) << 24) +
(gdAlphaOverlayColor( gdTrueColorGetRed(src), gdTrueColorGetRed(dst), gdRedMax ) << 16) +
(gdAlphaOverlayColor( gdTrueColorGetGreen(src), gdTrueColorGetGreen(dst), gdGreenMax ) << 8) +
(gdAlphaOverlayColor( gdTrueColorGetBlue(src), gdTrueColorGetBlue(dst), gdBlueMax ))
);
}
/* Apply 'overlay' effect - background pixels are colourised by the foreground colour */
static int gdAlphaOverlayColor (int src, int dst, int max )
{
dst = dst << 1;
if( dst > max ) {
/* in the "light" zone */
return dst + (src << 1) - (dst * src / max) - max;
} else {
/* in the "dark" zone */
return dst * src / max;
}
}
/* Apply 'multiply' effect */
BGD_DECLARE(int) gdLayerMultiply (int dst, int src)
{
int a1, a2, r1, r2, g1, g2, b1, b2;
a1 = gdAlphaMax - gdTrueColorGetAlpha(src);
a2 = gdAlphaMax - gdTrueColorGetAlpha(dst);
r1 = gdRedMax - (a1 * (gdRedMax - gdTrueColorGetRed(src))) / gdAlphaMax;
r2 = gdRedMax - (a2 * (gdRedMax - gdTrueColorGetRed(dst))) / gdAlphaMax;
g1 = gdGreenMax - (a1 * (gdGreenMax - gdTrueColorGetGreen(src))) / gdAlphaMax;
g2 = gdGreenMax - (a2 * (gdGreenMax - gdTrueColorGetGreen(dst))) / gdAlphaMax;
b1 = gdBlueMax - (a1 * (gdBlueMax - gdTrueColorGetBlue(src))) / gdAlphaMax;
b2 = gdBlueMax - (a2 * (gdBlueMax - gdTrueColorGetBlue(dst))) / gdAlphaMax ;
a1 = gdAlphaMax - a1;
a2 = gdAlphaMax - a2;
return ( ((a1*a2/gdAlphaMax) << 24) +
((r1*r2/gdRedMax) << 16) +
((g1*g2/gdGreenMax) << 8) +
((b1*b2/gdBlueMax))
);
}
BGD_DECLARE(void) gdImageAlphaBlending (gdImagePtr im, int alphaBlendingArg)
{
im->alphaBlendingFlag = alphaBlendingArg;

View File

@ -139,6 +139,7 @@ extern "C" {
#define gdEffectAlphaBlend 1
#define gdEffectNormal 2
#define gdEffectOverlay 3
#define gdEffectMultiply 4
#define GD_TRUE 1
#define GD_FALSE 0
@ -154,7 +155,9 @@ extern "C" {
The resulting color is opaque. */
BGD_DECLARE(int) gdAlphaBlend (int dest, int src);
BGD_DECLARE(int) gdLayerOverlay (int dest, int src);
BGD_DECLARE(int) gdLayerMultiply (int dest, int src);
enum gdPaletteQuantizationMethod {
GD_QUANT_DEFAULT = 0,
GD_QUANT_JQUANT = 1, /* libjpeg's old median cut. Fast, but only uses 16-bit color. */
@ -565,7 +568,9 @@ BGD_DECLARE(void) gdImageDestroy (gdImagePtr im);
alpha channel value of 'color'; default is to overwrite.
Tiling and line styling are also implemented
here. All other gd drawing functions pass through this call,
allowing for many useful effects. */
allowing for many useful effects.
Overlay and multiply effects are used when gdImageAlphaBlending
is passed gdEffectOverlay and gdEffectMultiply */
BGD_DECLARE(void) gdImageSetPixel (gdImagePtr im, int x, int y, int color);
/* FreeType 2 text output with hook to extra flags */