libtthimage/Lib/alpha.c
2022-10-28 05:07:32 +02:00

298 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 la...
03Fev14: ... please wait more ...
04Oct22: on the way, stay tuned.
*/
#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' !
*/
/*::------------------------------------------------------------------::*/