summaryrefslogtreecommitdiff
path: root/ext/gd/libgd/gd.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/gd/libgd/gd.c')
-rw-r--r--ext/gd/libgd/gd.c115
1 files changed, 96 insertions, 19 deletions
diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c
index 364b39e6ab..454f1bf30e 100644
--- a/ext/gd/libgd/gd.c
+++ b/ext/gd/libgd/gd.c
@@ -665,26 +665,28 @@ gdImageSetPixel (gdImagePtr im, int x, int y, int color)
gdImageTileApply (im, x, y);
break;
default:
- if (gdImageBoundsSafe (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;
+ if (gdImageBoundsSafe (im, x, y)) {
+ if (im->trueColor) {
+ switch( im->alphaBlendingFlag )
+ {
+ default:
+ case gdEffectReplace :
+ im->tpixels[y][x] = color;
+ break;
+ case gdEffectAlphaBlend :
+ im->tpixels[y][x] = gdAlphaBlend(im->tpixels[y][x], color);
+ break;
+ case gdEffectNormal :
+ im->tpixels[y][x] = gdFullAlphaBlend(im->tpixels[y][x], color);
+ break;
+ case gdEffectOverlay :
+ im->tpixels[y][x] = gdLayerOverlay(im->tpixels[y][x], color);
+ break;
+ }
+ } else {
+ im->pixels[y][x] = color;
}
- }
- else
- {
- im->pixels[y][x] = color;
- }
- }
+ }
break;
}
}
@@ -2574,3 +2576,78 @@ gdImageSaveAlpha (gdImagePtr im, int saveAlphaArg)
{
im->saveAlphaFlag = saveAlphaArg;
}
+
+int
+gdFullAlphaBlend (int dst, int src)
+{
+ int a1, a2;
+ a1 = gdAlphaTransparent - gdTrueColorGetAlpha(src);
+ a2 = gdAlphaTransparent - gdTrueColorGetAlpha(dst);
+
+ return ( ((gdAlphaTransparent - ((a1+a2)-(a1*a2/gdAlphaMax))) << 24) +
+ (gdAlphaBlendColor( gdTrueColorGetRed(src), gdTrueColorGetRed(dst), a1, a2 ) << 16) +
+ (gdAlphaBlendColor( gdTrueColorGetGreen(src), gdTrueColorGetGreen(dst), a1, a2 ) << 8) +
+ (gdAlphaBlendColor( gdTrueColorGetBlue(src), gdTrueColorGetBlue(dst), a1, a2 ))
+ );
+}
+
+int
+gdAlphaBlendColor( int b1, int b2, int a1, int a2 )
+{
+ int c;
+ int w;
+
+ /* deal with special cases */
+
+ if( (gdAlphaMax == a1) || (0 == a2) ) {
+ /* the back pixel can't be seen */
+ return b1;
+ } else if(0 == a1) {
+ /* the front pixel can't be seen */
+ return b2;
+ } else if(gdAlphaMax == a2) {
+ /* the back pixel is opaque */
+ return ( a1 * b1 + ( gdAlphaMax - a1 ) * b2 ) / gdAlphaMax;
+ }
+
+ /* the general case */
+ w = ( a1 * ( gdAlphaMax - a2 ) / ( gdAlphaMax - a1 * a2 / gdAlphaMax ) * b1 + \
+ a2 * ( gdAlphaMax - a1 ) / ( gdAlphaMax - a1 * a2 / gdAlphaMax ) * b2 ) / gdAlphaMax;
+ c = (a2 * b2 + ( gdAlphaMax - a2 ) * w ) / gdAlphaMax;
+ return ( a1 * b1 + ( gdAlphaMax - a1 ) * c ) / gdAlphaMax;
+}
+
+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 ))
+ );
+}
+
+int
+gdAlphaOverlayColor( int src, int dst, int max )
+{
+ /* this function implements the algorithm
+ *
+ * for dst[rgb] < 0.5,
+ * c[rgb] = 2.src[rgb].dst[rgb]
+ * and for dst[rgb] > 0.5,
+ * c[rgb] = -2.src[rgb].dst[rgb] + 2.dst[rgb] + 2.src[rgb] - 1
+ *
+ */
+
+ 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;
+ }
+}