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.62 2001/03/04 15:27:55 mirar Exp $ + **! $Id: layers.c,v 1.63 2001/03/17 14:44:29 mirar Exp $   **! class Layer   **! see also: layers   **!      **!   **!   **! <add_appendix name="layers" title="Image.Layer modes">   **! <dl compact>   **! <dt><i>The variables in the expression:</i>   **! <dt>L<dd><i>The active layer</i>
pike.git/src/modules/Image/layers.c:208:   **! }   **!   **! </execute>   **! </add_appendix>   */      #include "global.h"      #include <math.h> /* floor */    - RCSID("$Id: layers.c,v 1.62 2001/03/04 15:27:55 mirar Exp $"); + RCSID("$Id: layers.c,v 1.63 2001/03/17 14:44:29 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:309:   LMFUNC(lm_normal);      LMFUNC(lm_add);   LMFUNC(lm_subtract);   LMFUNC(lm_multiply);   LMFUNC(lm_divide);   LMFUNC(lm_modulo);   LMFUNC(lm_invsubtract);   LMFUNC(lm_invdivide);   LMFUNC(lm_invmodulo); + LMFUNC(lm_imultiply); + LMFUNC(lm_idivide); + LMFUNC(lm_invidivide);   LMFUNC(lm_difference);   LMFUNC(lm_min);   LMFUNC(lm_max);   LMFUNC(lm_bitwise_and);   LMFUNC(lm_bitwise_or);   LMFUNC(lm_bitwise_xor);      LMFUNC(lm_replace);   LMFUNC(lm_red);   LMFUNC(lm_green);   LMFUNC(lm_blue);      LMFUNC(lm_replace_hsv);   LMFUNC(lm_hue);   LMFUNC(lm_saturation);   LMFUNC(lm_value); -  + LMFUNC(lm_value_mul);   LMFUNC(lm_color);      LMFUNC(lm_darken);   LMFUNC(lm_lighten);   LMFUNC(lm_saturate);   LMFUNC(lm_desaturate);      LMFUNC(lm_dissolve);   LMFUNC(lm_behind);   LMFUNC(lm_erase);
pike.git/src/modules/Image/layers.c:369:   struct layer_mode_desc   {    char *name;    lm_row_func *func;    int optimize_alpha; /* alpha 0 -> skip layer */    struct pike_string *ps;    char *desc;   } layer_mode[]=   {    {"normal", lm_normal, 1, NULL, -  "D=(L*aL+S*(1-aL)*aS) / (aL+(1-aL)*aS), aD=(aL+(1-aL)*aS)"}, +  "D=L applied with alpha: " +  "D=(L*aL+S*(1-aL)*aS) / (aL+(1-aL)*aS), " +  "aD=(aL+(1-aL)*aS)"}, +     {"add", lm_add, 1, NULL, -  "D=L+S, apply alpha as \"normal\" mode"}, +  "D=L+S applied with alpha, aD=aS"},    {"subtract", lm_subtract, 1, NULL, -  "D=L-S, apply alpha as \"normal\" mode"}, +  "D=S-L applied with alpha, aD=aS"},    {"multiply", lm_multiply, 1, NULL, -  "D=L*S, apply alpha as \"normal\" mode"}, +  "D=S*L applied with alpha, aD=aS"},    {"divide", lm_divide, 1, NULL, -  "D=L/S, apply alpha as \"normal\" mode"}, +  "D=S/L applied with alpha, aD=aS"},    {"modulo", lm_modulo, 1, NULL, -  "D=L%S, apply alpha as \"normal\" mode"}, +  "D=S%L applied with alpha, aD=aS"}, +     {"invsubtract", lm_invsubtract, 1, NULL, -  "D=S-L, apply alpha as \"normal\" mode"}, +  "D=L-S applied with alpha, aD=aS"},    {"invdivide", lm_invdivide, 1, NULL, -  "D=S/L, apply alpha as \"normal\" mode"}, +  "D=L/S applied with alpha, aD=aS"},    {"invmodulo", lm_invmodulo, 1, NULL, -  "D=S%L, apply alpha as \"normal\" mode"}, +  "D=L%S applied with alpha, aD=aS"}, +  +  {"imultiply", lm_imultiply, 1, NULL, +  "D=(1-L)*S applied with alpha, aD=aS"}, +  {"idivide", lm_idivide, 1, NULL, +  "D=S/(1-L) applied with alpha, aD=aS"}, +  {"invidivide", lm_invidivide, 1, NULL, +  "D=L/(1-S) applied with alpha, aD=aS"}, +     {"difference", lm_difference, 1, NULL, -  "D=abs(L-S), apply alpha as \"normal\" mode"}, +  "D=abs(L-S) applied with alpha, aD=aS"},    {"max", lm_max, 1, NULL, -  "D=max(L,S), apply alpha as \"normal\" mode"}, +  "D=max(L,S) applied with alpha, aD=aS"},    {"min", lm_min, 1, NULL, -  "D=min(L,S), apply alpha as \"normal\" mode"}, +  "D=min(L,S) applied with alpha, aD=aS"},    {"bitwise_and", lm_bitwise_and, 1, NULL, -  "D=L&S, apply alpha as \"normal\" mode"}, +  "D=L&S applied with alpha, aD=aS"},    {"bitwise_or", lm_bitwise_or, 1, NULL, -  "D=L|S, apply alpha as \"normal\" mode"}, +  "D=L|S applied with alpha, aD=aS"},    {"bitwise_xor", lm_bitwise_xor, 1, NULL, -  "D=L^S, apply alpha as \"normal\" mode"}, +  "D=L^S applied with alpha, aD=aS"},       {"replace", lm_replace, 1, NULL,    "D=(L*aL+S*(1-aL)*aS) / (aL+(1-aL)*aS), aD=aS"},    {"red", lm_red, 1, NULL,    "Dr=(Lr*aLr+Sr*(1-aLr)*aSr) / (aLr+(1-aLr)*aSr), Dgb=Sgb, aD=aS"},    {"green", lm_green, 1, NULL,    "Dg=(Lg*aLg+Sg*(1-aLg)*aSg) / (aLg+(1-aLg)*aSg), Drb=Srb, aD=aS"},    {"blue", lm_blue, 1, NULL,    "Db=(Lb*aLb+Sb*(1-aLb)*aSb) / (aLb+(1-aLb)*aSb), Drg=Srg, aD=aS"},       {"replace_hsv", lm_replace_hsv, 1, NULL,    "Dhsv=(Lhsv*aLrgb+Shsv*(1-aLrgb)*aSrgb) / (aLrgb+(1-aLrgb)*aSrgb), aD=aS"},    {"hue", lm_hue, 1, NULL,    "Dh=(Lh*aLr+Sh*(1-aLr)*aSr) / (aLr+(1-aLr)*aSr), Dsv=Lsv, aD=aS"},    {"saturation", lm_saturation, 1, NULL,    "Ds=(Ls*aLg+Ss*(1-aLg)*aSg) / (aLg+(1-aLg)*aSg), Dhv=Lhv, aD=aS"},    {"value", lm_value, 1, NULL,    "Dv=(Lv*aLb+Sv*(1-aLb)*aSb) / (aLb+(1-aLb)*aSb), Dhs=Lhs, aD=aS"},    {"color", lm_color, 1, NULL,    "Dhs=(Lhs*aLrg+Shs*(1-aLrg)*aSrg) / (aLrg+(1-aLrg)*aSrg), Dv=Lv, aD=aS"}, -  +  {"value_mul", lm_value_mul, 1, NULL, +  "Dv=((Lv*Sv)*aLb+Sv*(1-aLb)*aSb) / (aLb+(1-aLb)*aSb), Dhs=Lhs, aD=aS"},       {"darken", lm_darken, 1, NULL,    "Dv=min(Lv,Sv), Dhs=Lhs, aD=aS"},    {"lighten", lm_lighten, 1, NULL,    "Dv=max(Lv,Sv), Dhs=Lhs, aD=aS"},    {"saturate", lm_saturate, 1, NULL,    "Ds=max(Ls,Ss), Dhv=Lhv, aD=aS"},    {"desaturate", lm_desaturate, 1, NULL,    "Ds=min(Ls,Ss), Dhv=Lhv, aD=aS"},       {"dissolve", lm_dissolve, 1, NULL,    "i=random 0 or 1, D=i?L:S, aD=i+aS"},    {"behind", lm_behind, 1, NULL,    "D=(S*aS+L*(1-aS)*aL) / (aS+(1-aS)*aL), aD=(aS+(1-aS)*aL); "    "simply swap S and L"},    {"erase", lm_erase, 1, NULL,    "D=S, aD=aS*(1-aL)"},       {"screen", lm_screen, 1, NULL, -  "1-(1-S)*(1-L), apply alpha as \"normal\""}, +  "1-(1-S)*(1-L) applied with alpha, aD=aS"},    {"overlay", lm_overlay, 1, NULL, -  "(1-(1-a)*(1-b)-a*b)*a+a*b, apply alpha as \"normal\""}, +  "(1-(1-a)*(1-b)-a*b)*a+a*b applied with alpha, aD=aS"},    {"burn_alpha", (lm_row_func*)lm_spec_burn_alpha, 1, NULL, -  "aD=aL+aS, D=L+S; experimental, may change or be removed"}, +  "aD=aL+aS applied with alpha, D=L+S;" +  " experimental, may change or be removed"},       {"equal", lm_equal, 0, NULL,    "each channel D=max if L==S, 0 otherwise, apply with alpha"},    {"not_equal", lm_not_equal, 0, NULL,    "each channel D=max if L!=S, 0 otherwise, apply with alpha"},    {"less", lm_less, 0, NULL,    "each channel D=max if L<S, 0 otherwise, apply with alpha"},    {"more", lm_more, 0, NULL,    "each channel D=max if L>S, 0 otherwise, apply with alpha"},    {"less_or_equal", lm_less_or_equal, 0, NULL,
pike.git/src/modules/Image/layers.c:571:    (D)->C=COMBINE_ALPHA_V((S)->C,(L)->C,0,(LA)->C,V); \    (DA)->C=COMBINE_ALPHA_SUM_V((LA)->C,0,V); \    } \    else \    { \    (D)->C=COMBINE_ALPHA_V((S)->C,(L)->C,(SA)->C,(LA)->C,V); \    (DA)->C=COMBINE_ALPHA_SUM_V((LA)->C,(SA)->C,V); \    } \    } while (0)    + #define ALPHA_ADD_nA(S,L,D,SA,LA,DA,C) \ +  do { \ +  if (!(LA)->C) (D)->C=(S)->C; \ +  else if (!(SA)->C) (D)->C=(L)->C; \ +  else if ((LA)->C==COLORMAX) (D)->C=(L)->C; \ +  else \ +  (D)->C=COMBINE_ALPHA((S)->C,(L)->C,(SA)->C,(LA)->C); \ +  } while(0)    -  + #define ALPHA_ADD_V_NOLA_nA(L,S,D,SA,DA,V,C) \ +  do { \ +  if (!(SA)->C) (D)->C=(L)->C; \ +  else \ +  { \ +  if ((SA)->C==COLORMAX) \ +  (D)->C=COMBINE_ALPHA_V((S)->C,(L)->C,COLORMAX,255,V); \ +  else \ +  (D)->C=COMBINE_ALPHA_V((S)->C,(L)->C,(SA)->C,255,V); \ +  } \ +  } while(0) +  + #define ALPHA_ADD_V_nA(L,S,D,LA,SA,DA,V,C) \ +  do { \ +  if (!(LA)->C) (D)->C=(S)->C; \ +  else if (!(SA)->C) \ +  { \ +  (D)->C=COMBINE_ALPHA_V((S)->C,(L)->C,0,(LA)->C,V); \ +  } \ +  else \ +  { \ +  (D)->C=COMBINE_ALPHA_V((S)->C,(L)->C,(SA)->C,(LA)->C,V); \ +  } \ +  } while (0) +  +    static INLINE void smear_color(rgb_group *d,rgb_group s,int len)   {    while (len--)    *(d++)=s;   }      #define MAX3(X,Y,Z) MAXIMUM(MAXIMUM(X,Y),Z)   #define MIN3(X,Y,Z) MINIMUM(MINIMUM(X,Y),Z)      /* Pike_sp was renamed to not_sp by hubbe */
pike.git/src/modules/Image/layers.c:1382:         #if defined(__ECL) && 0   #define WARN_TRACE(X) static char PIKE_CONCAT(foo__, X) (double d) { return (char)d; }   #else /* !__ECL */   #define WARN_TRACE(X)   #endif /* __ECL */      /* operators from template */    + #define L_COPY_ALPHA +    #define LM_FUNC lm_add   #define L_TRUNC(X) MINIMUM(255,(X)) - #define L_OPER(A,B) ((A)+DOUBLE_TO_INT(B)) + #define L_OPER(A,B) ((A)+(int)(B))   #define L_MMX_OPER(A,MMXR) paddusb_m2r(A,MMXR)   WARN_TRACE(1);   #include "layer_oper.h"   #undef L_MMX_OPER   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER    -  + #define LM_FUNC lm_a_add + #define L_TRUNC(X) MINIMUM(255,(X)) + #define L_OPER(A,B) ((A)+(int)(B)) + #define L_MMX_OPER(A,MMXR) paddusb_m2r(A,MMXR) + WARN_TRACE(1); + #include "layer_oper.h" + #undef L_MMX_OPER + #undef LM_FUNC + #undef L_TRUNC + #undef L_OPER +    #define LM_FUNC lm_subtract   #define L_TRUNC(X) MAXIMUM(0,(X)) - #define L_OPER(A,B) ((A)-DOUBLE_TO_INT(B)) + #define L_OPER(A,B) ((A)-(int)(B))   #define L_MMX_OPER(A,MMXR) psubusb_m2r(A,MMXR)   WARN_TRACE(2);   #include "layer_oper.h"   #undef L_MMX_OPER   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER      #define LM_FUNC lm_multiply   #define L_TRUNC(X) (X) - #define L_OPER(A,B) CCUT((A)*DOUBLE_TO_INT(B)) + #define L_OPER(A,B) CCUT((A)*(int)(B))   WARN_TRACE(3);   #include "layer_oper.h"   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER      #define LM_FUNC lm_divide   #define L_TRUNC(X) MINIMUM(255,(X)) - #define L_OPER(A,B) (CCUT((A)/C2F(1+DOUBLE_TO_INT(B)))) + #define L_OPER(A,B) MINIMUM( DOUBLE_TO_INT((A)/C2F(1+(int)(B))), COLORMAX)   WARN_TRACE(4);   #include "layer_oper.h"   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER      #define LM_FUNC lm_modulo   #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))   #define L_OPER(A,B) ((A)%((B)?(B):1))   WARN_TRACE(5);   #include "layer_oper.h"   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER      #define L_USE_SA      #define LM_FUNC lm_invsubtract   #define L_TRUNC(X) MAXIMUM(0,(X)) - #define L_OPER(A,B) ((B)-DOUBLE_TO_INT(A)) + #define L_OPER(A,B) ((B)-(int)(A))   WARN_TRACE(6);   #include "layer_oper.h"   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER      #define LM_FUNC lm_invdivide   #define L_TRUNC(X) MINIMUM(255,(X)) - #define L_OPER(A,B) (CCUT((B)/C2F(1+DOUBLE_TO_INT(A)))) + #define L_OPER(A,B) MINIMUM( DOUBLE_TO_INT((B)/C2F(1+(int)(A))), COLORMAX)   WARN_TRACE(7);   #include "layer_oper.h"   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER      #define LM_FUNC lm_invmodulo   #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))   #define L_OPER(A,B) ((B)%((A)?(A):1))   WARN_TRACE(8);   #include "layer_oper.h"   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER    -  + #define LM_FUNC lm_idivide + #define L_TRUNC(X) MINIMUM(255,(X)) + #define L_OPER(A,B) MINIMUM( DOUBLE_TO_INT((A)/C2F(COLORMAX+1-(int)(B))), COLORMAX) + WARN_TRACE(4); + #include "layer_oper.h" + #undef LM_FUNC + #undef L_TRUNC + #undef L_OPER +  + #define LM_FUNC lm_imultiply + #define L_TRUNC(X) (X) + #define L_OPER(A,B) CCUT((A)*(COLORMAX-(int)(B))) + WARN_TRACE(3); + #include "layer_oper.h" + #undef LM_FUNC + #undef L_TRUNC + #undef L_OPER +  + #define LM_FUNC lm_invidivide + #define L_TRUNC(X) MINIMUM(255,(X)) + #define L_OPER(A,B) MINIMUM( DOUBLE_TO_INT((B)/C2F(COLORMAX+1-(int)(A))), COLORMAX) + WARN_TRACE(7); + #include "layer_oper.h" + #undef LM_FUNC + #undef L_TRUNC + #undef L_OPER +    #undef L_USE_SA      #define LM_FUNC lm_difference   #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))   #define L_OPER(A,B) abs((A)-(B))   WARN_TRACE(9);   #include "layer_oper.h"   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER
pike.git/src/modules/Image/layers.c:1516:      #define LM_FUNC lm_bitwise_xor   #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))   #define L_OPER(A,B) ((A)^(B))   WARN_TRACE(14);   #include "layer_oper.h"   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER    + #undef L_COPY_ALPHA +    #define LM_FUNC lm_equal   #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))   #define L_OPER(A,B) (((A)==(B))?COLORMAX:0)   WARN_TRACE(15);   #include "layer_oper.h"   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER      #define LM_FUNC lm_not_equal
pike.git/src/modules/Image/layers.c:1765:    double dh,ds,dv; \    rgb_to_hsv((S),&sh,&ss,&sv); \    rgb_to_hsv((L),&lh,&ls,&lv); \    dv=lv*(V)*C2F((A).b)+sv*(1-(V)*C2F((A).b)); \    hsv_to_rgb(sh,ss,dv,&(D)); \    } while (0)   #include "layer_channel.h"   #undef L_CHANNEL_DO_V   #undef LM_FUNC    + #define LM_FUNC lm_value_mul + #define L_CHANNEL_DO_V(S,L,D,A,V) \ +  do { \ +  double lh,ls,lv; \ +  double sh,ss,sv; \ +  double dh,ds,dv; \ +  rgb_to_hsv((S),&sh,&ss,&sv); \ +  rgb_to_hsv((L),&lh,&ls,&lv); \ +  dv=sv*lv*(V)*C2F((A).b)+sv*(1-(V)*C2F((A).b)); \ +  hsv_to_rgb(sh,ss,dv,&(D)); \ +  } while (0) + #include "layer_channel.h" + #undef L_CHANNEL_DO_V + #undef LM_FUNC +    /* h, s */      #define LM_FUNC lm_color   #define L_CHANNEL_DO_V(S,L,D,A,V) \    do { \    double lh,ls,lv; \    double sh,ss,sv; \    double dh,ds,dv; \    rgb_to_hsv((S),&sh,&ss,&sv); \    rgb_to_hsv((L),&lh,&ls,&lv); \
pike.git/src/modules/Image/layers.c:1833:    rgb_to_hsv((S),&sh,&ss,&sv); \    rgb_to_hsv((L),&lh,&ls,&lv); \    hsv_to_rgb(sh,MINIMUM(ss,ls),sv,&(D)); \    } while (0)   #include "layer_channel.h"   #undef L_CHANNEL_DO_V   #undef LM_FUNC      /* screen: 255 - ((255-A)*(255-B)/255) */    + #define L_COPY_ALPHA +    #define LM_FUNC lm_screen   #define L_TRUNC(X) (X<0?0:(X>255?255:X))   #define L_OPER(A,B) 255 - CCUT((255-A)*(int)(255-B))   #include "layer_oper.h"   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER      #define LM_FUNC lm_overlay   #define L_TRUNC(X) (X)
pike.git/src/modules/Image/layers.c:1868:    double sh,ss,sv; \    double dh,ds,dv; \    rgb_to_hsv((S),&sh,&ss,&sv); \    rgb_to_hsv((L),&lh,&ls,&lv); \    hsv_to_rgb(sh,ss,MINIMUM(sv,lv),&(D)); \    } while (0)   #include "layer_channel.h"   #undef L_CHANNEL_DO_V   #undef LM_FUNC    -  + #undef L_COPY_ALPHA   #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)    {