pike.git
/
src
/
modules
/
Image
/
colors.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/modules/Image/colors.c:1:
+
/*
+
**! module Image
+
**! note
+
**! $Id: colors.c,v 1.1 1999/01/22 01:01:28 mirar Exp $
+
**! class colortable
+
**!
+
**! This object keeps colortable information,
+
**! mostly for image re-coloring (quantization).
+
**!
+
**! The object has color reduction, quantisation,
+
**! mapping and dithering capabilities.
+
**!
+
**! see also: Image, Image.image, Image.font, Image.GIF
+
*/
-
+
#include "global.h"
+
#include <config.h>
+
+
RCSID("$Id: colors.c,v 1.1 1999/01/22 01:01:28 mirar Exp $");
+
+
#include "config.h"
+
+
#include "stralloc.h"
+
#include "pike_macros.h"
+
#include "object.h"
+
#include "constants.h"
+
#include "interpret.h"
+
#include "svalue.h"
+
#include "array.h"
+
#include "mapping.h"
+
#include "threads.h"
+
#include "builtin_functions.h"
+
#include "dmalloc.h"
+
#include "module_support.h"
+
+
#include "image.h"
+
#include "colortable.h"
+
+
static struct mapping *colors=NULL;
+
static struct object *colortable=NULL;
+
static struct array *colornames=NULL;
+
+
struct program *image_color_program=NULL;
+
extern struct program *image_colortable_program;
+
+
static struct pike_string *str_array;
+
static struct pike_string *str_string;
+
static struct pike_string *str_r;
+
static struct pike_string *str_g;
+
static struct pike_string *str_b;
+
static struct pike_string *str_h;
+
static struct pike_string *str_s;
+
static struct pike_string *str_v;
+
+
struct color_struct
+
{
+
rgb_group rgb;
+
struct pike_string *name;
+
};
+
+
static void make_colors(void)
+
{
+
int n=0;
+
+
#define COLOR(name,R,G,B) \
+
push_text(name); \
+
push_int(R); \
+
push_int(G); \
+
push_int(B); \
+
push_text(name); \
+
push_object(clone_object(image_color_program,4)); \
+
n++;
+
#include "colors.h"
+
#undef COLOR
+
+
f_aggregate_mapping(n*2);
+
colors=sp[-1].u.mapping;
+
sp--;
+
+
n=0;
+
#define COLOR(name,R,G,B) \
+
push_int(R); \
+
push_int(G); \
+
push_int(B); \
+
f_aggregate(3); \
+
n++;
+
#include "colors.h"
+
#undef COLOR
+
+
f_aggregate(n);
+
colortable=clone_object(image_colortable_program,1);
+
+
push_int(5);
+
push_int(5);
+
push_int(5);
+
push_int(1);
+
safe_apply(colortable,"cubicles",4);
+
pop_stack();
+
+
n=0;
+
#define COLOR(name,R,G,B) \
+
push_text(name); \
+
n++;
+
#include "colors.h"
+
#undef COLOR
+
+
f_aggregate(n); \
+
colornames=sp[-1].u.array;
+
sp--;
+
}
+
+
#ifdef THIS
+
#undef THIS /* Needed for NT */
+
#endif
+
#define THIS ((struct color_struct*)(fp->current_storage))
+
#define THISOBJ (fp->current_object)
+
+
void init_color_struct(struct object *dummy)
+
{
+
THIS->rgb.r=THIS->rgb.g=THIS->rgb.b=0;
+
THIS->name=NULL;
+
}
+
+
void exit_color_struct(struct object *dummy)
+
{
+
if (THIS->name)
+
{
+
free_string(THIS->name);
+
THIS->name=NULL;
+
}
+
}
+
+
static void try_find_name(void)
+
{
+
rgb_group d;
+
+
if (!colors)
+
make_colors();
+
+
if (THIS->name)
+
{
+
free_string(THIS->name);
+
THIS->name=NULL;
+
}
+
+
image_colortable_map_image((struct neo_colortable*)colortable->storage,
+
&(THIS->rgb),&d,1,1);
+
+
if (d.r==THIS->rgb.r &&
+
d.g==THIS->rgb.g &&
+
d.b==THIS->rgb.b)
+
{
+
unsigned short d2;
+
image_colortable_index_16bit_image(
+
(struct neo_colortable*)colortable->storage,
+
&(THIS->rgb),&d2,1,1);
+
+
if (d2<colornames->size)
+
{
+
copy_shared_string(THIS->name,
+
colornames->item[d2].u.string);
+
}
+
}
+
}
+
+
void image_color_create(INT32 args)
+
{
+
if (args==4) /* r,g,b,name */
+
{
+
INT32 r,g,b;
+
get_all_args("Image.color->create()",args,"%i%i%i%W",
+
&r,&g,&b,&(THIS->name));
+
+
THIS->rgb.r=(COLORTYPE)r;
+
THIS->rgb.g=(COLORTYPE)g;
+
THIS->rgb.b=(COLORTYPE)b;
+
+
reference_shared_string(THIS->name);
+
+
pop_n_elems(args);
+
}
+
else if (args==3) /* r,g,b */
+
{
+
INT32 r,g,b;
+
get_all_args("Image.color->create()",args,"%i%i%i",
+
&r,&g,&b);
+
+
THIS->rgb.r=(COLORTYPE)r;
+
THIS->rgb.g=(COLORTYPE)g;
+
THIS->rgb.b=(COLORTYPE)b;
+
+
pop_n_elems(args);
+
+
try_find_name();
+
}
+
else error("Image.color->create(): Illegal argument(s)\n");
+
+
push_int(0);
+
}
+
+
void image_color_rgb(INT32 args)
+
{
+
pop_n_elems(args);
+
push_int(THIS->rgb.r);
+
push_int(THIS->rgb.g);
+
push_int(THIS->rgb.b);
+
f_aggregate(3);
+
}
+
+
void image_color_name(INT32 args)
+
{
+
if (THIS->name)
+
{
+
ref_push_string(THIS->name);
+
}
+
else
+
{
+
char buf[20];
+
switch (sizeof(COLORTYPE))
+
{
+
case 1:
+
sprintf(buf,"#%02x%02x%02x",THIS->rgb.r,THIS->rgb.g,THIS->rgb.b);
+
break;
+
case 2:
+
sprintf(buf,"#%04x%04x%04x",THIS->rgb.r,THIS->rgb.g,THIS->rgb.b);
+
break;
+
case 4:
+
sprintf(buf,"#%08x%08x%08x",THIS->rgb.r,THIS->rgb.g,THIS->rgb.b);
+
break;
+
}
+
push_text(buf);
+
}
+
}
+
+
void image_color_cast(INT32 args)
+
{
+
if (args!=1 ||
+
sp[-1].type!=T_STRING)
+
error("Image.color->cast(): Illegal argument(s)\n");
+
+
if (sp[-1].u.string==str_array)
+
{
+
image_color_rgb(args);
+
return;
+
}
+
if (sp[-1].u.string==str_string)
+
{
+
image_color_name(args);
+
return;
+
}
+
error("Image.color->cast(): Can't cast to that\n");
+
}
+
+
void image_color_index(INT32 args)
+
{
+
error("Image.color->`[]: Not implemented\n");
+
}
+
+
#define HEXTONUM(C) \
+
(((C)>='0' && (C)<='9')?(C)-'0': \
+
((C)>='a' && (C)<='f')?(C)-'a'+10: \
+
((C)>='A' && (C)<='F')?(C)-'A'+10:-1)
+
+
void image_get_color(INT32 args)
+
{
+
struct svalue s;
+
+
if (args!=1)
+
error("Image.color[]: illegal number of args");
+
+
if (!colors)
+
make_colors();
+
+
mapping_index_no_free(&s,colors,sp-1);
+
if (s.type==T_INT)
+
{
+
if (sp[-1].type==T_STRING &&
+
sp[-1].u.string->len>=4 &&
+
sp[-1].u.string->size_shift==0 &&
+
sp[-1].u.string->str[0]=='#')
+
{
+
/* #rgb, #rrggbb, #rrrgggbbb or #rrrrggggbbbb */
+
+
unsigned long i=sp[-1].u.string->len-1,j,k,rgb[3];
+
unsigned char *src=sp[-1].u.string->str+1;
+
if (!(i%3))
+
{
+
i/=3;
+
for (j=0; j<3; j++)
+
{
+
int z=0;
+
for (k=0; k<i; k++)
+
z=z*16+HEXTONUM(*src),src++;
+
switch (i)
+
{
+
case 1: z=(z<<12)+(z<<8)+(z<<4)+(z<<0); break;
+
case 2: z=(z<<8)+(z<<0); break;
+
case 3: z=(z<<4)+(z>>8); break;
+
}
+
switch (sizeof(COLORTYPE))
+
{
+
case 1: z>>=8; break;
+
case 4: z<<=16; break;
+
}
+
rgb[j]=z;
+
}
+
pop_n_elems(args);
+
push_int((INT32)rgb[0]);
+
push_int((INT32)rgb[1]);
+
push_int((INT32)rgb[2]);
+
push_object(clone_object(image_color_program,3));
+
+
return;
+
}
+
}
+
+
/* try other stuff here */
+
error("Image.color[]: no such color\n");
+
}
+
+
pop_stack();
+
*(sp++)=s;
+
}
+
+
void image_make_color(INT32 args)
+
{
+
struct svalue s;
+
+
if (args==1 && sp[-args].type==T_STRING)
+
{
+
image_get_color(args);
+
return;
+
}
+
+
push_object(clone_object(image_color_program,args));
+
}
+
+
void image_colors_indices(INT32 args)
+
{
+
pop_n_elems(args);
+
ref_push_mapping(colors);
+
f_indices(1);
+
}
+
+
void image_colors_values(INT32 args)
+
{
+
pop_n_elems(args);
+
ref_push_mapping(colors);
+
f_values(1);
+
}
+
+
void init_image_colors(void)
+
{
+
struct program *prg;
+
struct pike_string *str;
+
+
str_array=make_shared_string("array");
+
str_string=make_shared_string("string");
+
str_r=make_shared_string("r");
+
str_g=make_shared_string("g");
+
str_b=make_shared_string("b");
+
str_h=make_shared_string("h");
+
str_s=make_shared_string("s");
+
str_v=make_shared_string("v");
+
+
start_new_program();
+
+
add_storage(sizeof(struct color_struct));
+
set_init_callback(init_color_struct);
+
set_exit_callback(exit_color_struct);
+
+
add_function("create",image_color_create,
+
"function(:void)",0);
+
+
add_function("cast",image_color_cast,
+
"function(string:array|string)",0);
+
add_function("`[]",image_color_index,
+
"function(string|int:int|function)",0);
+
add_function("rgb",image_color_rgb,
+
"function(:array)",0);
+
add_function("name",image_color_name,
+
"function(:string)",0);
+
+
image_color_program=end_program();
+
+
start_new_program();
+
add_function("`[]",image_get_color,
+
"function(string:object)",0);
+
add_function("`()",image_make_color,
+
"function(string|int...:object)",0);
+
add_function("_indices",image_colors_indices,
+
"function(:array(string))",0);
+
add_function("_values",image_colors_values,
+
"function(:array(object))",0);
+
+
prg=end_program();
+
push_object(clone_object(prg,0));
+
free_program(prg);
+
str=make_shared_string("color");
+
add_constant(str,sp-1,0);
+
free_string(str);
+
pop_stack();
+
}
+
+
void exit_image_colors(void)
+
{
+
if (image_color_program)
+
{
+
free_program(image_color_program);
+
image_color_program=NULL;
+
}
+
if (colors)
+
{
+
free_mapping(colors);
+
free_object(colortable);
+
free_array(colornames);
+
+
colors=NULL;
+
colortable=NULL;
+
colornames=NULL;
+
}
+
free_string(str_array);
+
free_string(str_string);
+
free_string(str_r);
+
free_string(str_g);
+
free_string(str_b);
+
free_string(str_h);
+
free_string(str_s);
+
free_string(str_v);
+
}
Newline at end of file added.