400 lines
9.2 KiB
C
400 lines
9.2 KiB
C
/*
|
||
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.
|
||
*/
|
||
int
|
||
Image_save_color_Map(char *file, char *name, RGB_map *map)
|
||
{
|
||
int foo;
|
||
FILE *fp;
|
||
|
||
if ( (fp=fopen(file, "w")) == NULL ) {
|
||
fprintf(stderr, "Save Color Map: err fopen\n");
|
||
return FILE_CREATE_ERR;
|
||
}
|
||
|
||
if ( map->nbre == 0 ) {
|
||
fprintf(stderr, "Save Color Map: empty map\n");
|
||
}
|
||
|
||
for (foo=0; foo<map->nbre; foo++) {
|
||
fprintf(fp, "%3d %3d %3d",
|
||
map->red[foo], map->green[foo], map->blue[foo]);
|
||
switch (foo) {
|
||
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 ?
|
||
*/
|
||
int
|
||
Image_load_color_Map(char *file, char *name, RGB_map *where)
|
||
{
|
||
FILE *fp;
|
||
int nbre, r, g, b, foo, errcode;
|
||
char buffer[256];
|
||
|
||
if ( name != NULL ) {
|
||
if (strlen(name)>IMG_OBJNAME_LEN) return STRING_TOO_LONG;
|
||
strcpy(where->name, name);
|
||
}
|
||
else strcpy(where->name, "no name");
|
||
|
||
/*
|
||
* patch du 11 D<>cembre 2001: on utilise une fonction qui recherche le
|
||
* fichier dans differents endroits. Cf 'mustopen.c' pour + de d<>tails.
|
||
*/
|
||
if ((fp=Image_must_fopen(file, "r", 0)) == NULL) {
|
||
/* 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 */
|
||
|
||
while ( fgets(buffer, 250, fp) != NULL ) {
|
||
foo = sscanf(buffer, "%d %d %d", &r, &g, &b);
|
||
if (foo != 3) {
|
||
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++;
|
||
if (nbre > 256) {
|
||
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
|
||
*/
|
||
int
|
||
Image_attach_Map(Image_Desc *im, char *nom_map, int flags)
|
||
{
|
||
RGB_map map;
|
||
int foo;
|
||
|
||
fprintf(stderr, "Image attach Map: cette fonction n'est pas finie\n");
|
||
foo = Image_load_color_Map(nom_map, "", &map);
|
||
if (foo == 0) {
|
||
fprintf(stderr, "Attach Map: foo is zero ?\n");
|
||
}
|
||
|
||
return FUNC_NOT_FINISH;
|
||
}
|
||
/*::------------------------------------------------------------------::*/
|
||
/* new 31 Juillet 2000 */
|
||
|
||
int
|
||
Image_make_random_Map(char *nom, RGB_map *map, int nbre)
|
||
{
|
||
int foo;
|
||
|
||
fprintf(stderr, "making a random map named '%s'\n", nom);
|
||
|
||
if (nbre < 0 || nbre > 255) {
|
||
fprintf(stderr, "make random map: nbre = %d\n", map->nbre);
|
||
return BAD_COLOR_NUMBER;
|
||
}
|
||
map->nbre = nbre;
|
||
|
||
for (foo=0; foo<nbre; foo++) {
|
||
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.
|
||
*/
|
||
int
|
||
Image_make_222_Map(char *nom, RGB_map *map, int noise)
|
||
{
|
||
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;
|
||
|
||
for (foo=0; foo<64; foo++) {
|
||
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.
|
||
* param<61>tres:
|
||
* 0,1,2 R,G,B period
|
||
* 3,4,5 R,G,B phase
|
||
* 6,7 reserved
|
||
*/
|
||
int
|
||
Image_palette_3sinus(char *nom, RGB_map *ou, double pars[8])
|
||
{
|
||
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
|
||
|
||
for (foo=0; foo<256; foo++) {
|
||
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
|
||
*/
|
||
int
|
||
Image_mix_palettes(RGB_map *p1, RGB_map *p2, RGB_map *d, char *txt, int k)
|
||
{
|
||
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;
|
||
|
||
for (idx=0; idx<256; idx++) {
|
||
if (idx < p1->nbre)
|
||
{
|
||
r1 = p1->red[idx];
|
||
g1 = p1->green[idx];
|
||
b1 = p1->blue[idx];
|
||
}
|
||
else {
|
||
r1 = g1 = b1 = 0;
|
||
}
|
||
|
||
if (idx < p2->nbre) {
|
||
r2 = p2->red[idx];
|
||
g2 = p2->green[idx];
|
||
b2 = p2->blue[idx];
|
||
}
|
||
else {
|
||
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 */
|
||
|
||
/* XXX HACK XXX */
|
||
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
|
||
|
||
if (p->nbre < 1 || p->nbre > 256) {
|
||
fprintf(stderr, "%s: RGB_map %p has %d entries ?\n",
|
||
__func__, p, p->nbre);
|
||
}
|
||
|
||
for (foo=0; foo<p->nbre; foo++) {
|
||
p->red[foo] = round((double)p->red[foo] * v);
|
||
p->green[foo] = round((double)p->green[foo] * v);
|
||
p->blue[foo] = round((double)p->blue[foo] * v);
|
||
if (clip_it) {
|
||
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;
|
||
|
||
if (p->nbre < 1 || p->nbre > 256) {
|
||
fprintf(stderr, "%s: RGB_map %p has %d entries ?\n",
|
||
__func__, p, p->nbre);
|
||
}
|
||
|
||
for (foo=0; foo<p->nbre; foo++) {
|
||
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);
|
||
if (clip_it) {
|
||
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
|
||
|
||
if (NULL == p) {
|
||
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
|
||
|
||
if ( (fp=fopen(fname, "w")) == NULL ) {
|
||
fprintf(stderr, "%s: err fopen %s\n", __func__, fname);
|
||
return FILE_CREATE_ERR;
|
||
}
|
||
fprintf(fp, "P3\n%d 1\n255\n", p->nbre);
|
||
if (NULL != comment) {
|
||
fprintf(fp, "# %s\n", comment);
|
||
}
|
||
|
||
for (foo=0; foo<p->nbre; foo++) {
|
||
fprintf(fp, "%3d %3d %3d\n", p->red[foo], p->green[foo], p->blue[foo]);
|
||
}
|
||
|
||
fclose(fp);
|
||
|
||
return FULL_NUCKED;
|
||
}
|
||
/*::------------------------------------------------------------------::*/
|