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.6 1999/01/24 21:38:01 mirar Exp $ + **! $Id: colors.c,v 1.7 1999/01/26 02:02:31 mirar Exp $   **! submodule color   **!   **! This module keeps names and easy handling   **! for easy color support. It gives you an easy   **! way to get colors from names.   **!   **! A color is here an object, containing color   **! information and methods for conversion, see below.   **!   **! <ref>Image.color</ref> can be called to make a color object.
pike.git/src/modules/Image/colors.c:90:   **! This is the color object. It has six readable variables,   **! <tt>r</tt>, <tt>g</tt>, <tt>b</tt>, for the <i>red</i>,   **! <i>green</i> and <i>blue</i> values,   **! and <tt>h</tt>, <tt>s</tt>, <tt>v</tt>, for   **! the <i>hue</i>, <i>saturation</i> anv <i>value</i> values.   */      #include "global.h"   #include <config.h>    - RCSID("$Id: colors.c,v 1.6 1999/01/24 21:38:01 mirar Exp $"); + RCSID("$Id: colors.c,v 1.7 1999/01/26 02:02:31 mirar Exp $");      #include "config.h"      #include <math.h>      #include "stralloc.h"   #include "pike_macros.h"   #include "object.h"   #include "constants.h"   #include "interpret.h"
pike.git/src/modules/Image/colors.c:133:   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; +  rgbl_group rgbl;    struct pike_string *name;   };      /* forward */   static void image_make_rgb_color(INT32 args);   static void _image_make_rgb_color(INT32 r,INT32 g,INT32 b); -  + static void _image_make_rgbl_color(INT32 r,INT32 g,INT32 b); + static void _image_make_rgbf_color(float r,float g,float b);   static void image_make_hsv_color(INT32 args);   static void image_make_cmyk_color(INT32 args);   static void image_make_color(INT32 args);      struct html_color   {    int r,g,b;    char *name;    struct pike_string *pname;   } html_color[]=   {{0,0,0,"black",NULL}, {255,255,255,"white",NULL},    {0,128,0,"green",NULL}, {192,192,192,"silver",NULL},    {0,255,0,"lime",NULL}, {128,128,128,"gray",NULL},    {128,128,0,"olive",NULL}, {255,255,0,"yellow",NULL},    {128,0,0,"maroon",NULL}, {0,0,128,"navy",NULL},    {255,0,0,"red",NULL}, {0,0,255,"blue",NULL},    {128,0,128,"purple",NULL}, {0,128,128,"teal",NULL}, -  {255,255,0,"fuchsia",NULL}, {0,255,255,"aqua",NULL}}; +  {255,0,255,"fuchsia",NULL}, {0,255,255,"aqua",NULL}};      static void make_colors(void)   {    static struct color    {    int r,g,b;    char *name;    struct pike_string *pname;    } c[]={   #define COLOR(name,R,G,B) \
pike.git/src/modules/Image/colors.c:189:    struct color_struct *cs;    push_text(c[i].name);    copy_shared_string(c[i].pname,sp[-1].u.string);       push_object(clone_object(image_color_program,0));    cs=(struct color_struct*)    get_storage(sp[-1].u.object,image_color_program);    cs->rgb.r=(COLORTYPE)c[i].r;    cs->rgb.g=(COLORTYPE)c[i].g;    cs->rgb.b=(COLORTYPE)c[i].b; +  RGB_TO_RGBL(cs->rgbl,cs->rgb);    copy_shared_string(cs->name,c[i].pname);    }    f_aggregate_mapping(n*2);    colors=sp[-1].u.mapping;    sp--;       for (i=0;i<n;i++)    {    push_int(c[i].r);    push_int(c[i].g);
pike.git/src/modules/Image/colors.c:254:       if (!colors)    make_colors();       if (this->name)    {    free_string(this->name);    this->name=NULL;    }    +  if (this->rgbl.r!=COLOR_TO_COLORL(this->rgb.r) || +  this->rgbl.g!=COLOR_TO_COLORL(this->rgb.g) || +  this->rgbl.b!=COLOR_TO_COLORL(this->rgb.b)) +  return; +     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,
pike.git/src/modules/Image/colors.c:333:    {    get_all_args("Image.color.color->greylevel()",args,"%i%i%i",&r,&g,&b);    }    pop_n_elems(args);    if (r+g+b==0) r=g=b=1;    push_int((r*THIS->rgb.r+g*THIS->rgb.g+b*THIS->rgb.b)/(r+g+b));   }      #define MAX3(X,Y,Z) MAXIMUM(MAXIMUM(X,Y),Z)    - static void image_color_hsv(INT32 args) + static void image_color_hsvf(INT32 args)   {    float max, min;    float r,g,b, delta;    float h, s, v;       pop_n_elems(args);       if((THIS->rgb.r==THIS->rgb.g) && (THIS->rgb.g==THIS->rgb.b))    { -  push_int(0); -  push_int(0); -  push_int(THIS->rgb.r); +  push_float(0); +  push_float(0); +  push_float(COLORL_TO_FLOAT(THIS->rgbl.r));    f_aggregate(3);    return;    }    -  r = (float)(THIS->rgb.r)/((float)COLORMAX); -  g = (float)(THIS->rgb.g)/((float)COLORMAX); -  b = (float)(THIS->rgb.b)/((float)COLORMAX); +  r = COLORL_TO_FLOAT(THIS->rgbl.r); +  g = COLORL_TO_FLOAT(THIS->rgbl.g); +  b = COLORL_TO_FLOAT(THIS->rgbl.b);    max = MAX3(r,g,b);    min = -(MAX3(-r,-g,-b));       v = max;       if(max != 0.0)    s = (max - min)/max;    else    error("internal error, max==0.0\n");       delta = max-min;       if(r==max) h = (g-b)/delta;    else if(g==max) h = 2+(b-r)/delta;    else /*if(b==max)*/ h = 4+(r-g)/delta;    h *= 60; // now in degrees.    if(h<0) h+=360;    -  push_int((int)((h/360.0)*COLORMAX+0.5)); -  push_int((int)(s*COLORMAX+0.5)); -  push_int((int)(v*COLORMAX+0.5)); +  push_float(h); +  push_float(s); +  push_float(v);    f_aggregate(3);   }    -  + static void image_color_hsv(INT32 args) + { +  float h,s,v; +  image_color_hsvf(args); +  h=sp[-1].u.array->item[0].u.float_number; +  s=sp[-1].u.array->item[1].u.float_number; +  v=sp[-1].u.array->item[2].u.float_number; +  +  pop_stack(); +  push_int(FLOAT_TO_COLOR(h/360.0)); +  push_int(FLOAT_TO_COLOR(s)); +  push_int(FLOAT_TO_COLOR(v)); +  f_aggregate(3); + } +    static void image_color_cmyk(INT32 args)   {    float c,m,y,k; -  +  float r,g,b;    pop_n_elems(args);    -  k=255.0-MAX3(THIS->rgb.r,THIS->rgb.g,THIS->rgb.b); +  r=COLORL_TO_FLOAT(THIS->rgbl.r); +  g=COLORL_TO_FLOAT(THIS->rgbl.g); +  b=COLORL_TO_FLOAT(THIS->rgbl.b);    -  c=255.0-THIS->rgb.r-k; -  m=255.0-THIS->rgb.g-k; -  y=255.0-THIS->rgb.b-k; +  k=1.0-MAX3(r,g,b);    -  push_float(c*100.0/255.0); -  push_float(m*100.0/255.0); -  push_float(y/255.0*100.0); -  push_float(k/255.0*100.0); +  c=1.0-r-k; +  m=1.0-g-k; +  y=1.0-b-k; +  +  push_float(c*100.0); +  push_float(m*100.0); +  push_float(y*100.0); +  push_float(k*100.0);    f_aggregate(4);   }      /*   **! method object grey()   **! method object grey(int red,int green,int blue)   **! Gives a new color, containing a grey color,   **! which is calculated by the <ref>greylevel</ref> method.   **! returns a new <ref>Image.color.color</ref> object   **! see also: greylevel
pike.git/src/modules/Image/colors.c:461:    {    int sh;    if (i>8) i=8;       sh=4*(sizeof(COLORTYPE)*2-i);    if (sh>0)    sprintf(buf,"#%0*x%0*x%0*x",i,THIS->rgb.r>>sh,    i,THIS->rgb.g>>sh,i,THIS->rgb.b>>sh);    else    { -  unsigned INT32 r=THIS->rgb.r; -  unsigned INT32 g=THIS->rgb.g; -  unsigned INT32 b=THIS->rgb.b; -  const int q= -  ((sizeof(COLORTYPE)==1)?0x01010101: -  (sizeof(COLORTYPE)==2)?0x00010001:1); -  sh=32-i*4; -  sprintf(buf,"#%0*x%0*x%0*x",i,(r*q)>>sh,i,(g*q)>>sh,i,(b*q)>>sh); +  unsigned INT32 r=THIS->rgbl.r; +  unsigned INT32 g=THIS->rgbl.g; +  unsigned INT32 b=THIS->rgbl.b; +  sh=COLORLBITS-i*4; +  if (sh<0) +  { +  r=(r<<-sh)+(r>>(COLORLBITS+sh)); +  g=(g<<-sh)+(g>>(COLORLBITS+sh)); +  b=(b<<-sh)+(b>>(COLORLBITS+sh)); +  sh=0;    } -  +  sprintf(buf,"#%0*x%0*x%0*x", +  i,r>>sh,i,g>>sh,i,b>>sh);    } -  +  }    else -  switch (sizeof(COLORTYPE)) +  switch (sizeof(COLORTYPE)) /* constant */    {    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;
pike.git/src/modules/Image/colors.c:640:   {    if (args!=1)    error("Image.color.color->`==: illegal number of arguments");       if (sp[-1].type==T_OBJECT)    {    struct color_struct *other;    other=(struct color_struct*)    get_storage(sp[-1].u.object,image_color_program);    if (other&& -  other->rgb.r==THIS->rgb.r && -  other->rgb.g==THIS->rgb.g && -  other->rgb.b==THIS->rgb.b) +  other->rgbl.r==THIS->rgbl.r && +  other->rgbl.g==THIS->rgbl.g && +  other->rgbl.b==THIS->rgbl.b)    {    pop_stack();    push_int(1);    return;    }    }    else if (sp[-1].type==T_ARRAY)    {    if (sp[-1].u.array->size==3 &&    sp[-1].u.array->item[0].type==T_INT &&
pike.git/src/modules/Image/colors.c:744:   **! <ref>Image.color</ref>.white-><ref>light</ref>()-><ref>dark</ref>()   **! doesn't give the white color back, but the equal to   **! <ref>Image.color</ref>.white-><ref>dark</ref>(), since   **! white can't get any <ref>light</ref>er.   */         static void image_color_light(INT32 args)   {    pop_n_elems(args); -  image_color_hsv(0); +  image_color_hsvf(0);    sp--;    push_array_items(sp->u.array); /* frees */ -  sp[-1].u.integer+=50; +  sp[-1].u.float_number+=+0.2;    image_make_hsv_color(3);   }      static void image_color_dark(INT32 args)   {    pop_n_elems(args); -  image_color_hsv(0); +  image_color_hsvf(0);    sp--;    push_array_items(sp->u.array); /* frees */ -  sp[-1].u.integer-=50; +  sp[-1].u.float_number-=0.2;    image_make_hsv_color(3);   }      static void image_color_neon(INT32 args)   {    pop_n_elems(args); -  image_color_hsv(0); +  image_color_hsvf(0);    sp--;    push_array_items(sp->u.array); /* frees */ -  sp[-1].u.integer=255; -  sp[-2].u.integer=255; +  +  if (sp[-1].u.float_number==0.0 || +  sp[-2].u.float_number==0.0) +  { +  if (sp[-2].u.float_number<0.5) +  sp[-2].u.float_number=0.0; +  else +  sp[-2].u.float_number=1.0; +  } +  else +  { +  sp[-1].u.float_number=1.0; +  sp[-2].u.float_number=1.0; +  }    image_make_hsv_color(3);   }      static void image_color_dull(INT32 args)   {    pop_n_elems(args); -  image_color_hsv(0); +  +  image_color_hsvf(0);    sp--;    push_array_items(sp->u.array); /* frees */ -  sp[-2].u.integer-=50; -  sp[-1].u.integer-=50; +  +  if (sp[-1].u.float_number==0.0) +  { +  pop_n_elems(3); +  ref_push_object(THISOBJ); +  return; +  } +  +  sp[-2].u.float_number-=0.2;    image_make_hsv_color(3);   }      static void image_color_bright(INT32 args)   {    pop_n_elems(args); -  image_color_hsv(0); +  image_color_hsvf(0);    sp--;    push_array_items(sp->u.array); /* frees */ -  sp[-2].u.integer+=50; -  sp[-1].u.integer+=50; +  +  if (sp[-1].u.float_number==0.0) +  { +  pop_n_elems(3); +  ref_push_object(THISOBJ); +  return; +  } +  +  sp[-2].u.float_number+=0.2;    image_make_hsv_color(3);   }         static void image_color_mult(INT32 args)   {    float x=0.0;    get_all_args("Image.color.color->`*",args,"%f",&x);    pop_n_elems(args);    _image_make_rgb_color((int)(THIS->rgb.r*x),
pike.git/src/modules/Image/colors.c:849:    if (sp[-1].type==T_OBJECT)    {    struct color_struct *cs=(struct color_struct*)    get_storage(sp[-args].u.object,image_color_program);    *rgb=cs->rgb;    pop_stack();    return 1;    }    pop_stack();    } -  return NULL; +  return 0;   }      static void image_color_add(INT32 args)   {    rgb_group rgb;       if (!image_color_arg(args,&rgb))    error("Image.color.color->`+: Illegal argument(s)");       pop_n_elems(args);
pike.git/src/modules/Image/colors.c:901:    *(sp++)=s;    return;    }       if (sp[-1].type==T_STRING &&    sp[-1].u.string->size_shift==0)    {    if (sp[-1].u.string->len>=4 &&    sp[-1].u.string->str[0]=='#')    { -  /* #rgb, #rrggbb, #rrrgggbbb or #rrrrggggbbbb */ +  /* #rgb, #rrggbb, #rrrgggbbb, etc */       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++)    {    unsigned INT32 z=0;    for (k=0; k<i; k++)
pike.git/src/modules/Image/colors.c:924:    {    pop_stack();    push_int(0);    sp[-1].subtype=NUMBER_UNDEFINED;    return;    }    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; +  case 1: z=(z*0x11111111)>>(32-COLORLBITS); break; +  case 2: z=(z*0x01010101)>>(32-COLORLBITS); break; +  case 3: z=(z*0x00100100+(z>>8))>>(32-COLORLBITS); break;    -  case 5: z=(z>>4); break; -  case 6: z=(z>>8); break; -  case 7: z=(z>>12); break; -  case 8: z=(z>>16); break; +  case 4: +  case 5: +  case 6: +  case 7: +  case 8: +  if (i*4<COLORLBITS) +  z=(z<<(COLORLBITS-i*4))+(z>>(i*8-COLORLBITS)); +  else +  z=z>>(i*4-COLORLBITS); +  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]); -  image_make_rgb_color(3); -  +  _image_make_rgbl_color((INT32)rgb[0], +  (INT32)rgb[1], +  (INT32)rgb[2]);    return;    }    }    if (sp[-1].u.string->len>=4 &&    sp[-1].u.string->str[0]=='@')    {    /* @h,s,v; h=0..359, s,v=0..100 */    stack_dup();    push_text("@%f,%f,%f\n");    f_sscanf(2);
pike.git/src/modules/Image/colors.c:1007:    push_int(strlen(callables[n]));    push_int(1000000);    f_index(3);    image_get_color(1);    if (sp[-1].type!=T_OBJECT) return; /* no way */    safe_apply(sp[-1].u.object,callables[n],0);    stack_swap();    pop_stack();    return;    } +  if (sp[-1].u.string->len>=4 && +  sp[-1].u.string->str[0]=='g') +  { +  /* greyx; x=0..99 */ +  stack_dup(); +  push_text("grey%f\n"); +  f_sscanf(2); +  if (sp[-1].type==T_ARRAY && +  sp[-1].u.array->size==1) +  { +  float f; +  f=sp[-1].u.array->item[0].u.float_number; +  pop_stack(); +  sp--; +  +  return;    } -  +  pop_stack(); +  } +  }       /* try other stuff here */       pop_stack();    push_int(0);    sp[-1].subtype=NUMBER_UNDEFINED;    return;    }       pop_stack();
pike.git/src/modules/Image/colors.c:1090:   **! Creates a new color object from given red, green and blue,   **! hue, saturation and value, or greylevel, in color value range.   **! It could also be created from <i>cmyk</i> values in percent.   **!   **! The <ref>html</ref>() method only understands the HTML color names,   **! or the <tt>#rrggbb</tt> form. It is case insensitive.   **!   **! returns the created object.   */    + static void _image_make_rgbl_color(INT32 r,INT32 g,INT32 b) + { +  struct color_struct *cs; +  +  if (r<0) r=0; else if (r>COLORLMAX) r=COLORLMAX; /* >=2^31? no way... */ +  if (g<0) g=0; else if (g>COLORLMAX) g=COLORLMAX; +  if (b<0) b=0; else if (b>COLORLMAX) b=COLORLMAX; +  +  push_object(clone_object(image_color_program,0)); +  +  cs=(struct color_struct*) +  get_storage(sp[-1].u.object,image_color_program); +  +  cs->rgbl.r=(INT32)r; +  cs->rgbl.g=(INT32)g; +  cs->rgbl.b=(INT32)b; +  RGBL_TO_RGB(cs->rgb,cs->rgbl); +  +  try_find_name(cs); + } +  + static void _image_make_rgbf_color(float r,float g,float b) + { + #define FOO(X) FLOAT_TO_COLORL((X)<0.0?0.0:(X)>1.0?1.0:(X)) +  _image_make_rgbl_color(FOO(r),FOO(g),FOO(b)); + #undef FOO + } +    static void _image_make_rgb_color(INT32 r,INT32 g,INT32 b)   {    struct color_struct *cs;       if (r<0) r=0; else if (r>COLORMAX) r=COLORMAX;    if (g<0) g=0; else if (g>COLORMAX) g=COLORMAX;    if (b<0) b=0; else if (b>COLORMAX) b=COLORMAX;       push_object(clone_object(image_color_program,0));       cs=(struct color_struct*)    get_storage(sp[-1].u.object,image_color_program);       cs->rgb.r=(COLORTYPE)r;    cs->rgb.g=(COLORTYPE)g;    cs->rgb.b=(COLORTYPE)b; -  +  RGB_TO_RGBL(cs->rgbl,cs->rgb);       try_find_name(cs);   }      static void image_make_rgb_color(INT32 args)   {    INT32 r=0,g=0,b=0;       get_all_args("Image.color.rgb()",args,"%i%i%i",&r,&g,&b);       _image_make_rgb_color(r,g,b);   }      static void image_make_hsv_color(INT32 args)   {    float h,s,v; -  INT32 hi,si,vi; +     float r=0,g=0,b=0; /* to avoid warning */    -  +  if (args && sp[-args].type==T_INT) +  { +  INT32 hi,si,vi;    get_all_args("Image.color.hsv()",args,"%i%i%i",    &hi,&si,&vi);    pop_n_elems(args);       if (hi<0) hi=(hi%COLORMAX)+COLORMAX;    else if (hi>COLORMAX) hi%=COLORMAX; /* repeating */    if (si<0) si=0; else if (si>COLORMAX) si=COLORMAX;    if (vi<0) vi=0; else if (vi>COLORMAX) vi=COLORMAX;       h = (hi/((float)COLORMAX))*(360.0/60.0);    s = si/((float)COLORMAX);    v = vi/((float)COLORMAX); -  +  } +  else +  { +  get_all_args("Image.color.hsv()",args,"%f%f%f", +  &h,&s,&v); +  pop_n_elems(args); +  if (h<0) h=360+h-(((int)h/360)*360); +  if (h>360.0) h-=(((int)h/360)*360); +  h/=60; +  }    -  if(s==0.0 || si==0) +  if(s==0.0)    {    r = g = b = v;    } else {   #define i floor(h)   #define f (h-i)   #define p (v * (1 - s))   #define q (v * (1 - (s * f)))   #define t (v * (1 - (s * (1 -f))))    switch((int)i)    {    case 6: // 360 degrees. Same as 0..    case 0: r = v; g = t; b = p; break;    case 1: r = q; g = v; b = p; break;    case 2: r = p; g = v; b = t; break;    case 3: r = p; g = q; b = v; break;    case 4: r = t; g = p; b = v; break;    case 5: r = v; g = p; b = q; break; -  +  default: error("internal error\n");    }    }   #undef i   #undef f   #undef p   #undef q   #undef t - #define FOO(X) ((int)((X)<0.0?0:(X)>1.0?COLORMAX:(int)((X)*((float)COLORMAX)+0.5))) +     -  _image_make_rgb_color(FOO(r),FOO(g),FOO(b)); -  - #undef FOO +  _image_make_rgbf_color(r,g,b);   }      static void image_make_cmyk_color(INT32 args)   {    float c,m,y,k,r,g,b;    get_all_args("Image.color.cmyk()",args,"%F%F%F%F",&c,&m,&y,&k);    pop_n_elems(args);       r=100-(c+k);    g=100-(m+k);    b=100-(y+k);    -  _image_make_rgb_color((int)(r*255.4/100.0), -  (int)(g*255.4/100.0), -  (int)(b*255.4/100.0)); +  _image_make_rgbf_color(r*0.01,g*0.01,b*0.01);   }      static void image_make_greylevel_color(INT32 args)   {    INT32 i;       get_all_args("Image.color.greylevel()",args,"%i",&i);    pop_n_elems(args);       _image_make_rgb_color(i,i,i);
pike.git/src/modules/Image/colors.c:1276:       start_new_program();       add_storage(sizeof(struct color_struct));    set_init_callback(init_color_struct);    set_exit_callback(exit_color_struct);       /* color info methods */       add_function("cast",image_color_cast, -  "function(string:array|string)",OPT_TRY_OPTIMIZE); +  "function(string:array|string)",/* opt */0);    add_function("`[]",image_color_index, -  "function(string|int:int|function)",OPT_TRY_OPTIMIZE); +  "function(string|int:int|function)",/* opt */0);    add_function("`->",image_color_index, -  "function(string|int:int|function)",OPT_TRY_OPTIMIZE); +  "function(string|int:int|function)",/* opt */0);    add_function("`==",image_color_equal, -  "function(object|int:int)",OPT_TRY_OPTIMIZE); +  "function(object|int:int)",/* opt */0);       add_function("name",image_color_name, -  "function(:string)",OPT_TRY_OPTIMIZE); +  "function(:string)",/* opt */0);    add_function("hex",image_color_hex, -  "function(:string)",OPT_TRY_OPTIMIZE); +  "function(:string)",/* opt */0);    add_function("html",image_color_html, -  "function(:string)",OPT_TRY_OPTIMIZE); +  "function(:string)",/* opt */0);       add_function("rgb",image_color_rgb, -  "function(:array)",OPT_TRY_OPTIMIZE); +  "function(:array(int))",/* opt */0);    add_function("hsv",image_color_hsv, -  "function(:array)",OPT_TRY_OPTIMIZE); +  "function(:array(int))",/* opt */0); +  add_function("hsvf",image_color_hsvf, +  "function(:array(float))",/* opt */0);    add_function("cmyk",image_color_cmyk, -  "function(:array)",OPT_TRY_OPTIMIZE); +  "function(:array(float))",/* opt */0);    add_function("greylevel",image_color_greylevel, -  "function(:int)|function(int,int,int:int)",OPT_TRY_OPTIMIZE); +  "function(:int)|function(int,int,int:int)",/* opt */0);       /* color conversion methods */       add_function("grey",image_color_grey,    "function(:object)|function(int,int,int:object)", -  OPT_TRY_OPTIMIZE); +  /* opt */0);       add_function("light",image_color_light, -  "function(:object)",OPT_TRY_OPTIMIZE); +  "function(:object)",/* opt */0);    add_function("dark",image_color_dark, -  "function(:object)",OPT_TRY_OPTIMIZE); +  "function(:object)",/* opt */0);    add_function("neon",image_color_neon, -  "function(:object)",OPT_TRY_OPTIMIZE); +  "function(:object)",/* opt */0);    add_function("bright",image_color_bright, -  "function(:object)",OPT_TRY_OPTIMIZE); +  "function(:object)",/* opt */0);    add_function("dull",image_color_dull, -  "function(:object)",OPT_TRY_OPTIMIZE); +  "function(:object)",/* opt */0);       add_function("`*",image_color_mult, -  "function(float:object)",OPT_TRY_OPTIMIZE); +  "function(float:object)",/* opt */0);    add_function("`+",image_color_add, -  "function(object:object)",OPT_TRY_OPTIMIZE); +  "function(object:object)",/* opt */0);       image_color_program=end_program();       start_new_program();    add_function("`[]",image_get_color, -  "function(string:object)",OPT_TRY_OPTIMIZE); +  "function(string:object)",/* opt */0);    add_function("`()",image_make_color, -  "function(string|int...:object)",OPT_TRY_OPTIMIZE); +  "function(string|int...:object)",/* opt */0);    add_function("rgb",image_make_rgb_color, -  "function(int,int,int:object)",OPT_TRY_OPTIMIZE); +  "function(int,int,int:object)",/* opt */0);    add_function("hsv",image_make_hsv_color, -  "function(int,int,int:object)",OPT_TRY_OPTIMIZE); +  "function(int,int,int:object)|" +  "function(float,float,float:object)",/* opt */0);    add_function("cmyk",image_make_cmyk_color,    "function(int|float,int|float,int|float,int|float:object)", -  OPT_TRY_OPTIMIZE); +  /* opt */0);    add_function("html",image_make_html_color, -  "function(string:object)",OPT_TRY_OPTIMIZE); +  "function(string:object)",/* opt */0);    add_function("guess",image_guess_color, -  "function(string:object)",OPT_TRY_OPTIMIZE); +  "function(string:object)",/* opt */0);    add_function("greylevel",image_make_greylevel_color, -  "function(int:object)",OPT_TRY_OPTIMIZE); +  "function(int:object)",/* opt */0);    add_function("_indices",image_colors_indices, -  "function(:array(string))",OPT_TRY_OPTIMIZE); +  "function(:array(string))",/* opt */0);    add_function("_values",image_colors_values, -  "function(:array(object))",OPT_TRY_OPTIMIZE); +  "function(:array(object))",/* opt */0);       add_program_constant("color",image_color_program,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();