From 3ed409cbd09193d4fa5609fccccfd5c7ddf5d534 Mon Sep 17 00:00:00 2001 From: Christophe CURIS 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 RCombineAlpha function, based on Gimp. This function is called when needed in the raster.c functions. This patch is based on the Brad Jorsch patch for the 0.62.1-0.1 version. [crmafra: v1 was sent by Rodolfo kix Garcia ] --- wrlib/Makefile.am | 1 + wrlib/alpha_combine.c | 66 +++++++++++++++++++++ wrlib/draw.c | 1 + wrlib/raster.c | 159 ++++++++++++++++++++++---------------------------- wrlib/wraster.h | 3 + 5 files changed, 140 insertions(+), 90 deletions(-) create mode 100644 wrlib/alpha_combine.c diff --git a/wrlib/Makefile.am b/wrlib/Makefile.am index 6c6de3d1..8dec1f65 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 00000000..e670d626 --- /dev/null +++ b/wrlib/alpha_combine.c @@ -0,0 +1,66 @@ +/* alpha_combine.c - Alpha channel combination, based on Gimp 1.1.24 + * The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * 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>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 87f2cad4..071f016a 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 188dd516..f01db848 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 78bfc168..b55af326 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, -- 2.11.4.GIT