--- ../gd-2.0.34-orig/gd.c Tue Feb 6 16:33:29 2007 +++ gd.c Sat Aug 18 15:22:53 2007 @@ -2202,6 +2202,66 @@ BGD_DECLARE(void) gdImageCopy (gdImagePt } } +/* + * Blend two true-colour images and optionally adjust the source image's + * alpha channel by opacity. Valid range for opacity is 0 to 100, where 0 + * means complete transparency (essentially a no-op) and 100 means copy + * the source image as-is (essentially calling gdImageCopy()). + * If either of the images is not true-colour, or the destination image + * does not have its alphaBlendingFlag set, we call gdImageCopyMerge() + * and return. + */ +BGD_DECLARE(void) +gdImageBlend(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, + int srcY, int w, int h, int opacity) +{ + int alpha, c, i, x, y; + float alpha_adj; + + /* Valid range for opacity is 0 to 100 */ + if (opacity >= 100) { + gdImageCopy(dst, src, dstX, dstY, srcX, srcY, w, h); + return; + } + else if (opacity <= 0) + return; /* Complete transparency; i.e., no-op. */ + /* + * We only handle the case where both images are true-colour and + * destination image has alpha-blending flag set. Otherwise, we + * simpley call gdImageCopyMerge(...) + */ + if (!dst->trueColor || !src->trueColor || !dst->alphaBlendingFlag) { + gdImageCopyMerge(dst, src, dstX, dstY, srcX, srcY, + w, h, opacity); + return; + } + alpha_adj = (100.0 - opacity) / 100.0; + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + c = gdImageGetPixel(src, srcX + x, srcY + y); + /* + * I am making an assumption that in true-colour + * images, there is no im->transparent, else we + * could use the following optimization: + * if (c == src->transparent) + * continue; + */ + alpha = (c >> 24) & 0xff; + if (alpha == gdAlphaTransparent) + continue; + /* + * XXX: Can gdAlphaTransparent and gdAlphaMax ever + * be different values? + */ + alpha += (gdAlphaMax - alpha) * alpha_adj; + if (alpha >= gdAlphaMax) + continue; + c = (c & 0x00ffffff) | (alpha << 24); + gdImageSetPixel(dst, dstX + x, dstY + y, c); + } + } +} + /* This function is a substitute for real alpha channel operations, so it doesn't pay attention to the alpha channel. */ BGD_DECLARE(void) gdImageCopyMerge (gdImagePtr dst, gdImagePtr src, int dstX, int dstY,