Hello, May I suggest a small fix in the patch? I have attached the same patch with the proposed fixes, which are: - the declaration of 'alpha_combine' has no reason to be inside the same-name file; - however, this definition is missing before use in the other files (actually only "wraster.c", but that's the idea) which generate a dangerous warning (bug risk!)
To which I did this: - moved the declaration in "wraster.h" so it can be visible in the needed place; - added inclusion of this header in alpha_combine.c to report errors on declaration mismatch; - renamed the function to "RCombineAlpha" to have a name consistent with the other functions declared in the header. Regards, Christophe. ----- Mail d'origine ----- De: Rodolfo kix Garcia <[email protected]> À: [email protected] Envoyé: Sun, 15 Jan 2012 19:41:05 +0100 (CET) Objet: [PATCH] wrlib: Improvement in the alpha channel support. Hi, I wrote this patch based on the Debian bug patch described above. Please, I would like more people test it before apply it. Best Regards, kix. PS. Carlos, I think that you can apply this patch now (UTF-8 + No Line Wrapping)
From 33746405e285d71cf5e306a9cea00d91e0168092 Mon Sep 17 00:00:00 2001 From: Christophe CURIS <[email protected]> Date: Sun, 15 Jan 2012 20:45:54 +0100 Subject: [PATCH] wrlib: Improvement in the alpha channel support. There are some problems in the alpha channel support, as is reported at http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=72917 This patch add a new alpha_combine function, based on Gimp. This function is called when needed in the raster.c functions. This patch is based on the Brad Jorsch <[email protected]> patch for the 0.62.1-0.1 version. --- wrlib/Makefile.am | 1 + wrlib/alpha_combine.c | 68 +++++++++++++++++++++ wrlib/draw.c | 1 + wrlib/raster.c | 159 +++++++++++++++++++++---------------------------- wrlib/wraster.h | 3 + 5 files changed, 142 insertions(+), 90 deletions(-) create mode 100644 wrlib/alpha_combine.c diff --git a/wrlib/Makefile.am b/wrlib/Makefile.am index 6c6de3d..8dec1f6 100644 --- a/wrlib/Makefile.am +++ b/wrlib/Makefile.am @@ -20,6 +20,7 @@ include_HEADERS = wraster.h libwraster_la_SOURCES = \ raster.c \ + alpha_combine.c \ draw.c \ color.c \ load.c \ diff --git a/wrlib/alpha_combine.c b/wrlib/alpha_combine.c new file mode 100644 index 0000000..967c1f6 --- /dev/null +++ b/wrlib/alpha_combine.c @@ -0,0 +1,68 @@ +/* alpha_combine.c - Alpha channel combination, based on Gimp 1.1.24 + * + * Raster graphics library + * + * Copyright (c) 1997-2003 Alfredo K. Kojima + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "wraster.h" + +void RCombineAlpha(unsigned char *d, unsigned char *s, int s_has_alpha, + int width, int height, int dwi, int swi, int opacity) { + int x, y; + int t, sa; + int alpha; + float ratio, cratio; + + for (y=0; y<height; y++) { + for (x=0; x<width; x++) { + sa=s_has_alpha?*(s+3):255; + + if (opacity!=255) { + t = sa * opacity + 0x80; + sa = ((t>>8)+t)>>8; + } + + t = *(d+3) * (255-sa) + 0x80; + alpha = sa + (((t>>8)+t)>>8); + + if (sa==0 || alpha==0) { + ratio = 0; + cratio = 1.0; + } else if(sa == alpha) { + ratio = 1.0; + cratio = 0; + } else { + ratio = (float)sa / alpha; + cratio = 1.0 - ratio; + } + + *d = (int)*d * cratio + (int)*s * ratio; + s++; d++; + *d = (int)*d * cratio + (int)*s * ratio; + s++; d++; + *d = (int)*d * cratio + (int)*s * ratio; + s++; d++; + *d = alpha; + d++; + + if (s_has_alpha) s++; + } + d+=dwi; + s+=swi; + } +} diff --git a/wrlib/draw.c b/wrlib/draw.c index 87f2cad..071f016 100644 --- a/wrlib/draw.c +++ b/wrlib/draw.c @@ -143,6 +143,7 @@ static void operatePixel(RImage * image, int ofs, int operation, RColor * color) *sr = (((int)*sr * nalpha) + ((int)color->red * alpha)) / 256; *sg = (((int)*sg * nalpha) + ((int)color->green * alpha)) / 256; *sb = (((int)*sb * nalpha) + ((int)color->blue * alpha)) / 256; + *sa = alpha + ((int)*sa * nalpha) / 256; } break; case RAddOperation: diff --git a/wrlib/raster.c b/wrlib/raster.c index 188dd51..f01db84 100644 --- a/wrlib/raster.c +++ b/wrlib/raster.c @@ -171,7 +171,7 @@ void RCombineImages(RImage * image, RImage * src) *d++ = *s++; *d++ = *s++; *d++ = *s++; - d++; + *d++ = 255; } } } @@ -200,20 +200,7 @@ void RCombineImages(RImage * image, RImage * src) s++; } } else { - for (i = 0; i < image->height * image->width; i++) { - alpha = *(s + 3); - calpha = 255 - alpha; - *d = (((int)*d * calpha) + ((int)*s * alpha)) / 256; - d++; - s++; - *d = (((int)*d * calpha) + ((int)*s * alpha)) / 256; - d++; - s++; - *d = (((int)*d * calpha) + ((int)*s * alpha)) / 256; - d++; - s++; - *d++ |= *s++; - } + RCombineAlpha(d, s, 1, image->width, image->height, 0, 0, 255); } } } @@ -237,39 +224,25 @@ void RCombineImagesWithOpaqueness(RImage * image, RImage * src, int opaqueness) #define COP c_opaqueness if (!HAS_ALPHA(src)) { - int dalpha = HAS_ALPHA(image); - for (i = 0; i < image->width * image->height; i++) { - *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; - d++; - s++; - *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; - d++; - s++; - *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; - d++; - s++; - if (dalpha) { - d++; - } - } - } else { - int tmp; - if (!HAS_ALPHA(image)) { for (i = 0; i < image->width * image->height; i++) { - tmp = (*(s + 3) * opaqueness) / 256; - *d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256; + *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; d++; s++; - *d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256; + *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; d++; s++; - *d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256; + *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; d++; s++; - s++; } } else { + RCombineAlpha(d, s, 0, image->width, image->height, 0, 0, OP); + } + } else { + int tmp; + + if (!HAS_ALPHA(image)) { for (i = 0; i < image->width * image->height; i++) { tmp = (*(s + 3) * opaqueness) / 256; *d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256; @@ -281,10 +254,10 @@ void RCombineImagesWithOpaqueness(RImage * image, RImage * src, int opaqueness) *d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256; d++; s++; - *d |= tmp; - d++; s++; } + } else { + RCombineAlpha(d, s, 1, image->width, image->height, 0, 0, opaqueness); } } #undef OP @@ -360,7 +333,7 @@ void RCombineArea(RImage * image, RImage * src, int sx, int sy, unsigned width, *d++ = *s++; *d++ = *s++; *d++ = *s++; - d++; + *d++ = 255; } d += dwi; s += swi; @@ -379,25 +352,27 @@ void RCombineArea(RImage * image, RImage * src, int sx, int sy, unsigned width, d = image->data + (dy * (int)image->width + dx) * 3; } - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - alpha = *(s + 3); - calpha = 255 - alpha; - *d = (((int)*d * calpha) + ((int)*s * alpha)) / 256; - s++; - d++; - *d = (((int)*d * calpha) + ((int)*s * alpha)) / 256; - s++; - d++; - *d = (((int)*d * calpha) + ((int)*s * alpha)) / 256; - s++; - d++; - s++; - if (dalpha) + if (!dalpha) { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + alpha = *(s + 3); + calpha = 255 - alpha; + *d = (((int)*d * calpha) + ((int)*s * alpha)) / 256; + s++; d++; + *d = (((int)*d * calpha) + ((int)*s * alpha)) / 256; + s++; + d++; + *d = (((int)*d * calpha) + ((int)*s * alpha)) / 256; + s++; + d++; + s++; + } + d += dwi; + s += swi; } - d += dwi; - s += swi; + } else { + RCombineAlpha(d, s, 1, width, height, dwi, swi, 255); } } } @@ -502,22 +477,24 @@ RCombineAreaWithOpaqueness(RImage * image, RImage * src, int sx, int sy, s = src->data + (sy * src->width + sx) * 3; swi = (src->width - width) * 3; - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; - s++; - d++; - *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; - s++; - d++; - *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; - s++; - d++; - if (dalpha) + if (!dalpha) { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; + s++; d++; + *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; + s++; + d++; + *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; + s++; + d++; + } + d += dwi; + s += swi; } - d += dwi; - s += swi; + } else { + RCombineAlpha(d, s, 0, width, height, dwi, swi, OP); } } else { int tmp; @@ -525,24 +502,26 @@ RCombineAreaWithOpaqueness(RImage * image, RImage * src, int sx, int sy, s = src->data + (sy * src->width + sx) * 4; swi = (src->width - width) * 4; - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - tmp = (*(s + 3) * opaqueness) / 256; - *d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256; - d++; - s++; - *d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256; - d++; - s++; - *d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256; - d++; - s++; - s++; - if (dalpha) + if (!dalpha) { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + tmp = (*(s + 3) * opaqueness) / 256; + *d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256; + d++; + s++; + *d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256; + d++; + s++; + *d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256; d++; + s++; + s++; + } + d += dwi; + s += swi; } - d += dwi; - s += swi; + } else { + RCombineAlpha(d, s, 1, width, height, dwi, swi, OP); } } #undef OP @@ -627,12 +606,12 @@ RImage *RMakeCenteredImage(RImage * image, unsigned width, unsigned height, RCol int x, y, w, h, sx, sy; RImage *tmp; - tmp = RCreateImage(width, height, False); + tmp = RCreateImage(width, height, HAS_ALPHA(image)); if (!tmp) { return NULL; } - RClearImage(tmp, color); + RFillImage(tmp, color); if (image->height < height) { h = image->height; diff --git a/wrlib/wraster.h b/wrlib/wraster.h index 78bfc16..b55af32 100644 --- a/wrlib/wraster.h +++ b/wrlib/wraster.h @@ -356,6 +356,9 @@ void RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy, unsigned width, unsigned height, int dx, int dy, int opaqueness); +void RCombineAlpha(unsigned char *d, unsigned char *s, int s_has_alpha, + int width, int height, int dwi, int swi, int opacity); + RImage *RScaleImage(RImage *image, unsigned new_width, unsigned new_height); RImage *RSmoothScaleImage(RImage *src, unsigned new_width, -- 1.7.2.5
