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

version» Context lines:

pike.git/src/modules/Image/layers.c:1:   /*   **! module Image   **! note - **! $Id: layers.c,v 1.31 1999/08/09 14:46:41 mirar Exp $ + **! $Id: layers.c,v 1.32 1999/08/10 10:13:21 mirar Exp $   **! class Layer   **! see also: layers   **!      **!   **!   **! <add_appendix name="layers" title="Image.Layer modes"><execute>   **! import Image;   **!   **! void write_image(string desc,
pike.git/src/modules/Image/layers.c:188:   **! }   **!   **! </execute>   **! </add_appendix>   */      #include "global.h"      #include <math.h> /* floor */    - RCSID("$Id: layers.c,v 1.31 1999/08/09 14:46:41 mirar Exp $"); + RCSID("$Id: layers.c,v 1.32 1999/08/10 10:13:21 mirar Exp $");      #include "image_machine.h"      #include "stralloc.h"   #include "pike_macros.h"   #include "object.h"   #include "constants.h"   #include "interpret.h"   #include "svalue.h"   #include "array.h"
pike.git/src/modules/Image/layers.c:323:   LMFUNC(lm_less_or_equal);   LMFUNC(lm_more_or_equal);      LMFUNC(lm_logic_equal);   LMFUNC(lm_logic_not_equal);   LMFUNC(lm_logic_strict_less);   LMFUNC(lm_logic_strict_more);   LMFUNC(lm_logic_strict_less_or_equal);   LMFUNC(lm_logic_strict_more_or_equal);    + static void lm_spec_burn_alpha(struct layer *ly, +  rgb_group *l, rgb_group *la, +  rgb_group *s, rgb_group *sa, +  rgb_group *d, rgb_group *da, +  int len); +    struct layer_mode_desc   {    char *name;    lm_row_func *func;    int optimize_alpha; /* alpha 0 -> skip layer */    struct pike_string *ps;   } layer_mode[]=   {    {"normal", lm_normal, 1, NULL },    {"add", lm_add, 1, NULL },
pike.git/src/modules/Image/layers.c:369:    {"lighten", lm_lighten, 1, NULL },    {"saturate", lm_saturate, 1, NULL },    {"desaturate", lm_desaturate, 1, NULL },       {"dissolve", lm_dissolve, 1, NULL },    {"behind", lm_behind, 1, NULL },    {"erase", lm_erase, 1, NULL },       {"screen", lm_screen, 1, NULL },    {"overlay", lm_overlay, 1, NULL }, +  {"burn_alpha", (lm_row_func*)lm_spec_burn_alpha, 1, NULL },       {"equal", lm_equal, 0, NULL },    {"not_equal", lm_not_equal, 0, NULL },    {"less", lm_less, 0, NULL },    {"more", lm_more, 0, NULL },    {"less_or_equal", lm_less_or_equal, 0, NULL },    {"more_or_equal", lm_more_or_equal, 0, NULL },       {"logic_equal", lm_logic_equal, 0, NULL },    {"logic_not_equal",lm_logic_not_equal,0, NULL },
pike.git/src/modules/Image/layers.c:1231:   /*** layer mode definitions ***************************/      static void lm_normal(rgb_group *s,rgb_group *l,rgb_group *d,    rgb_group *sa,rgb_group *la,rgb_group *da,    int len,double alpha)   {    /* la may be NULL, no other */       if (alpha==0.0) /* optimized */    { + #ifdef LAYERS_DUAL    MEMCPY(d,s,sizeof(rgb_group)*len);    MEMCPY(da,sa,sizeof(rgb_group)*len); -  + #endif    return;    }    else if (alpha==1.0)    {    if (!la) /* no layer alpha => full opaque */    {    MEMCPY(d,l,sizeof(rgb_group)*len);    smear_color(da,white,len);    }    else -  +  {    while (len--)    { -  if (la->r==COLORMAX && la->g==COLORMAX && la->b==COLORMAX) +  if (la->r==0 && la->g==0 && la->b==0)    { -  +  int n=0; +  do +  { +  n++; la++; +  } +  while (len && len-- && la->r==0 && la->g==0 && la->b==0); +  if (n>1) +  { +  MEMCPY(d,s,n*sizeof(rgb_group)); +  MEMCPY(da,sa,n*sizeof(rgb_group)); +  l+=n; s+=n; sa+=n; d+=n; da+=n; +  } +  else +  *(d++)=*(s++),*(da++)=*(sa++),l++; +  continue; +  } +  else if (la->r==COLORMAX && la->g==COLORMAX && la->b==COLORMAX) +  {    *d=*l;    *da=*la;    } -  else if (la->r==0 && la->g==0 && la->b==0) +  else if (l->r==COLORMAX && l->g==COLORMAX && l->b==COLORMAX)    { -  *d=*s; -  *da=*sa; +  ALPHA_ADD(s,&white,d,sa,la,da,r); +  ALPHA_ADD(s,&white,d,sa,la,da,g); +  ALPHA_ADD(s,&white,d,sa,la,da,b);    }    else    {    ALPHA_ADD(s,l,d,sa,la,da,r);    ALPHA_ADD(s,l,d,sa,la,da,g);    ALPHA_ADD(s,l,d,sa,la,da,b);    }    l++; s++; la++; sa++; d++; da++;    }    } -  +  }    else    {    if (!la) /* no layer alpha => alpha value opaque */    while (len--)    {    ALPHA_ADD_V_NOLA(s,l,d,sa,da,alpha,r);    ALPHA_ADD_V_NOLA(s,l,d,sa,da,alpha,g);    ALPHA_ADD_V_NOLA(s,l,d,sa,da,alpha,b);       l++; s++; la++; sa++; da++; d++;
pike.git/src/modules/Image/layers.c:1757:   #undef L_CHANNEL_DO      /* special modes */      static void lm_dissolve(rgb_group *s,rgb_group *l,rgb_group *d,    rgb_group *sa,rgb_group *la,rgb_group *da,    int len,double alpha)   {    if (alpha==0.0)    { + #ifdef LAYERS_DUAL    MEMCPY(d,s,sizeof(rgb_group)*len);    MEMCPY(da,sa,sizeof(rgb_group)*len); -  + #endif    return;    }    else if (alpha==1.0)    {    if (!la) /* no layer alpha => full opaque */    {    MEMCPY(d,l,sizeof(rgb_group)*len);    smear_color(da,white,len);    }    else
pike.git/src/modules/Image/layers.c:1814:   }      static void lm_behind(rgb_group *s,rgb_group *l,rgb_group *d,    rgb_group *sa,rgb_group *la,rgb_group *da,    int len,double alpha)   {    /* la may be NULL, no other */       if (alpha==0.0) /* optimized */    { + #ifdef LAYERS_DUAL    MEMCPY(d,s,sizeof(rgb_group)*len);    MEMCPY(da,sa,sizeof(rgb_group)*len); -  + #endif    return;    }    else if (alpha==1.0)    while (len--)    {    if (sa->r==COLORMAX && sa->g==COLORMAX && sa->b==COLORMAX)    {    *d=*s;    *da=*sa;    }
pike.git/src/modules/Image/layers.c:1882:    if (la) la++;    }   }      static void lm_erase(rgb_group *s,rgb_group *l,rgb_group *d,    rgb_group *sa,rgb_group *la,rgb_group *da,    int len,double alpha)   {    /* la may be NULL, no other */    + #ifdef LAYERS_DUAL    MEMCPY(d,s,sizeof(rgb_group)*len); -  + #endif       if (alpha==1.0)    if (!la) /* full opaque */    smear_color(da,black,len);    else    while (len--)    {    da->r=CCUT(sa->r*(int)(COLORMAX-la->r));    da->g=CCUT(sa->g*(int)(COLORMAX-la->g));    da->b=CCUT(sa->b*(int)(COLORMAX-la->b));
pike.git/src/modules/Image/layers.c:1914:    while (len--)    {    da->r=CCUT(sa->r*(int)(COLORMAX-alpha*la->r));    da->g=CCUT(sa->g*(int)(COLORMAX-alpha*la->g));    da->b=CCUT(sa->b*(int)(COLORMAX-alpha*la->b));       la++; sa++; da++;    }   }    + static void lm_spec_burn_alpha(struct layer *ly, +  rgb_group *l, rgb_group *la, +  rgb_group *s, rgb_group *sa, +  rgb_group *d, rgb_group *da, +  int len) +  + { +  /* special optimized */ +  if (!la) +  { + #ifdef LAYERS_DUAL +  MEMCPY(d,s,len*sizeof(rgb_group)); +  MEMCPY(da,sa,len*sizeof(rgb_group)); + #endif +  return; +  } +  +  if (ly->alpha_value==1.0) +  if (!l) +  if (ly->fill.r==COLORMAX && +  ly->fill.g==COLORMAX && +  ly->fill.b==COLORMAX) +  { +  smear_color(d,white,len); +  while (len--) +  { +  da->r=MINIMUM(sa->r+la->r,COLORMAX); +  da->g=MINIMUM(sa->g+la->g,COLORMAX); +  da->b=MINIMUM(sa->b+la->b,COLORMAX); +  da++; sa++; la++; +  } +  } +  else if (ly->fill.r!=0 || +  ly->fill.g!=0 || +  ly->fill.b!=0) +  { +  rgb_group fill=ly->fill; +  while (len--) +  { +  d->r=MINIMUM(s->r+fill.r,COLORMAX); +  d->g=MINIMUM(s->g+fill.g,COLORMAX); +  d->b=MINIMUM(s->b+fill.b,COLORMAX); +  da->r=MINIMUM(sa->r+la->r,COLORMAX); +  da->g=MINIMUM(sa->g+la->g,COLORMAX); +  da->b=MINIMUM(sa->b+la->b,COLORMAX); +  da++; sa++; la++; d++; s++; +  } +  } +  else +  { + #ifdef LAYERS_DUAL +  MEMCPY(d,s,len*sizeof(rgb_group)); + #endif +  while (len--) +  { +  da->r=MINIMUM(sa->r+la->r,COLORMAX); +  da->g=MINIMUM(sa->g+la->g,COLORMAX); +  da->b=MINIMUM(sa->b+la->b,COLORMAX); +  da++; sa++; la++; +  } +  } +  else +  while (len--) +  { +  if ((s->r==COLORMAX && +  s->g==COLORMAX && +  s->b==COLORMAX)) +  { +  *d=*s; +  } +  else +  { +  d->r=MINIMUM(s->r+l->r,COLORMAX); +  d->g=MINIMUM(s->g+l->g,COLORMAX); +  d->b=MINIMUM(s->b+l->b,COLORMAX); +  } +  da->r=MINIMUM(sa->r+la->r,COLORMAX); +  da->g=MINIMUM(sa->g+la->g,COLORMAX); +  da->b=MINIMUM(sa->b+la->b,COLORMAX); +  da++; sa++; la++; s++; d++; +  if (l) l++; +  } +  else +  { +  double alpha=ly->alpha_value; +  while (len--) +  { +  if ((s->r==COLORMAX && +  s->g==COLORMAX && +  s->b==COLORMAX) +  || !l) +  { +  *d=*s; +  da->r=MINIMUM(sa->r+(COLORTYPE)(alpha*la->r),COLORMAX); +  da->g=MINIMUM(sa->g+(COLORTYPE)(alpha*la->g),COLORMAX); +  da->b=MINIMUM(sa->b+(COLORTYPE)(alpha*la->b),COLORMAX); +  } +  else +  { +  d->r=s->r+(COLORTYPE)(alpha*l->r); +  d->g=s->g+(COLORTYPE)(alpha*l->g); +  d->b=s->b+(COLORTYPE)(alpha*l->b); +  +  da->r=MINIMUM(sa->r+(COLORTYPE)(alpha*l->r),COLORMAX); +  da->g=MINIMUM(sa->g+(COLORTYPE)(alpha*l->g),COLORMAX); +  da->b=MINIMUM(sa->b+(COLORTYPE)(alpha*l->b),COLORMAX); +  } +  da++; sa++; la++; s++; d++; +  } +  } + } +    /*** the add-layer function ***************************/      static INLINE void img_lay_first_line(struct layer *l,    int xoffs,int xsize,    int y, /* in _this_ layer */    rgb_group *d,rgb_group *da)   {    if (!l->tiled)    {    rgb_group *s,*sa;
pike.git/src/modules/Image/layers.c:2023:      static INLINE void img_lay_stroke(struct layer *ly,    rgb_group *l,    rgb_group *la,    rgb_group *s,    rgb_group *sa,    rgb_group *d,    rgb_group *da,    int len)   { +  if (ly->row_func==lm_spec_burn_alpha) +  { +  lm_spec_burn_alpha(ly,l,la,s,sa,d,da,len); +  return; +  } +     if (l)    {    (ly->row_func)(s,l,d,sa,la,da,len,ly->alpha_value);    return;    } -  +     if (!la && ly->really_optimize_alpha)    {   /* fprintf(stderr,"fast skip ly->yoffs=%d\n",ly->yoffs); */ -  + #ifdef LAYERS_DUAL    MEMCPY(d,s,len*sizeof(rgb_group));    MEMCPY(da,sa,len*sizeof(rgb_group)); -  + #endif    return;    }       if (!la &&    ly->fill_alpha.r==COLORMAX &&    ly->fill_alpha.g==COLORMAX &&    ly->fill_alpha.b==COLORMAX)    {    while (len>SNUMPIXS)    {
pike.git/src/modules/Image/layers.c:2058:    if (l) l+=SNUMPIXS;    len-=SNUMPIXS;    }    if (len)    (ly->row_func)(s,l?l:ly->sfill,d,sa,NULL,da,len,ly->alpha_value);    }    else    {    int i;    + /* fprintf(stderr,"ly=%p len=%d\n",ly,len); */ +     while (len>SNUMPIXS)    {    (ly->row_func)(s,l?l:ly->sfill,d,sa,la?la:ly->sfill_alpha,da,    SNUMPIXS,ly->alpha_value);    s+=SNUMPIXS; d+=SNUMPIXS;    sa+=SNUMPIXS; da+=SNUMPIXS;    if (l) l+=SNUMPIXS;    if (la) la+=SNUMPIXS;    len-=SNUMPIXS;    }
pike.git/src/modules/Image/layers.c:2172:    if (xsize)    img_lay_stroke(ly,l,la,s,sa,d,da,xsize);    }   }         void img_lay(struct layer **layer,    int layers,    struct layer *dest)   { -  rgb_group *line1,*line2,*aline1,*aline2; + #ifdef LAYERS_DUAL +  rgb_group *line1,*aline1; +  rgb_group *line2,*aline2; + #endif    rgb_group *d,*da;    int width=dest->xsize;    int y,z;    int xoffs=dest->xoffs,xsize=dest->xsize;    -  + #ifdef LAYERS_DUAL    line1=malloc(sizeof(rgb_group)*width); -  line2=malloc(sizeof(rgb_group)*width); +     aline1=malloc(sizeof(rgb_group)*width); -  +  line2=malloc(sizeof(rgb_group)*width);    aline2=malloc(sizeof(rgb_group)*width); -  if (!line1 || !line2 || !aline1 || !aline2) +  if (!line1 || !aline1 +  !line2 || !aline2)    {    if (line1) free(line1); -  if (line2) free(line2); +     if (aline1) free(aline1); -  +  if (line2) free(line2);    if (aline2) free(aline2);    resource_error(NULL,0,0,"memory",sizeof(rgb_group)*4*width,    "Out of memory.\n");    } -  + #endif       da=dest->alp->img;    d=dest->img->img;       /* loop over lines */    for (y=0; y<dest->ysize; y++)    {    if (layers>1 || layer[0]->row_func!=lm_normal ||    layer[0]->tiled)    {    /* add the bottom layer first */    if (layer[0]->row_func==lm_normal &&    !layer[0]->tiled) /* cheat */    {    img_lay_first_line(layer[0],xoffs,xsize,    y+dest->yoffs-layer[0]->yoffs, -  line1,aline1),z=1; + #ifdef LAYERS_DUAL +  line1,aline1 + #else +  d,da + #endif +  ),z=1;    z=1;    }    else    { -  + #ifdef LAYERS_DUAL    smear_color(line1,black,xsize);    smear_color(aline1,black,xsize); -  + #else +  smear_color(d,black,xsize); +  smear_color(da,black,xsize); + #endif    z=0;    }       /* loop over the rest of the layers, except the last */    for (; z<layers-1; z++)    if (!layer[z]->really_optimize_alpha ||    (layer[z]->yoffs<=y+dest->yoffs &&    y+dest->yoffs<layer[z]->yoffs+layer[z]->ysize))    {    rgb_group *tmp;
pike.git/src/modules/Image/layers.c:2235:   /* if (!layer[z]->really_optimize_alpha) */   /* fprintf(stderr,"huh %d\n",z); */   /* if (!(layer[z]->yoffs>=y+dest->yoffs && */   /* y+dest->yoffs<layer[z]->yoffs+layer[z]->ysize)) */   /* fprintf(stderr,"hmm %d %d<=%d<%d\n", */   /* z, */   /* layer[z]->yoffs, */   /* y+dest->yoffs, */   /* layer[z]->yoffs+layer[z]->ysize); */    -  img_lay_line(layer[z],line1,aline1, +  img_lay_line(layer[z], + #ifdef LAYERS_DUAL +  line1,aline1, + #else +  d,da, + #endif    xoffs,xsize,    y+dest->yoffs-layer[z]->yoffs, -  line2,aline2); + #ifdef LAYERS_DUAL +  line2,aline2 + #else +  d,da + #endif +  ); + #ifdef LAYERS_DUAL    /* swap buffers */    tmp=line1; line1=line2; line2=tmp;    tmp=aline1; aline1=aline2; aline2=tmp; -  + #endif    }   /* else */   /* fprintf(stderr,"skip %d\n",z); */       /* make the last layer on the destionation */ -  img_lay_line(layer[layers-1],line1,aline1, -  xoffs,xsize,y+dest->yoffs-layer[layers-1]->yoffs,d,da); +  img_lay_line(layer[layers-1], + #ifdef LAYERS_DUAL +  line1,aline1, + #else +  d,da, + #endif +  xoffs,xsize,y+dest->yoffs-layer[layers-1]->yoffs, +  d,da);    }    else    {    /* make the layer to destination*/    img_lay_first_line(layer[0],xoffs,xsize,    y+dest->yoffs-layer[0]->yoffs,d,da);    }    d+=dest->xsize;    da+=dest->xsize;    }    -  + #ifdef LAYERS_DUAL    free(line1);    free(aline1);    free(line2);    free(aline2); -  + #endif   }      /*   **! module Image   **! method Image.Layer lay(array(Image.Layer|mapping))   **! method Image.Layer lay(array(Image.Layer|mapping),int xoffset,int yoffset,int xsize,int ysize)   **! Combine layers.   **! returns a new layer object.   **!   **! see also: Image.Layer