libtthimage/Lib/palettes.c

400 lines
9.4 KiB
C
Raw Normal View History

2022-06-27 02:19:31 +02:00
/*
palettes.c
----------
for more informations about color maps, you can seek the web
from this starting point: http://www.fractint.org/
*/
#include <stdio.h>
#include <stdlib.h> /* for rand() */
#include <string.h>
#include <math.h>
#include "../tthimage.h"
/*::------------------------------------------------------------------::*/
/*
* Les colors maps sont censees etre compatible avec celles
* de FRACTINT, mais il faudrait verifier.
*/
2024-07-16 19:07:37 +02:00
int Image_save_color_Map(char *file, char *name, RGB_map *map)
2022-06-27 02:19:31 +02:00
{
int foo;
FILE *fp;
2023-11-18 19:56:25 +01:00
fprintf(stderr, ">>> %s ( '%s' '%s' %p )\n", __func__,
file, name, map);
2022-08-22 17:53:30 +02:00
if ( (fp=fopen(file, "w")) == NULL ) {
2022-06-27 02:19:31 +02:00
fprintf(stderr, "Save Color Map: err fopen\n");
return FILE_CREATE_ERR;
}
2022-08-22 17:53:30 +02:00
if ( map->nbre == 0 ) {
2022-06-27 02:19:31 +02:00
fprintf(stderr, "Save Color Map: empty map\n");
}
2022-08-22 17:53:30 +02:00
for (foo=0; foo<map->nbre; foo++) {
2022-06-27 02:19:31 +02:00
fprintf(fp, "%3d %3d %3d",
map->red[foo], map->green[foo], map->blue[foo]);
2022-08-22 17:53:30 +02:00
switch (foo) {
2022-06-27 02:19:31 +02:00
case 0:
if (name != NULL)
fprintf(fp, " Name: %s", name);
else
fprintf(fp, " Anne Onim Colormap");
break;
case 1:
fprintf(fp, " Lib version: %s", IMAGE_VERSION_STRING);
break;
case 2:
fprintf(fp, " Number of colors %d", map->nbre);
break;
case 3:
fprintf(fp, " Bugs -> call Tonton Th");
break;
case 42:
fprintf(fp, " Yes, 42 is _the_ answer");
break;
}
fprintf(fp, "\n");
}
fclose(fp);
return OLL_KORRECT;
}
/*::------------------------------------------------------------------::*/
/*
* Colors map file are (maybe?) compatibles with colors maps
* of FRACTINT. More check must be done.
*
* Les colors maps sont censees etre compatible avec celles
* de FRACTINT, mais il faudrait verifier.
*
* What is the 'right thing' to do when we get more than
* 256 lines of data ? return an error ?
*/
2024-07-16 19:07:37 +02:00
int Image_load_color_Map(char *file, char *name, RGB_map *where)
2022-06-27 02:19:31 +02:00
{
FILE *fp;
int nbre, r, g, b, foo, errcode;
char buffer[256];
2024-07-16 19:07:37 +02:00
#if DEBUG_LEVEL
2023-11-18 19:56:25 +01:00
fprintf(stderr, ">>> %s ( '%s' '%s' %p )\n", __func__,
file, name, where);
2024-07-16 19:07:37 +02:00
#endif
2023-11-18 19:56:25 +01:00
2022-08-22 17:53:30 +02:00
if ( name != NULL ) {
if (strlen(name)>IMG_OBJNAME_LEN) return STRING_TOO_LONG;
2022-06-27 02:19:31 +02:00
strcpy(where->name, name);
}
2023-11-18 19:56:25 +01:00
else strcpy(where->name, "<noname>");
2022-06-27 02:19:31 +02:00
/*
2024-07-16 19:07:37 +02:00
* patch du 11 Decembre 2001: on utilise une fonction qui recherche le
* fichier dans differents endroits. Cf 'mustopen.c' pour + de details.
2022-06-27 02:19:31 +02:00
*/
2022-08-22 17:53:30 +02:00
if ((fp=Image_must_fopen(file, "r", 0)) == NULL) {
2022-06-27 02:19:31 +02:00
/* safety poke */
where->nbre = 0;
fprintf(stderr, "Load color MAP: %s not found\n", file);
return FILE_NOT_FOUND;
}
nbre = 0; errcode = 0;
where->nbre = 0; /* kill bad value */
2022-08-22 17:53:30 +02:00
while ( fgets(buffer, 250, fp) != NULL ) {
2022-06-27 02:19:31 +02:00
foo = sscanf(buffer, "%d %d %d", &r, &g, &b);
2022-08-22 17:53:30 +02:00
if (foo != 3) {
2022-06-27 02:19:31 +02:00
fprintf(stderr, "line %d: [%s]\n", nbre, buffer);
errcode = BAD_COLOR_NUMBER; break;
}
where->red[nbre] = r;
where->green[nbre] = g;
where->blue[nbre] = b;
nbre++;
2022-08-22 17:53:30 +02:00
if (nbre > 256) {
2022-06-27 02:19:31 +02:00
fprintf(stderr, "load color map: nbre = %d\n", nbre);
errcode = MAP_TOO_BIG; break;
}
}
where->nbre = nbre;
fclose(fp);
return errcode;
}
/*::------------------------------------------------------------------::*/
/*
* attach color map a finir...
*
* XXX voir aussi indexcol.x XXX
*/
2024-07-16 19:07:37 +02:00
int Image_attach_Map(Image_Desc *im, char *nom_map, int flags)
2022-06-27 02:19:31 +02:00
{
RGB_map map;
int foo;
2024-07-16 19:07:37 +02:00
fprintf(stderr, "%s: cette fonction n'est pas finie\n", __func__);
2022-06-27 02:19:31 +02:00
foo = Image_load_color_Map(nom_map, "", &map);
2022-08-22 17:53:30 +02:00
if (foo == 0) {
2022-06-27 02:19:31 +02:00
fprintf(stderr, "Attach Map: foo is zero ?\n");
}
return FUNC_NOT_FINISH;
}
/*::------------------------------------------------------------------::*/
/* new 31 Juillet 2000 */
2024-07-16 19:07:37 +02:00
int Image_make_random_Map(char *nom, RGB_map *map, int nbre)
2022-06-27 02:19:31 +02:00
{
int foo;
fprintf(stderr, "making a random map named '%s'\n", nom);
2022-08-22 17:53:30 +02:00
if (nbre < 0 || nbre > 255) {
2022-06-27 02:19:31 +02:00
fprintf(stderr, "make random map: nbre = %d\n", map->nbre);
return BAD_COLOR_NUMBER;
}
map->nbre = nbre;
2022-08-22 17:53:30 +02:00
for (foo=0; foo<nbre; foo++) {
2022-06-27 02:19:31 +02:00
map->red[foo] = rand() & 0xff;
map->green[foo] = rand() & 0xff;
map->blue[foo] = rand() & 0xff;
}
return OLL_KORRECT;
}
/*::------------------------------------------------------------------::*/
/* 21 Sept 2000
Make a 2x2x2 color palette.
*/
2024-07-16 19:07:37 +02:00
int Image_make_222_Map(char *nom, RGB_map *map, int noise)
2022-06-27 02:19:31 +02:00
{
int foo, r, g, b;
#if DEBUG_LEVEL
fprintf(stderr, "Make 222 map: parameter 'noise' (%d) not used\n", noise);
#endif
strcpy(map->name, "* FMBL roulaize *");
map->nbre = 64;
2022-08-22 17:53:30 +02:00
for (foo=0; foo<64; foo++) {
2022-06-27 02:19:31 +02:00
r = ((foo >> 0) & 0x03) * 85;
g = ((foo >> 2) & 0x03) * 85;
b = ((foo >> 4) & 0x03) * 85;
#if DEBUG_LEVEL
fprintf(stderr, "make 222 map: %3d: %3d %3d %3d\n", foo, r, g, b);
#endif
map->red[foo] = r;
map->green[foo] = g;
map->blue[foo] = b;
}
return OLL_KORRECT;
}
/*::------------------------------------------------------------------::*/
/* 15 Mai 2001
* A big classic: the three-sinus color map.
2024-07-16 19:07:37 +02:00
* parametres:
2022-06-27 02:19:31 +02:00
* 0,1,2 R,G,B period
* 3,4,5 R,G,B phase
* 6,7 reserved
*/
2024-07-16 19:07:37 +02:00
int Image_palette_3sinus(char *nom, RGB_map *ou, double pars[8])
2022-06-27 02:19:31 +02:00
{
int foo;
double dfoo, dra, dga, dba;
fprintf(stderr, "Palette 3 Sinus: may be bogus ?\n");
#if DEBUG_LEVEL
for (foo=0; foo<8; foo++)
fprintf(stderr, " %3d %g\n", foo, pars[foo]);
#endif
2022-08-22 17:53:30 +02:00
for (foo=0; foo<256; foo++) {
2022-06-27 02:19:31 +02:00
dfoo = (double)foo / 255.0 * M_PI * 2;
dra = sin((pars[0] * dfoo) + pars[3]);
dga = sin((pars[1] * dfoo) + pars[4]);
dba = sin((pars[2] * dfoo) + pars[5]);
ou->red[foo] = (int)(dra * 127.0 + 127.0);
ou->green[foo] = (int)(dga * 127.0 + 127.0);
ou->blue[foo] = (int)(dba * 127.0 + 127.0);
}
ou->nbre = 256;
return FUNC_IS_BETA;
}
/*::------------------------------------------------------------------::*/
/* new 18 Dec 2001
*/
2024-07-16 19:07:37 +02:00
int Image_mix_palettes(RGB_map *p1, RGB_map *p2, RGB_map *d, char *txt, int k)
2022-06-27 02:19:31 +02:00
{
int idx, k2;
int r1, g1, b1, r2, g2, b2;
#if DEBUG_LEVEL
fprintf(stderr, "Image mix palette: work in progress...\n");
#endif
k2 = 10000 - k;
2022-08-22 17:53:30 +02:00
for (idx=0; idx<256; idx++) {
2024-07-16 19:07:37 +02:00
if (idx < p1->nbre) {
2022-06-27 02:19:31 +02:00
r1 = p1->red[idx];
g1 = p1->green[idx];
b1 = p1->blue[idx];
}
2022-08-22 17:53:30 +02:00
else {
2022-06-27 02:19:31 +02:00
r1 = g1 = b1 = 0;
}
2022-08-22 17:53:30 +02:00
if (idx < p2->nbre) {
2022-06-27 02:19:31 +02:00
r2 = p2->red[idx];
g2 = p2->green[idx];
b2 = p2->blue[idx];
}
2022-08-22 17:53:30 +02:00
else {
2022-06-27 02:19:31 +02:00
r2 = g2 = b2 = 0;
}
d->red[idx] = (r1*k + r2*k2) / 10000;
d->green[idx] = (g1*k + g2*k2) / 10000;
d->blue[idx] = (b1*k + b2*k2) / 10000;
}
d->nbre = 256;
if (strlen(txt)<IMG_OBJNAME_LEN)
strcpy(d->name, txt);
else
strcpy(d->name, "mix palettes: TXT is too long");
return FUNC_IS_BETA;
}
/*::------------------------------------------------------------------::*/
/* new 01 aout 2008 */
2024-07-16 19:07:37 +02:00
/* XXX HACK XXX */ /* please explain ! */
2022-06-27 02:19:31 +02:00
double round(double);
/* XXX HACK XXX */
int Image_scale_palette(RGB_map *p, double v, int clip_it)
{
int foo;
#if DEBUG_LEVEL
int maxval = -99999;
#endif
2022-08-22 17:53:30 +02:00
if (p->nbre < 1 || p->nbre > 256) {
2022-06-27 02:19:31 +02:00
fprintf(stderr, "%s: RGB_map %p has %d entries ?\n",
__func__, p, p->nbre);
}
2022-08-22 17:53:30 +02:00
for (foo=0; foo<p->nbre; foo++) {
2024-07-16 19:07:37 +02:00
p->red[foo] = round((double)p->red[foo] * v);
2022-06-27 02:19:31 +02:00
p->green[foo] = round((double)p->green[foo] * v);
2024-07-16 19:07:37 +02:00
p->blue[foo] = round((double)p->blue[foo] * v);
2022-08-22 17:53:30 +02:00
if (clip_it) {
2022-06-27 02:19:31 +02:00
if (p->red[foo] < 0) p->red[foo] = 0;
if (p->red[foo] > 255) p->red[foo] = 255;
if (p->green[foo] < 0) p->green[foo] = 0;
if (p->green[foo] > 255) p->green[foo] = 255;
if (p->blue[foo] < 0) p->blue[foo] = 0;
if (p->blue[foo] > 255) p->blue[foo] = 255;
}
#if DEBUG_LEVEL
if (p->red[foo] > maxval) maxval = p->red[foo];
if (p->green[foo] > maxval) maxval = p->green[foo];
if (p->blue[foo] > maxval) maxval = p->blue[foo];
#endif
}
#if DEBUG_LEVEL
fprintf(stderr, "%s: maxval is %d\n", __func__, maxval);
#endif
return FUNC_IS_BETA;
}
/*::------------------------------------------------------------------::*/
/* nouveau 10 aout 2008 - avenue St Exupery -
*/
int Image_scale3_palette(RGB_map *p, double rk, double gk, double bk,
int clip_it)
{
int foo;
2022-08-22 17:53:30 +02:00
if (p->nbre < 1 || p->nbre > 256) {
2022-06-27 02:19:31 +02:00
fprintf(stderr, "%s: RGB_map %p has %d entries ?\n",
__func__, p, p->nbre);
}
2022-08-22 17:53:30 +02:00
for (foo=0; foo<p->nbre; foo++) {
2022-06-27 02:19:31 +02:00
p->red[foo] = round((double)p->red[foo] * rk);
p->green[foo] = round((double)p->green[foo] * gk);
p->blue[foo] = round((double)p->blue[foo] * bk);
2022-08-22 17:53:30 +02:00
if (clip_it) {
2022-06-27 02:19:31 +02:00
if (p->red[foo] < 0) p->red[foo] = 0;
if (p->red[foo] > 255) p->red[foo] = 255;
if (p->green[foo] < 0) p->green[foo] = 0;
if (p->green[foo] > 255) p->green[foo] = 255;
if (p->blue[foo] < 0) p->blue[foo] = 0;
if (p->blue[foo] > 255) p->blue[foo] = 255;
}
}
return FUNC_IS_BETA;
}
/*::------------------------------------------------------------------::*/
/*
* nouveau 7 juillet 2010 - enregistrement d'une palette dans un fichier
* au format PPM - man ppmquant pour plus de details.
* premiere mise en oeuvre : les vignettes de l'exPOVsition.
*/
int Image_map2ppm(RGB_map *p, char *fname, char *comment)
{
FILE *fp;
int foo;
#if DEBUG_LEVEL
fprintf(stderr, "%s (( %p '%s' '%s' ))\n", __func__, p, fname, comment);
#endif
2022-08-22 17:53:30 +02:00
if (NULL == p) {
2022-06-27 02:19:31 +02:00
fprintf(stderr, "in %s, can't gruik au nill map\n", __func__);
abort();
}
#if DEBUG_LEVEL
fprintf(stderr, "we have %d colors in palette at %p\n", p->nbre, p);
#endif
2022-08-22 17:53:30 +02:00
if ( (fp=fopen(fname, "w")) == NULL ) {
2022-06-27 02:19:31 +02:00
fprintf(stderr, "%s: err fopen %s\n", __func__, fname);
return FILE_CREATE_ERR;
}
fprintf(fp, "P3\n%d 1\n255\n", p->nbre);
2022-07-07 12:52:00 +02:00
if (NULL != comment) {
fprintf(fp, "# %s\n", comment);
}
2022-08-22 17:53:30 +02:00
for (foo=0; foo<p->nbre; foo++) {
2022-06-27 02:19:31 +02:00
fprintf(fp, "%3d %3d %3d\n", p->red[foo], p->green[foo], p->blue[foo]);
}
fclose(fp);
2024-07-16 19:07:37 +02:00
return FUNC_IS_BETA;
2022-06-27 02:19:31 +02:00
}
/*::------------------------------------------------------------------::*/