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.5 1999/01/24 17:31:02 mirar Exp $ + **! $Id: colors.c,v 1.6 1999/01/24 21:38:01 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.5 1999/01/24 17:31:02 mirar Exp $"); + RCSID("$Id: colors.c,v 1.6 1999/01/24 21:38:01 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:136:   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;   };    - void image_make_hsv_color(INT32 args); /* forward */ - void image_make_cmyk_color(INT32 args); /* forward */ + /* 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_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},
pike.git/src/modules/Image/colors.c:175:   #undef COLOR    };    int i;    const int n=sizeof(c)/sizeof(c[0]);       for (i=0; (size_t)i<sizeof(html_color)/sizeof(html_color[0]); i++)    html_color[i].pname=make_shared_string(html_color[i].name);       for (i=0;i<n;i++)    { +  struct color_struct *cs;    push_text(c[i].name);    copy_shared_string(c[i].pname,sp[-1].u.string); -  push_int(c[i].r); -  push_int(c[i].g); -  push_int(c[i].b); -  push_text(c[i].name); -  push_object(clone_object(image_color_program,4)); +  +  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; +  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);    push_int(c[i].b);
pike.git/src/modules/Image/colors.c:218:    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) + static 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) + static void exit_color_struct(struct object *dummy)   {    if (THIS->name)    {    free_string(THIS->name);    THIS->name=NULL;    }   }    - static void try_find_name(void) + static void try_find_name(struct color_struct *this)   {    rgb_group d;       if (!colors)    make_colors();    -  if (THIS->name) +  if (this->name)    { -  free_string(THIS->name); -  THIS->name=NULL; +  free_string(this->name); +  this->name=NULL;    }       image_colortable_map_image((struct neo_colortable*)colortable->storage, -  &(THIS->rgb),&d,1,1); +  &(this->rgb),&d,1,1);    -  if (d.r==THIS->rgb.r && -  d.g==THIS->rgb.g && -  d.b==THIS->rgb.b) +  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); +  &(this->rgb),&d2,1,1);       if (d2<colornames->size)    { -  copy_shared_string(THIS->name, +  copy_shared_string(this->name,    colornames->item[d2].u.string);    }    }   }      /*   **! method void create(int r,int g,int b)   **! This is the main <ref>Image.color.color</ref> creation   **! method, mostly for internal use.   **----- internal note: it takes a fourth argument, name of color ---   **!   */ -  - void image_color_create(INT32 args) - { -  if (args==4) /* r,g,b,name */ -  { -  INT32 r,g,b; -  get_all_args("Image.color.color->create()",args,"%i%i%i%W", -  &r,&g,&b,&(THIS->name)); -  -  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; -  -  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.color->create()",args,"%i%i%i", -  &r,&g,&b); -  -  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; -  -  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.color->create(): Illegal argument(s)\n"); -  -  push_int(0); - } -  +    /*   **! method array(int) rgb()   **! method array(int) hsv()   **! method array(int) cmyk()   **! method int greylevel()   **! method int greylevel(int r, int g, int b)   **! This is methods of getting information from an   **! <ref>Image.color.color</ref> object.   **!   **! They give an array of
pike.git/src/modules/Image/colors.c:340:   **! or the greylevel value (range as color value).   **!   **! The greylevel is calculated by weighting red, green   **! and blue. Default weights are 87, 127 and 41, respective,   **! and could be given by argument.   **!   **! returns array(int) respective int   **! see also: Image.color.color, grey   */    - void image_color_rgb(INT32 args) + static 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_greylevel(INT32 args) + static void image_color_greylevel(INT32 args)   {    INT32 r,g,b;    if (args==0)    {    r=87;    g=127;    b=41;    }    else    {    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)    - void image_color_hsv(INT32 args) + static void image_color_hsv(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);
pike.git/src/modules/Image/colors.c:413:    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));    f_aggregate(3);   }    - void image_color_cmyk(INT32 args) + static void image_color_cmyk(INT32 args)   {    float c,m,y,k;    pop_n_elems(args);       k=255.0-MAX3(THIS->rgb.r,THIS->rgb.g,THIS->rgb.b);       c=255.0-THIS->rgb.r-k;    m=255.0-THIS->rgb.g-k;    y=255.0-THIS->rgb.b-k;   
pike.git/src/modules/Image/colors.c:440:      /*   **! 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   */    - void image_color_grey(INT32 args) + static void image_color_grey(INT32 args)   {    image_color_greylevel(args);    stack_dup();    stack_dup(); -  push_object(clone_object(image_color_program,3)); +  image_make_rgb_color(3);   }      /*   **! method string hex()   **! method string hex(int n)   **! method string name()   **! method string html()   **! Information methods.   **!   **! <ref>hex</ref>() simply gives a string on the <tt>#rrggbb</tt>
pike.git/src/modules/Image/colors.c:472:   **! per default is the <ref>hex</ref>() method use.   **!   **! <ref>html</ref>() gives the <tt>HTML</tt> name of   **! the color, or the <ref>hex</ref>(2) if it isn't one   **! of the 16 <tt>HTML</tt> colors.   **!   **! returns a new <ref>Image.color.color</ref> object   **! see also: rgb, hsv, Image.color   */    - void image_color_hex(INT32 args) + static void image_color_hex(INT32 args)   {    char buf[80];    INT32 i=sizeof(COLORTYPE)*2;       if (args)    get_all_args("Image.color.color->hex()",args,"%i",&i);       pop_n_elems(args);    if (i<1)    {
pike.git/src/modules/Image/colors.c:525:    break;    case 4:    sprintf(buf,"#%08x%08x%08x",THIS->rgb.r,THIS->rgb.g,THIS->rgb.b);    break;    default:    error("unknown size of colortype\n");    }    push_text(buf);   }    - void image_color_html(INT32 args) + static void image_color_html(INT32 args)   {    int i;       if (!colors) make_colors();       pop_n_elems(args);       for (i=0; (size_t)i<sizeof(html_color)/sizeof(html_color[0]); i++)    if (THIS->rgb.r==html_color[i].r &&    THIS->rgb.g==html_color[i].g &&    THIS->rgb.b==html_color[i].b)    {    ref_push_string(html_color[i].pname);    return;    }       push_int(2);    image_color_hex(1);   }    - void image_color_name(INT32 args) + static void image_color_name(INT32 args)   {    pop_n_elems(args);    if (THIS->name)    ref_push_string(THIS->name);    else    image_color_hex(0);   }      /*   **! method array|string cast()   **! cast the object to an array, representing red, green   **! and blue (equal to <tt>-><ref>rgb</ref>()</tt>), or   **! to a string, giving the name (equal to <tt>-><ref>name</ref>()</tt>).   **! returns the name as string or rgb as array   **! see also: rgb, name   */    - void image_color_cast(INT32 args) + static void image_color_cast(INT32 args)   {    if (args!=1 ||    sp[-1].type!=T_STRING)    error("Image.color.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.color->cast(): Can't cast to that\n");   }    - void image_color_index(INT32 args) + static void image_color_index(INT32 args)   {    struct svalue s;       if (args!=1)    error("Image.color[]: illegal number of arguments\n");       object_index_no_free2(&s,THISOBJ,sp-1);    if (s.type==T_INT && sp[-1].type==T_STRING)    {    if (sp[-1].u.string==str_r)
pike.git/src/modules/Image/colors.c:665:   **! if (black==0) ...   **! if (red=="red") ...   **! </pre>   **!   **! returns 1 or 0   **! see also: rgb, grey, name   **! note:   **! The other datatype (not color object) must be to the right!   */    - void image_color_equal(INT32 args) + static void image_color_equal(INT32 args)   {    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&&
pike.git/src/modules/Image/colors.c:777:   **! The opposites may not always take each other out.   **! The color is maximised at white and black levels,   **! so, for instance   **! <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.   */       - void image_color_light(INT32 args) + static void image_color_light(INT32 args)   {    pop_n_elems(args);    image_color_hsv(0);    sp--;    push_array_items(sp->u.array); /* frees */    sp[-1].u.integer+=50;    image_make_hsv_color(3);   }    - void image_color_dark(INT32 args) + static void image_color_dark(INT32 args)   {    pop_n_elems(args);    image_color_hsv(0);    sp--;    push_array_items(sp->u.array); /* frees */    sp[-1].u.integer-=50;    image_make_hsv_color(3);   }    - void image_color_neon(INT32 args) + static void image_color_neon(INT32 args)   {    pop_n_elems(args);    image_color_hsv(0);    sp--;    push_array_items(sp->u.array); /* frees */    sp[-1].u.integer=255;    sp[-2].u.integer=255;    image_make_hsv_color(3);   }    - void image_color_dull(INT32 args) + static void image_color_dull(INT32 args)   {    pop_n_elems(args);    image_color_hsv(0);    sp--;    push_array_items(sp->u.array); /* frees */    sp[-2].u.integer-=50;    sp[-1].u.integer-=50;    image_make_hsv_color(3);   }    - void image_color_bright(INT32 args) + static void image_color_bright(INT32 args)   {    pop_n_elems(args);    image_color_hsv(0);    sp--;    push_array_items(sp->u.array); /* frees */    sp[-2].u.integer+=50;    sp[-1].u.integer+=50;    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), +  (int)(THIS->rgb.g*x), +  (int)(THIS->rgb.b*x)); + } +  + static int image_color_arg(INT32 args,rgb_group *rgb) + { +  if (!args) return 0; +  if (sp[-args].type==T_OBJECT) +  { +  struct color_struct *cs=(struct color_struct*) +  get_storage(sp[-args].u.object,image_color_program); +  +  if (cs) +  { +  *rgb=cs->rgb; +  return 1; +  } +  } +  else if (sp[-args].type==T_ARRAY) +  { +  int n=sp[-args].u.array->size; +  add_ref(sp[-args].u.array); +  push_array_items(sp[-args].u.array); +  image_make_color(n); +  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(); +  } +  else if (sp[-args].type==T_STRING) +  { +  push_svalue(sp-args); +  image_make_color(1); +  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; + } +  + 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); +  _image_make_rgb_color((int)(THIS->rgb.r+rgb.r), +  (int)(THIS->rgb.g+rgb.g), +  (int)(THIS->rgb.b+rgb.b)); + } +  +  +    #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) + static void image_get_color(INT32 args)   {    struct svalue s;    int n;    static char *callables[]={"light","dark","neon","dull","bright"};       if (args!=1)    error("Image.color[]: illegal number of args");       if (!colors)    make_colors();
pike.git/src/modules/Image/colors.c:907:    {    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)); +  image_make_rgb_color(3);       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");
pike.git/src/modules/Image/colors.c:984:    pop_stack();    push_int(0);    sp[-1].subtype=NUMBER_UNDEFINED;    return;    }       pop_stack();    *(sp++)=s;   }    - void image_guess_color(INT32 args) + static void image_guess_color(INT32 args)   {    struct svalue s;       if (args!=1 && sp[-args].type!=T_STRING)    error("Image.color->guess(): illegal argument(s)\n");       f_lower_case(1);    push_text(" ");    o_subtract();   
pike.git/src/modules/Image/colors.c:1011:    return;    }    pop_stack();    push_text("#");    stack_swap();    f_add(2);       image_get_color(1);   }    - void image_make_color(INT32 args) + static 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)); +  image_make_rgb_color(args);   }         /*   **! module Image   **! submodule color   **!   **! method object guess(string)   **! This is equivalent to   **! <tt><ref>Image.color</ref>(lower_case(str)-" ")</tt>,
pike.git/src/modules/Image/colors.c:1054:   **! 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.   */    - void image_make_rgb_color(INT32 args) + static void _image_make_rgb_color(INT32 r,INT32 g,INT32 b)   { -  if (args!=3) -  { -  error("Image.color.rgb(): illegal number of arguments\n"); -  return; +  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; +  +  try_find_name(cs);   }    -  push_object(clone_object(image_color_program,args)); + 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);   }    - void image_make_hsv_color(INT32 args) + 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 */       get_all_args("Image.color.hsv()",args,"%i%i%i",    &hi,&si,&vi);    pop_n_elems(args);       if (hi<0) hi=(hi%COLORMAX)+COLORMAX;
pike.git/src/modules/Image/colors.c:1110:    case 4: r = t; g = p; b = v; break;    case 5: r = v; g = p; b = q; break;    }    }   #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))) -  push_int(FOO(r)); -  push_int(FOO(g)); -  push_int(FOO(b)); +     -  push_object(clone_object(image_color_program,3)); +  _image_make_rgb_color(FOO(r),FOO(g),FOO(b)); +  + #undef FOO   }    - void image_make_cmyk_color(INT32 args) + 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);    -  push_int((int)(r*255.4/100.0)); -  push_int((int)(g*255.4/100.0)); -  push_int((int)(b*255.4/100.0)); -  -  push_object(clone_object(image_color_program,3)); +  _image_make_rgb_color((int)(r*255.4/100.0), +  (int)(g*255.4/100.0), +  (int)(b*255.4/100.0));   }    - void image_make_greylevel_color(INT32 args) + static void image_make_greylevel_color(INT32 args)   {    INT32 i;       get_all_args("Image.color.greylevel()",args,"%i",&i);    pop_n_elems(args);    -  push_int(i); -  push_int(i); -  push_int(i); -  -  push_object(clone_object(image_color_program,3)); +  _image_make_rgb_color(i,i,i);   }    - void image_make_html_color(INT32 args) + static void image_make_html_color(INT32 args)   {    int i;       if (args!=1 ||    sp[-1].type!=T_STRING)    {    error("Image.color.html(): illegal arguments\n");    return;    }       f_lower_case(1);    for (i=0; (size_t)i<sizeof(html_color)/sizeof(html_color[0]); i++)    if (html_color[i].pname==sp[-1].u.string)    { -  push_int(html_color[i].r); -  push_int(html_color[i].g); -  push_int(html_color[i].b); -  push_object(clone_object(image_color_program,3)); +  _image_make_rgb_color(html_color[i].r, +  html_color[i].g, +  html_color[i].b);    return;    }       if (sp[-1].u.string->len>0 &&    sp[-1].u.string->str[0]=='#') -  push_object(clone_object(image_color_program,1)); +  image_get_color(1);    else    {    push_text("#");    stack_swap();    f_add(2); -  push_object(clone_object(image_color_program,1)); +  image_get_color(1);    }   }      /*   **! method array(string) _indices()   **! method array(object) _values()   **! (ie as <tt>indices(Image.color)</tt> or <tt>values(Image.color)</tt>)   **! <tt>indices</tt> gives a list of all the known color names,   **! <tt>values</tt> gives there corresponding objects.   **! see also: Image.color   */    - void image_colors_indices(INT32 args) + static void image_colors_indices(INT32 args)   {    pop_n_elems(args);    if (!colors) make_colors();    ref_push_mapping(colors);    f_indices(1);   }    - void image_colors_values(INT32 args) + static void image_colors_values(INT32 args)   {    pop_n_elems(args);    if (!colors) make_colors();    ref_push_mapping(colors);    f_values(1);   }      void init_image_colors(void)   {    struct program *prg;
pike.git/src/modules/Image/colors.c:1227:    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); -  +     /* color info methods */       add_function("cast",image_color_cast,    "function(string:array|string)",OPT_TRY_OPTIMIZE);    add_function("`[]",image_color_index,    "function(string|int:int|function)",OPT_TRY_OPTIMIZE);    add_function("`->",image_color_index,    "function(string|int:int|function)",OPT_TRY_OPTIMIZE);    add_function("`==",image_color_equal,    "function(object|int:int)",OPT_TRY_OPTIMIZE);
pike.git/src/modules/Image/colors.c:1274:    "function(:object)",OPT_TRY_OPTIMIZE);    add_function("dark",image_color_dark,    "function(:object)",OPT_TRY_OPTIMIZE);    add_function("neon",image_color_neon,    "function(:object)",OPT_TRY_OPTIMIZE);    add_function("bright",image_color_bright,    "function(:object)",OPT_TRY_OPTIMIZE);    add_function("dull",image_color_dull,    "function(:object)",OPT_TRY_OPTIMIZE);    +  add_function("`*",image_color_mult, +  "function(float:object)",OPT_TRY_OPTIMIZE); +  add_function("`+",image_color_add, +  "function(object:object)",OPT_TRY_OPTIMIZE); +     image_color_program=end_program();       start_new_program();    add_function("`[]",image_get_color,    "function(string:object)",OPT_TRY_OPTIMIZE);    add_function("`()",image_make_color,    "function(string|int...:object)",OPT_TRY_OPTIMIZE);    add_function("rgb",image_make_rgb_color,    "function(int,int,int:object)",OPT_TRY_OPTIMIZE);    add_function("hsv",image_make_hsv_color,