1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 20:38:08 +01:00

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 <anomie@users.sourceforge.net>
patch for the 0.62.1-0.1 version.

[crmafra: v1 was sent by Rodolfo kix Garcia <kix@kix.es>]
This commit is contained in:
Christophe CURIS
2012-01-15 20:45:54 +01:00
committed by Carlos R. Mafra
parent e06b3005e8
commit 3ed409cbd0
5 changed files with 142 additions and 92 deletions

View File

@@ -20,6 +20,7 @@ include_HEADERS = wraster.h
libwraster_la_SOURCES = \ libwraster_la_SOURCES = \
raster.c \ raster.c \
alpha_combine.c \
draw.c \ draw.c \
color.c \ color.c \
load.c \ load.c \

66
wrlib/alpha_combine.c Normal file
View File

@@ -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<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;
}
}

View File

@@ -143,6 +143,7 @@ static void operatePixel(RImage * image, int ofs, int operation, RColor * color)
*sr = (((int)*sr * nalpha) + ((int)color->red * alpha)) / 256; *sr = (((int)*sr * nalpha) + ((int)color->red * alpha)) / 256;
*sg = (((int)*sg * nalpha) + ((int)color->green * alpha)) / 256; *sg = (((int)*sg * nalpha) + ((int)color->green * alpha)) / 256;
*sb = (((int)*sb * nalpha) + ((int)color->blue * alpha)) / 256; *sb = (((int)*sb * nalpha) + ((int)color->blue * alpha)) / 256;
*sa = alpha + ((int)*sa * nalpha) / 256;
} }
break; break;
case RAddOperation: case RAddOperation:

View File

@@ -171,7 +171,7 @@ void RCombineImages(RImage * image, RImage * src)
*d++ = *s++; *d++ = *s++;
*d++ = *s++; *d++ = *s++;
*d++ = *s++; *d++ = *s++;
d++; *d++ = 255;
} }
} }
} }
@@ -200,20 +200,7 @@ void RCombineImages(RImage * image, RImage * src)
s++; s++;
} }
} else { } else {
for (i = 0; i < image->height * image->width; i++) { RCombineAlpha(d, s, 1, image->width, image->height, 0, 0, 255);
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++;
}
} }
} }
} }
@@ -237,20 +224,20 @@ void RCombineImagesWithOpaqueness(RImage * image, RImage * src, int opaqueness)
#define COP c_opaqueness #define COP c_opaqueness
if (!HAS_ALPHA(src)) { if (!HAS_ALPHA(src)) {
int dalpha = HAS_ALPHA(image); if (!HAS_ALPHA(image)) {
for (i = 0; i < image->width * image->height; i++) { for (i = 0; i < image->width * image->height; i++) {
*d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; *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++; 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++;
} }
} else {
RCombineAlpha(d, s, 0, image->width, image->height, 0, 0, OP);
} }
} else { } else {
int tmp; int tmp;
@@ -270,21 +257,7 @@ void RCombineImagesWithOpaqueness(RImage * image, RImage * src, int opaqueness)
s++; s++;
} }
} else { } else {
for (i = 0; i < image->width * image->height; i++) { RCombineAlpha(d, s, 1, image->width, image->height, 0, 0, opaqueness);
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++;
*d |= tmp;
d++;
s++;
}
} }
} }
#undef OP #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++ = *s++;
*d++ = *s++; *d++ = *s++;
d++; *d++ = 255;
} }
d += dwi; d += dwi;
s += swi; 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; d = image->data + (dy * (int)image->width + dx) * 3;
} }
for (y = 0; y < height; y++) { if (!dalpha) {
for (x = 0; x < width; x++) { for (y = 0; y < height; y++) {
alpha = *(s + 3); for (x = 0; x < width; x++) {
calpha = 255 - alpha; alpha = *(s + 3);
*d = (((int)*d * calpha) + ((int)*s * alpha)) / 256; calpha = 255 - alpha;
s++; *d = (((int)*d * calpha) + ((int)*s * alpha)) / 256;
d++; s++;
*d = (((int)*d * calpha) + ((int)*s * alpha)) / 256;
s++;
d++;
*d = (((int)*d * calpha) + ((int)*s * alpha)) / 256;
s++;
d++;
s++;
if (dalpha)
d++; 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; } else {
s += swi; 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; s = src->data + (sy * src->width + sx) * 3;
swi = (src->width - width) * 3; swi = (src->width - width) * 3;
for (y = 0; y < height; y++) { if (!dalpha) {
for (x = 0; x < width; x++) { for (y = 0; y < height; y++) {
*d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256; for (x = 0; x < width; x++) {
s++; *d = (((int)*d * (int)COP) + ((int)*s * (int)OP)) / 256;
d++; s++;
*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)
d++; 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; } else {
s += swi; RCombineAlpha(d, s, 0, width, height, dwi, swi, OP);
} }
} else { } else {
int tmp; int tmp;
@@ -525,24 +502,26 @@ RCombineAreaWithOpaqueness(RImage * image, RImage * src, int sx, int sy,
s = src->data + (sy * src->width + sx) * 4; s = src->data + (sy * src->width + sx) * 4;
swi = (src->width - width) * 4; swi = (src->width - width) * 4;
for (y = 0; y < height; y++) { if (!dalpha) {
for (x = 0; x < width; x++) { for (y = 0; y < height; y++) {
tmp = (*(s + 3) * opaqueness) / 256; for (x = 0; x < width; x++) {
*d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256; tmp = (*(s + 3) * opaqueness) / 256;
d++; *d = (((int)*d * (255 - tmp)) + ((int)*s * tmp)) / 256;
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)
d++; 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; } else {
s += swi; RCombineAlpha(d, s, 1, width, height, dwi, swi, OP);
} }
} }
#undef OP #undef OP
@@ -627,12 +606,12 @@ RImage *RMakeCenteredImage(RImage * image, unsigned width, unsigned height, RCol
int x, y, w, h, sx, sy; int x, y, w, h, sx, sy;
RImage *tmp; RImage *tmp;
tmp = RCreateImage(width, height, False); tmp = RCreateImage(width, height, HAS_ALPHA(image));
if (!tmp) { if (!tmp) {
return NULL; return NULL;
} }
RClearImage(tmp, color); RFillImage(tmp, color);
if (image->height < height) { if (image->height < height) {
h = image->height; h = image->height;

View File

@@ -356,6 +356,9 @@ void RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
unsigned width, unsigned height, int dx, int dy, unsigned width, unsigned height, int dx, int dy,
int opaqueness); 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 *RScaleImage(RImage *image, unsigned new_width, unsigned new_height);
RImage *RSmoothScaleImage(RImage *src, unsigned new_width, RImage *RSmoothScaleImage(RImage *src, unsigned new_width,