pike.git / src / modules / Image / colors.c

version» Context lines:

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.