2022-06-26 02:23:53 +02:00
|
|
|
|
/*
|
2022-06-26 22:55:56 +02:00
|
|
|
|
fonctions de bases pour la librairie 'libtthimage'
|
|
|
|
|
--------------------------------------------------
|
2022-06-26 02:23:53 +02:00
|
|
|
|
|
|
|
|
|
(g) 1992,2003 - Thierry Boudet - aka Oulala
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2022-06-26 22:55:56 +02:00
|
|
|
|
#include "../tthimage.h"
|
2022-06-26 02:23:53 +02:00
|
|
|
|
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
2023-09-23 20:00:14 +02:00
|
|
|
|
void Image_print_version(int flag)
|
2022-06-26 02:23:53 +02:00
|
|
|
|
{
|
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
|
|
fflush(stdout);
|
2024-07-17 02:39:21 +02:00
|
|
|
|
fprintf(stderr, "-+- This is the `tthimage' library v%s (wtfyw 2024) tTh\n",
|
2022-06-26 02:23:53 +02:00
|
|
|
|
IMAGE_VERSION_STRING);
|
|
|
|
|
if (flag)
|
|
|
|
|
{
|
|
|
|
|
/* this information is only correct IF you touch image.c before
|
|
|
|
|
* running 'make' utility */
|
2023-09-23 20:00:14 +02:00
|
|
|
|
fprintf(stderr, " + compiled : %s, %s\n", __DATE__, __TIME__);
|
2022-06-26 02:23:53 +02:00
|
|
|
|
}
|
|
|
|
|
if (flag > 1)
|
|
|
|
|
{
|
2023-09-23 20:00:14 +02:00
|
|
|
|
fprintf(stderr, " + DESTDIR = %s\n", DESTDIR);
|
|
|
|
|
fprintf(stderr, " + SHAREDIR = %s\n", SHAREDIR);
|
|
|
|
|
fprintf(stderr, " + CC OPTS = %s\n", CC_OPTS);
|
2022-06-26 02:23:53 +02:00
|
|
|
|
}
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
|
|
|
|
|
/* OMFG, this is a gnuism ! */
|
|
|
|
|
if ( (ptr=getenv("MALLOC_CHECK_")) != NULL)
|
|
|
|
|
{
|
2022-06-26 22:55:56 +02:00
|
|
|
|
fprintf(stderr, "-+- libtthimage: malloc check is set to %s\n", ptr);
|
2022-06-26 02:23:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
|
fprintf(stderr,
|
2022-06-26 22:55:56 +02:00
|
|
|
|
"Warning! this version of libtthimage is compiled with DEBUG_LEVEL=%d\n",
|
2022-06-26 02:23:53 +02:00
|
|
|
|
DEBUG_LEVEL);
|
|
|
|
|
#if FORCE_ABORT
|
2022-06-26 22:55:56 +02:00
|
|
|
|
fprintf(stderr, "Warning! this version of libtthimage is compiled with FORCE_ABORT!\n");
|
2022-06-26 02:23:53 +02:00
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/*
|
|
|
|
|
* This function create a new channel for an image.
|
|
|
|
|
* Before version 0.4.9 it was a private function, but
|
|
|
|
|
* the module 'alpha.c' need access to it.
|
|
|
|
|
*
|
|
|
|
|
* ... So I make it "semi-public" ... */
|
|
|
|
|
int Image_alloc_pixels(unsigned char ***pix, int w, int h);
|
|
|
|
|
/*
|
|
|
|
|
* pour le moment, pas de code retour en cas
|
|
|
|
|
* d'erreur, mais un exit(1) brutal.
|
|
|
|
|
*/
|
|
|
|
|
int Image_alloc_pixels(unsigned char ***pix, int w, int h)
|
|
|
|
|
{
|
|
|
|
|
int foo;
|
|
|
|
|
unsigned char **lignes, *ptr;
|
|
|
|
|
|
|
|
|
|
lignes = (unsigned char **)malloc(sizeof(unsigned char *) * h);
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
|
|
|
fprintf(stderr, " alloc pixels for plane @ %p -> %p\n", pix, lignes);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
*pix = lignes; /* setting the indirected return value here
|
|
|
|
|
so we can use 'lignes' in the loop. */
|
|
|
|
|
|
|
|
|
|
for (foo=0; foo<h; foo++)
|
|
|
|
|
{
|
|
|
|
|
if ((ptr=(unsigned char *)malloc(sizeof(unsigned char) * w))==NULL)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "%s: malloc failed for image line %d\n", __func__, foo);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
*lignes++ = ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/*
|
|
|
|
|
* This function allocate an image and return a pointer
|
|
|
|
|
* on the structure who describe the image.
|
|
|
|
|
* - - - > don't "free" this pointer, please.
|
|
|
|
|
*/
|
|
|
|
|
Image_Desc *
|
|
|
|
|
Image_alloc(int width, int height, int type)
|
|
|
|
|
{
|
|
|
|
|
Image_Desc *header;
|
|
|
|
|
int foo;
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
|
|
|
fprintf(stderr, "allocation for an image %dx%d, type:%d\n",
|
|
|
|
|
width, height, type);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if ( (header=(Image_Desc *)calloc(sizeof(Image_Desc), 1)) == NULL )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Image_Alloc (%s) err malloc header\n", __FILE__);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
|
|
|
fprintf(stderr, " header is at @ %p\n", header);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
strcpy(header->name, "");
|
|
|
|
|
header->nb_planes = type;
|
|
|
|
|
header->width = width; header->height = height;
|
|
|
|
|
#if IMGCOMMENT
|
|
|
|
|
strcpy(header->comment, "* libimg is (dwtfywl) tontonTh 2022 *");
|
|
|
|
|
#else
|
|
|
|
|
/*
|
|
|
|
|
* The old 'Xv' image viewer does not like .TGA with a comment.
|
|
|
|
|
*/
|
|
|
|
|
strcpy(header->comment, "");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
header->type = type;
|
|
|
|
|
header->Rpix = header->Gpix = header->Bpix = header->Apix = NULL;
|
|
|
|
|
|
|
|
|
|
header->magic = MAGIC_OF_IMAGE;
|
|
|
|
|
|
|
|
|
|
header->nbcols = 0;
|
|
|
|
|
header->idx_palette = 0;
|
|
|
|
|
header->errmsg = header->modified = 0;
|
|
|
|
|
|
|
|
|
|
/* nouveau 18 Sept 2001 */
|
|
|
|
|
header->fx = header->fy = 0.0;
|
|
|
|
|
header->fw = (double)width;
|
|
|
|
|
header->fh = (double)height;
|
|
|
|
|
|
|
|
|
|
/* new 12 Nov 2001 - see 'turtle.c' */
|
|
|
|
|
header->rt = header->gt = header->bt = 42;
|
|
|
|
|
header->xt = (double)width / 2.0;
|
|
|
|
|
header->yt = (double)height / 2.0;
|
|
|
|
|
header->at = 0; /* canal alpha, 0 est-il la bonne valeur ? */
|
|
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case IMAGE_GREY:
|
|
|
|
|
Image_alloc_pixels(&header->Rpix, width, height);
|
|
|
|
|
for (foo=0; foo<256; foo++)
|
|
|
|
|
{
|
|
|
|
|
header->palette[0][foo] = foo;
|
|
|
|
|
header->palette[1][foo] = foo;
|
|
|
|
|
header->palette[2][foo] = foo;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case IMAGE_RGB:
|
|
|
|
|
Image_alloc_pixels(&header->Rpix, width, height);
|
|
|
|
|
Image_alloc_pixels(&header->Gpix, width, height);
|
|
|
|
|
Image_alloc_pixels(&header->Bpix, width, height);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case IMAGE_RGBA:
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
|
fprintf(stderr, "WARNING! allocating an image with alpha channel,\n");
|
|
|
|
|
#endif
|
|
|
|
|
Image_alloc_pixels(&header->Rpix, width, height);
|
|
|
|
|
Image_alloc_pixels(&header->Gpix, width, height);
|
|
|
|
|
Image_alloc_pixels(&header->Bpix, width, height);
|
|
|
|
|
Image_alloc_pixels(&header->Apix, width, height);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
fprintf(stderr, "***** %s alloc image: %d is an unknow type *****\n",
|
|
|
|
|
__FILE__, type);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (getenv("MALLOC_CHECK_") != NULL)
|
|
|
|
|
{
|
2022-06-26 22:55:56 +02:00
|
|
|
|
fprintf(stderr, "-+- libtthimage %s %d: alloc %p\n",
|
2022-06-26 02:23:53 +02:00
|
|
|
|
__FILE__, __LINE__, header);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return header;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/*
|
|
|
|
|
This fonction build another image from a model.
|
|
|
|
|
*/
|
|
|
|
|
Image_Desc *
|
|
|
|
|
Image_clone (Image_Desc *src, int copy)
|
|
|
|
|
{
|
|
|
|
|
Image_Desc *image;
|
|
|
|
|
|
|
|
|
|
if ( src==NULL )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Image_clone: source descriptor is NULL\n");
|
|
|
|
|
exit(5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
image = Image_alloc(src->width, src->height, src->type);
|
|
|
|
|
if ( image==NULL )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Image_clone: cloned descriptor is NULL\n");
|
|
|
|
|
exit(5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* we have to transfer a few attributes ...
|
|
|
|
|
*/
|
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
|
|
|
fprintf(stderr, "clone %p to %p, no copy of attributes ?\n", src, image);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
image->fx = src->fx; image->fy = src->fy;
|
|
|
|
|
image->fw = src->fw; image->fh = src->fh;
|
|
|
|
|
|
|
|
|
|
if (copy == 1)
|
|
|
|
|
{
|
|
|
|
|
Image_copy(src, image);
|
|
|
|
|
}
|
|
|
|
|
image->modified = 0; /* 8 Fev 01 */
|
|
|
|
|
|
|
|
|
|
return image;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
int Image_copy_comment(Image_Desc *s, Image_Desc *d)
|
|
|
|
|
{
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
|
fprintf(stderr, "%s ( %p -> %p )\n", __func__, s, d);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* TODO check the validity of the comment, there _must_ be a '\0' inside */
|
|
|
|
|
|
|
|
|
|
memcpy(d->comment, s->comment, IMG_OBJCOMMENT_LEN);
|
|
|
|
|
|
|
|
|
|
return FUNC_IS_ALPHA;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/*
|
|
|
|
|
* Helas, cette fonction ne marche que sur les images RGB
|
|
|
|
|
* et comment la rendre compatible tout-types sans tout casser ?
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
Image_clear( Image_Desc *image, int r, int g, int b )
|
|
|
|
|
{
|
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
|
|
if (image->type == IMAGE_RGB)
|
|
|
|
|
{
|
|
|
|
|
for (y=0; y<image->height; y++)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* XXX here we can go faster with a few memset
|
|
|
|
|
*/
|
|
|
|
|
for (x=0; x<image->width; x++)
|
|
|
|
|
{
|
|
|
|
|
(image->Rpix[y])[x] = r;
|
|
|
|
|
(image->Gpix[y])[x] = g;
|
|
|
|
|
(image->Bpix[y])[x] = b;
|
|
|
|
|
/* Bon, et le canal Alpha, il devient quoi ? */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0; /* ok, this 'return' here is a "spleyterie" :) */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (image->type == IMAGE_RGBA)
|
|
|
|
|
{
|
|
|
|
|
for (y=0; y<image->height; y++)
|
|
|
|
|
{
|
|
|
|
|
for (x=0; x<image->width; x++)
|
|
|
|
|
{
|
|
|
|
|
(image->Rpix[y])[x] = r;
|
|
|
|
|
(image->Gpix[y])[x] = g;
|
|
|
|
|
(image->Bpix[y])[x] = b;
|
|
|
|
|
(image->Apix[y])[x] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0; /* ok, this 'return' here is a "spleyterie" :) */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "%s : invalid image type %d : %s\n", __func__,
|
|
|
|
|
image->type, Image_type2str(image->type));
|
|
|
|
|
return IMAGE_BAD_TYPE;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
2023-09-25 13:28:13 +02:00
|
|
|
|
/* new: Sat Sep 23 19:07:03 UTC 2023
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
int Image_set_rgb(Image_Desc *img, RGBA *rgba)
|
|
|
|
|
{
|
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
|
fprintf(stderr, ">>> %s ( %p %p ) %d %d %d\n", __func__, img,
|
|
|
|
|
rgba, rgba->r, rgba->g, rgba->b);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (IMAGE_RGB != img->type) {
|
|
|
|
|
fprintf(stderr, "%s : invalid image type %d : %s\n", __func__,
|
|
|
|
|
img->type, Image_type2str(img->type));
|
|
|
|
|
return IMAGE_BAD_TYPE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (y=0; y<img->height; y++) {
|
|
|
|
|
for (x=0; x<img->width; x++) {
|
|
|
|
|
(img->Rpix[y])[x] = rgba->r;
|
|
|
|
|
(img->Gpix[y])[x] = rgba->g;
|
|
|
|
|
(img->Bpix[y])[x] = rgba->b;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return FUNC_IS_BETA;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
2022-06-26 02:23:53 +02:00
|
|
|
|
/*
|
|
|
|
|
* every image in memory have a comment field, who is writen
|
|
|
|
|
* in TGA and PNM file when image is saved.
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
Image_set_comment(Image_Desc *image, char *text)
|
|
|
|
|
{
|
|
|
|
|
if (strlen(text) > IMG_OBJCOMMENT_LEN)
|
|
|
|
|
return STRING_TOO_LONG;
|
|
|
|
|
strcpy(image->comment, text);
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/* 10 nov 2001: no #define for this not-so-magic 254 value ? */
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
int
|
|
|
|
|
Image_plot_gray(Image_Desc *img, int x, int y, int v)
|
|
|
|
|
{
|
|
|
|
|
if ( x<0 || y<0 || x>=img->width || y>=img->height )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "ERRPLOT X %4d Y %4d %d\n", x, y, v);
|
|
|
|
|
return OUT_OF_IMAGE;
|
|
|
|
|
}
|
|
|
|
|
(img->Rpix[y])[x] = (uint8_t)v;
|
|
|
|
|
/* POURQUOI on ne plotte qu'une composante ? XXX */
|
|
|
|
|
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Image_plotRGB(Image_Desc *img, int x, int y, int r, int g, int b)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL > 2
|
|
|
|
|
fprintf(stderr, "PLOTRGB %d %d\n", x, y);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if ( x<0 || y<0 || x>=img->width || y>=img->height )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Errplot RGB X=%d, Y=%d %d, %d, %d\n", x, y, r, g, b);
|
|
|
|
|
#if FORCE_ABORT
|
|
|
|
|
abort();
|
|
|
|
|
#endif
|
|
|
|
|
return OUT_OF_IMAGE;
|
|
|
|
|
}
|
|
|
|
|
(img->Rpix[y])[x] = (uint8_t)(r&0xff);
|
|
|
|
|
(img->Gpix[y])[x] = (uint8_t)(g&0xff);
|
|
|
|
|
(img->Bpix[y])[x] = (uint8_t)(b&0xff);
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Image_plotRGBA(Image_Desc *img, int x, int y, int r, int g, int b, int a)
|
|
|
|
|
{
|
|
|
|
|
if ( x<0 || y<0 || x>=img->width || y>=img->height )
|
|
|
|
|
{
|
|
|
|
|
/* may be an #if DEBUG_LEVEL here ? */
|
|
|
|
|
fprintf(stderr, "Errplot RGBA X %4d Y %4d %d, %d, %d, %d\n",
|
|
|
|
|
x, y, r, g, b, a);
|
|
|
|
|
#if FORCE_ABORT
|
|
|
|
|
abort();
|
|
|
|
|
#endif
|
|
|
|
|
return OUT_OF_IMAGE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(img->Rpix[y])[x] = (uint8_t)(r&0xff);
|
|
|
|
|
(img->Gpix[y])[x] = (uint8_t)(g&0xff);
|
|
|
|
|
(img->Bpix[y])[x] = (uint8_t)(b&0xff);
|
|
|
|
|
(img->Apix[y])[x] = (uint8_t)(a&0xff);
|
|
|
|
|
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
int
|
|
|
|
|
Image_getRGB(Image_Desc *img, int x, int y, int *pr, int *pg, int *pb)
|
|
|
|
|
{
|
|
|
|
|
if ( x<0 || y<0 || x>=img->width || y>=img->height )
|
|
|
|
|
{
|
|
|
|
|
/* may be an #if DEBUG_LEVEL here ? */
|
|
|
|
|
fprintf(stderr, "ERR GETRGB X %4d Y %4d\n", x, y);
|
|
|
|
|
#if FORCE_ABORT
|
|
|
|
|
abort();
|
|
|
|
|
#endif
|
|
|
|
|
return OUT_OF_IMAGE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*pr = (int)((img->Rpix[y])[x]);
|
|
|
|
|
*pg = (int)((img->Gpix[y])[x]);
|
|
|
|
|
*pb = (int)((img->Bpix[y])[x]);
|
|
|
|
|
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
int
|
|
|
|
|
Image_getRGBA(Image_Desc *img, int x, int y, int *pr, int *pg, int *pb, int *pa)
|
|
|
|
|
{
|
|
|
|
|
if ( x<0 || y<0 || x>=img->width || y>=img->height )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "ERR GETRGBA X %4d Y %4d\n", x, y);
|
|
|
|
|
#if FORCE_ABORT
|
|
|
|
|
abort();
|
|
|
|
|
#endif
|
|
|
|
|
return OUT_OF_IMAGE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (img->type != IMAGE_RGBA)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Image get RGBA: bad image type: %d, %s\n",
|
|
|
|
|
img->type, Image_type2str(img->type));
|
|
|
|
|
#if FORCE_ABORT
|
|
|
|
|
abort();
|
|
|
|
|
#endif
|
|
|
|
|
exit(7); /* et un code d'erreur, <20>a irais pas mieux */
|
|
|
|
|
}
|
|
|
|
|
*pr = (int)((img->Rpix[y])[x]);
|
|
|
|
|
*pg = (int)((img->Gpix[y])[x]);
|
|
|
|
|
*pb = (int)((img->Bpix[y])[x]);
|
|
|
|
|
*pa = (int)((img->Apix[y])[x]);
|
|
|
|
|
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/*
|
|
|
|
|
* ecriture d'une des composantes de l'image. (new=2000-02-01)
|
|
|
|
|
*
|
|
|
|
|
* 15 mars 2003: l'interface Fortran est dans 'img77g.c' XXX
|
|
|
|
|
*/
|
|
|
|
|
int Image_plot_channel(Image_Desc *img, char channel, int x, int y, int value)
|
|
|
|
|
{
|
|
|
|
|
if ( x<0 || y<0 || x>=img->width || y>=img->height )
|
|
|
|
|
{
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
|
fprintf(stderr, "ERR PLOTCHANNEL X %4d Y %4d\n", x, y);
|
|
|
|
|
#endif
|
|
|
|
|
return OUT_OF_IMAGE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (channel)
|
|
|
|
|
{
|
|
|
|
|
case 'r': case 'R': (img->Rpix[y])[x] = (uint8_t)(value&0xff); break;
|
|
|
|
|
case 'g': case 'G': (img->Gpix[y])[x] = (uint8_t)(value&0xff); break;
|
|
|
|
|
case 'b': case 'B': (img->Bpix[y])[x] = (uint8_t)(value&0xff); break;
|
|
|
|
|
case 'a': case 'A': (img->Apix[y])[x] = (uint8_t)(value&0xff); break;
|
|
|
|
|
default: return WRONG_CHANNEL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/*
|
|
|
|
|
lecture d'une des composantes de l'image.
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
Image_R_pixel(Image_Desc *img, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
if ( x<0 || y<0 || x>=img->width || y>=img->height )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "ERR READ R PIX X%d Y%d\n", x, y);
|
|
|
|
|
return OUT_OF_IMAGE;
|
|
|
|
|
}
|
|
|
|
|
return (int)((img->Rpix[y])[x]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
Image_G_pixel(Image_Desc *img, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
if ( x<0 || y<0 || x>=img->width || y>=img->height )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "ERR READ G PIX X%d Y%d\n", x, y);
|
|
|
|
|
return OUT_OF_IMAGE;
|
|
|
|
|
}
|
|
|
|
|
return (int)((img->Gpix[y])[x]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
Image_B_pixel(Image_Desc *img, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
if ( x<0 || y<0 || x>=img->width || y>=img->height )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "ERR READ B PIX X%d Y%d\n", x, y);
|
|
|
|
|
return OUT_OF_IMAGE;
|
|
|
|
|
}
|
|
|
|
|
return (int)((img->Bpix[y])[x]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
Image_A_pixel(Image_Desc *img, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
if ( x<0 || y<0 || x>=img->width || y>=img->height )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "ERR A PIX X%d Y%d\n", x, y);
|
|
|
|
|
return OUT_OF_IMAGE;
|
|
|
|
|
}
|
|
|
|
|
return (int)((img->Apix[y])[x]);
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
2022-06-26 11:06:35 +02:00
|
|
|
|
/*
|
|
|
|
|
cette fonction ne marche que si les deux images
|
|
|
|
|
sont allouees et de meme dimensions.
|
|
|
|
|
*/
|
2022-09-17 11:23:21 +02:00
|
|
|
|
int Image_copy(Image_Desc *src, Image_Desc *dst)
|
2022-06-26 11:06:35 +02:00
|
|
|
|
{
|
|
|
|
|
int foo;
|
|
|
|
|
|
2022-09-17 11:23:21 +02:00
|
|
|
|
if ( (foo=Image_compare_desc(src, dst)) ) {
|
|
|
|
|
fprintf(stderr, "%s: images are differents %d\n", __func__, foo);
|
2022-06-26 11:06:35 +02:00
|
|
|
|
return foo;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-17 11:23:21 +02:00
|
|
|
|
for (foo=0; foo<src->height; foo++) {
|
2022-06-26 11:06:35 +02:00
|
|
|
|
memcpy(dst->Rpix[foo], src->Rpix[foo], src->width);
|
|
|
|
|
memcpy(dst->Gpix[foo], src->Gpix[foo], src->width);
|
|
|
|
|
memcpy(dst->Bpix[foo], src->Bpix[foo], src->width);
|
|
|
|
|
if (dst->Apix!=NULL && src->Apix!=NULL)
|
|
|
|
|
memcpy(dst->Apix[foo], src->Apix[foo], src->width);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst->modified = 1;
|
|
|
|
|
/*
|
|
|
|
|
>> 18 Juin 2002
|
|
|
|
|
>> ============
|
|
|
|
|
>> bon, maintenant se pose un grand probl<EFBFBD>me philosophique.
|
|
|
|
|
>> on vient juste de copier les octets qui incarnent les pixels
|
|
|
|
|
>> rgb et peut-<EFBFBD>tre alpha. Mais ce n'est que la partie <EFBFBD>vident
|
|
|
|
|
>> d'une image: ses pixels.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
2022-06-26 02:23:53 +02:00
|
|
|
|
/*
|
|
|
|
|
* no boundary control ?
|
|
|
|
|
*/
|
2022-09-17 11:23:21 +02:00
|
|
|
|
int Image_pixel_copy(Image_Desc *s, int x, int y, Image_Desc *d, int i, int j)
|
2022-06-26 02:23:53 +02:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
(d->Rpix[j])[i] = (s->Rpix[y])[x];
|
|
|
|
|
(d->Gpix[j])[i] = (s->Gpix[y])[x];
|
|
|
|
|
(d->Bpix[j])[i] = (s->Bpix[y])[x];
|
|
|
|
|
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/*
|
|
|
|
|
* Le nom de cette fonction n'a pas trop de rapport avec ce qu'elle fait,
|
|
|
|
|
* mais elle permet de faire reculer Crash Coredump.
|
|
|
|
|
*/
|
2022-09-17 11:23:21 +02:00
|
|
|
|
int Image_compare_desc(Image_Desc *a, Image_Desc *b)
|
2022-06-26 02:23:53 +02:00
|
|
|
|
{
|
|
|
|
|
char *fmt = "Image at %p have no 'Dead Beef' in it\n";
|
|
|
|
|
|
|
|
|
|
if ( (a==NULL) || (b==NULL) ) return NULL_DESCRIPTOR;
|
|
|
|
|
|
|
|
|
|
if ( a->magic != MAGIC_OF_IMAGE )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, fmt, a);
|
|
|
|
|
return NOT_AN_IMAGE_DESC;
|
|
|
|
|
}
|
|
|
|
|
if ( b->magic != MAGIC_OF_IMAGE )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, fmt, a);
|
|
|
|
|
return NOT_AN_IMAGE_DESC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( a->width != b->width ) return DIFFERENT_WIDTH;
|
|
|
|
|
if ( a->height!= b->height) return DIFFERENT_HEIGHT;
|
|
|
|
|
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/*
|
|
|
|
|
Cette fonction ne rend pas toute la memoire
|
|
|
|
|
Pour le moment, le header n'est pas restitue.
|
|
|
|
|
|
|
|
|
|
le probleme, si on desalloue le header
|
|
|
|
|
c'est qu'il reste un pointeur fou chez
|
|
|
|
|
l'appelant ...
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
Image_DeAllocate(Image_Desc *im)
|
|
|
|
|
{
|
|
|
|
|
int line;
|
|
|
|
|
|
|
|
|
|
if (getenv("MALLOC_CHECK_") != NULL) {
|
2022-06-26 22:55:56 +02:00
|
|
|
|
fprintf(stderr, "-+- libtthimage %s %d: free %p\n",
|
2022-06-26 02:23:53 +02:00
|
|
|
|
__FILE__, __LINE__, im);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( im->magic != MAGIC_OF_IMAGE ) {
|
|
|
|
|
fprintf(stderr, "at %p, there was no 'Dead Beef' to deallocate\n", im);
|
|
|
|
|
/* emergency exit */
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
|
|
|
fprintf(stderr, ">> de-allocating image %p, cross your fingers.\n", im);
|
|
|
|
|
fprintf(stderr, " %p %p %p %p\n", im->Rpix, im->Gpix, im->Bpix, im->Apix);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
im->magic = 0L; /* mark dirty/invalid. */
|
|
|
|
|
im->type = IMAGE_NONE; /* -1, et tusors */
|
|
|
|
|
|
2022-09-13 00:11:53 +02:00
|
|
|
|
if (im->Rpix != NULL) {
|
2022-06-26 02:23:53 +02:00
|
|
|
|
for (line=0; line<im->height; line++)
|
|
|
|
|
if (im->Rpix[line] != NULL) free(im->Rpix[line]);
|
|
|
|
|
free(im->Rpix); im->Rpix = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-13 00:11:53 +02:00
|
|
|
|
if (im->Gpix != NULL) {
|
2022-06-26 02:23:53 +02:00
|
|
|
|
for (line=0; line<im->height; line++)
|
|
|
|
|
if (im->Gpix[line] != NULL) free(im->Gpix[line]);
|
|
|
|
|
free(im->Gpix); im->Gpix = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-13 00:11:53 +02:00
|
|
|
|
if (im->Bpix != NULL) {
|
2022-06-26 02:23:53 +02:00
|
|
|
|
for (line=0; line<im->height; line++)
|
|
|
|
|
if (im->Bpix[line] != NULL) free(im->Bpix[line]);
|
|
|
|
|
free(im->Bpix); im->Bpix = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-13 00:11:53 +02:00
|
|
|
|
if (im->Apix != NULL) {
|
2022-06-26 02:23:53 +02:00
|
|
|
|
for (line=0; line<im->height; line++)
|
|
|
|
|
if (im->Apix[line] != NULL) free(im->Apix[line]);
|
|
|
|
|
free(im->Apix); im->Apix = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
|
|
|
fprintf(stderr, "DeAllocate >> are we alive ?\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|