297 lines
6.5 KiB
C
297 lines
6.5 KiB
C
/*
|
|
alpha.c
|
|
-------
|
|
Various transparency operations, aka "alpha channel ops"
|
|
|
|
--------------------------------------
|
|
Et c,a va me forcer a installer libpng
|
|
--------------------------------------
|
|
15May01: on attend toujours libPNG
|
|
07Dec01: pfeue, libPNG toujours pas là...
|
|
03Fev14: ... please wait more ...
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "../tthimage.h"
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
int
|
|
Image_RGBA_over_RGB(Image_Desc *rgba, Image_Desc *src, Image_Desc *dst)
|
|
{
|
|
int x, y;
|
|
int rs, gs, bs, rm, gm, bm, am, r, g, b;
|
|
int foo;
|
|
|
|
if (rgba->type != IMAGE_RGBA)
|
|
{
|
|
fprintf(stderr, "RGBA over RGB: image is not RGBA (%d)\n", rgba->type);
|
|
return IMAGE_BAD_TYPE;
|
|
}
|
|
if ( (foo=Image_compare_desc(rgba, src)) )
|
|
{
|
|
fprintf(stderr, "RGBA over RGB: err on sources: %s\n",
|
|
Image_err2str(foo));
|
|
return foo;
|
|
}
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "RGBA/RGB types: %d %d %d\n", rgba->type, src->type, dst->type);
|
|
#endif
|
|
|
|
for (y=0; y<src->height; y++)
|
|
{
|
|
for (x=0; x<src->width; x++)
|
|
{
|
|
rs = (src->Rpix[y])[x];
|
|
gs = (src->Gpix[y])[x];
|
|
bs = (src->Bpix[y])[x];
|
|
Image_getRGBA(rgba, x, y, &rm, &gm, &bm, &am);
|
|
|
|
r = ((rs*(255-am)) + (rm*am)) / 256;
|
|
g = ((gs*(255-am)) + (gm*am)) / 256;
|
|
b = ((bs*(255-am)) + (bm*am)) / 256;
|
|
|
|
Image_plotRGB(dst, x, y, r, g, b);
|
|
}
|
|
}
|
|
|
|
return FUNC_IS_BETA;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* this function do some dirty things with the internals
|
|
* of the library. And you got here a 'secret' prototype.
|
|
*/
|
|
int Image_alloc_pixels(unsigned char ***pix, int w, int h);
|
|
/*
|
|
* Ahem. You, if you use this prototype, you are going
|
|
* to be a big laM3r. Don't do it. You have be warned.
|
|
*/
|
|
int
|
|
Image_add_alpha_channel(Image_Desc *img, int value)
|
|
{
|
|
uint8_t **tmp_ptr;
|
|
int foo;
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "Add Alpha Channel v=%d to Img %p\n", value, img);
|
|
#endif
|
|
|
|
if (img == NULL)
|
|
{
|
|
fprintf(stderr, "Add Alpha Channel: ZarWa, 'img' is NULL\n");
|
|
return NULL_DESCRIPTOR;
|
|
}
|
|
|
|
if (img->Apix != NULL)
|
|
{
|
|
fprintf(stderr, "Image %p already has an alpha channel\n", img);
|
|
return VERY_STRANGE;
|
|
}
|
|
|
|
if (img->type != IMAGE_RGB)
|
|
{
|
|
fprintf(stderr, "Image %p is not RGB.\n", img);
|
|
return VERY_STRANGE;
|
|
}
|
|
|
|
foo = Image_alloc_pixels(&tmp_ptr, img->width, img->height);
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "creation channel alpha foo=%d ptr=%p\n", foo, tmp_ptr);
|
|
#endif
|
|
|
|
/* Yo, le plan memoire est disponible, on y poke la 'value' */
|
|
for (foo=0; foo<img->height; foo++) {
|
|
memset(tmp_ptr[foo], value, img->width);
|
|
}
|
|
|
|
/* and now, we update the image descriptor */
|
|
img->type = IMAGE_RGBA;
|
|
img->nb_planes = 4;
|
|
img->Apix = tmp_ptr;
|
|
img->modified = 1;
|
|
|
|
#if DEBUG_LEVEL
|
|
Image_dump_descriptor(img, "apres creation canal Alpha");
|
|
#endif
|
|
|
|
return OLL_KORRECT;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
int
|
|
Image_kill_alpha_channel(Image_Desc *img)
|
|
{
|
|
int line;
|
|
|
|
#if DEBUG_LEVEL
|
|
Image_dump_descriptor(img, "Killing Alpha Channel");
|
|
#endif
|
|
|
|
if (img->type != IMAGE_RGBA) {
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "Kill Alpha Channel: bad type %d\n", img->type);
|
|
#endif
|
|
return VERY_STRANGE;
|
|
}
|
|
|
|
if (img->nb_planes != 4) {
|
|
fprintf(stderr, "Kill Alpha Channel: bad planes number %d\n",
|
|
img->nb_planes);
|
|
return VERY_STRANGE;
|
|
}
|
|
|
|
if (img->Apix == NULL) {
|
|
fprintf(stderr, "Kill Alpha Channel: _no_ alpha channel in %p\n", img);
|
|
return NO_ALPHA_CHANNEL;
|
|
}
|
|
|
|
for (line=0; line<img->height; line++)
|
|
if (img->Apix[line] != NULL) free(img->Apix[line]);
|
|
|
|
free(img->Apix); img->Apix = NULL;
|
|
img->nb_planes = 3;
|
|
img->type = IMAGE_RGB;
|
|
img->modified = 1;
|
|
|
|
return OLL_KORRECT;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
int
|
|
Image_map_alpha_on_img(Image_Desc *img)
|
|
{
|
|
register int pix;
|
|
int x, y;
|
|
|
|
if (img->Apix == NULL)
|
|
{
|
|
fprintf(stderr, "%s : %p have no alpha channel.\n", __func__, img);
|
|
return FULL_NUCKED;
|
|
}
|
|
|
|
if (img->type != IMAGE_RGBA)
|
|
{
|
|
fprintf(stderr, "%s : %p is not an RGBA image.\n", __func__, img);
|
|
return FULL_NUCKED;
|
|
}
|
|
|
|
for (y=0; y<img->height; y++)
|
|
{
|
|
for (x=0; x<img->width; x++)
|
|
{
|
|
pix = (img->Rpix[y])[x] * (img->Apix[y])[x];
|
|
(img->Rpix[y])[x] = pix / 256;
|
|
|
|
pix = (img->Gpix[y])[x] * (img->Apix[y])[x];
|
|
(img->Gpix[y])[x] = pix / 256;
|
|
|
|
pix = (img->Bpix[y])[x] * (img->Apix[y])[x];
|
|
(img->Bpix[y])[x] = pix / 256;
|
|
}
|
|
}
|
|
|
|
return OLL_KORRECT;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* given two levels by RGB component, this func build an alpha
|
|
* binary mask where pixels in the 3 RGB intervals have the v1
|
|
* alpha value, and all others have the v2 alpha value.
|
|
*/
|
|
int
|
|
Image_alpha_op_0(Image_Desc *src, Image_Desc *dst, int v1, int v2,
|
|
int rb, int rt, int gb, int gt, int bb, int bt,
|
|
int param)
|
|
{
|
|
int x, y, foo, r, g, b;
|
|
int c1, c2;
|
|
|
|
/*
|
|
XXX NO SAFETY CONTROLS ?
|
|
*/
|
|
if (dst->Apix == NULL)
|
|
{
|
|
fprintf(stderr, "Alpha op 0: dst %p have no alpha channel.\n", dst);
|
|
return FULL_NUCKED;
|
|
}
|
|
if (0 != param)
|
|
{
|
|
fprintf(stderr, "%s: parameter must be 0\n", __func__);
|
|
}
|
|
|
|
c1 = c2 = 0;
|
|
for (y=0; y<src->height; y++)
|
|
{
|
|
for (x=0; x<src->width; x++)
|
|
{
|
|
foo = Image_getRGB(src, x, y, &r, &g, &b);
|
|
|
|
if ( (r > rb && r < rt) ||
|
|
(g > gb && g < gt) ||
|
|
(b > bb && b < bt) )
|
|
{
|
|
dst->Apix[y][x] = v1;
|
|
c1++;
|
|
}
|
|
else
|
|
{
|
|
dst->Apix[y][x] = v2;
|
|
c2++;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "Alpha op 0: c1=%d c2=%d\n", c1, c2);
|
|
#endif
|
|
|
|
return FUNC_IS_BETA;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* New: 16 Oct 2001.
|
|
*/
|
|
int Image_copy_component_to_alpha(Image_Desc *img, char component)
|
|
{
|
|
int x, y;
|
|
|
|
if (img->type != IMAGE_RGBA)
|
|
{
|
|
fprintf(stderr, "Alpha copy comp: %p is not an RGBA image.\n", img);
|
|
return NO_ALPHA_CHANNEL;
|
|
}
|
|
|
|
if (img->Apix == NULL)
|
|
{
|
|
fprintf(stderr, "Alpha copy comp: %p have no alpha channel.\n", img);
|
|
return NO_ALPHA_CHANNEL;
|
|
}
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "moving component '%c' to alpha channel of %p\n",
|
|
component, img);
|
|
#endif
|
|
|
|
for (y=0; y<img->height; y++) {
|
|
for (x=0; x<img->width; x++) {
|
|
switch (component)
|
|
{
|
|
case 'r': case 'R':
|
|
img->Apix[y][x] = img->Rpix[y][x]; break;
|
|
case 'g': case 'G':
|
|
img->Apix[y][x] = img->Gpix[y][x]; break;
|
|
case 'b': case 'B':
|
|
img->Apix[y][x] = img->Bpix[y][x]; break;
|
|
}
|
|
}
|
|
}
|
|
return FUNC_IS_ALPHA;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* bon, et maintenant, qu'est-ce qu'on invente ?
|
|
* ben 'alpha2.c' !
|
|
*/
|
|
/*::------------------------------------------------------------------::*/
|