Branch: Tag:

2001-03-26

2001-03-26 21:15:22 by Mirar (Pontus Hagland) <pike@sort.mirar.org>

adding hue, lightness, saturation modes; looks like most of them works, will put more work into it later

Rev: src/modules/Image/layers.c:1.64

1:   /*   **! module Image   **! note - **! $Id: layers.c,v 1.63 2001/03/17 14:44:29 mirar Exp $ + **! $Id: layers.c,v 1.64 2001/03/26 21:15:22 mirar Exp $   **! class Layer   **! see also: layers   **!
16:   **! <dt>D<dd><i>The destintion layer (the result)</i>   **! <dt>Xrgb<dd><i>Layer red (<b>Xr</b>), green (<b>Xg</b>) or blue channel (<b>Xb</b>) </i>   **! <dt>Xhsv<dd><i>Layer hue (<b>Xh</b>), saturation (<b>Xs</b>) or value channel (<b>Xv</b>) (virtual channels)</i> + **! <dt>Xhls<dd><i>Layer hue (<b>Xh</b>), lightness channel (<b>Xl</b>) or saturation (<b>Xs</b>) (virtual channels)</i>   **! <dt>aX<dd><i>Layer alpha, channel in layer alpha</i>   **! </dl>   **! <i>All channels are calculated separately, if nothing else is specified.</i>
215:      #include <math.h> /* floor */    - RCSID("$Id: layers.c,v 1.63 2001/03/17 14:44:29 mirar Exp $"); + RCSID("$Id: layers.c,v 1.64 2001/03/26 21:15:22 mirar Exp $");      #include "image_machine.h"   
337:   LMFUNC(lm_value);   LMFUNC(lm_value_mul);   LMFUNC(lm_color); -  +    LMFUNC(lm_darken);   LMFUNC(lm_lighten);   LMFUNC(lm_saturate);   LMFUNC(lm_desaturate);    -  + LMFUNC(lm_hls_replace); + LMFUNC(lm_hls_hue); + LMFUNC(lm_hls_saturation); + LMFUNC(lm_hls_lightness); + LMFUNC(lm_hls_lightness_mul); + LMFUNC(lm_hls_color); + LMFUNC(lm_hls_darken); + LMFUNC(lm_hls_lighten); + LMFUNC(lm_hls_saturate); + LMFUNC(lm_hls_desaturate); +    LMFUNC(lm_dissolve);   LMFUNC(lm_behind);   LMFUNC(lm_erase);
443:    "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,
453:    {"desaturate", lm_desaturate, 1, NULL,    "Ds=min(Ls,Ss), Dhv=Lhv, aD=aS"},    +  {"hls_replace", lm_hls_replace, 1, NULL, +  "Dhsv=(Lhls*aLrgb+Shls*(1-aLrgb)*aSrgb) / (aLrgb+(1-aLrgb)*aSrgb), aD=aS"}, +  {"hls_hue", lm_hls_hue, 1, NULL, +  "Dh=(Lh*aLr+Sh*(1-aLr)*aSr) / (aLr+(1-aLr)*aSr), Dsv=Lsv, aD=aS"}, +  {"hls_saturation",lm_hls_saturation, 1, NULL, +  "Ds=(Ls*aLg+Ss*(1-aLg)*aSg) / (aLg+(1-aLg)*aSg), Dhv=Lhv, aD=aS"}, +  {"hls_lightness", lm_hls_lightness, 1, NULL, +  "Dl=(Ll*aLb+Sl*(1-aLb)*aSb) / (aLb+(1-aLb)*aSb), Dhs=Lhs, aD=aS"}, +  {"hls_color", lm_hls_color, 1, NULL, +  "Dhs=(Lhs*aLrg+Shs*(1-aLrg)*aSrg) / (aLrg+(1-aLrg)*aSrg), Dl=Ll, aD=aS"}, +  {"hls_lightness_mul",lm_hls_lightness_mul, 1, NULL, +  "Dl=((Ll*Sl)*aLb+Sl*(1-aLb)*aSb) / (aLb+(1-aLb)*aSb), Dhs=Lhs, aD=aS"}, +  {"hls_darken", lm_hls_darken, 1, NULL, +  "Dv=min(Ll,Sl), Dhs=Lhs, aD=aS"}, +  {"hls_lighten", lm_hls_lighten, 1, NULL, +  "Dv=max(Ll,Sl), Dhs=Lhs, aD=aS"}, +  {"hls_saturate", lm_hls_saturate, 1, NULL, +  "Ds=max(Ls,Ss), Dhl=Lhl, aD=aS"}, +  {"hls_desaturate",lm_hls_desaturate, 1, NULL, +  "Ds=min(Ls,Ss), Dhl=Lhl, aD=aS"}, +     {"dissolve", lm_dissolve, 1, NULL,    "i=random 0 or 1, D=i?L:S, aD=i+aS"},    {"behind", lm_behind, 1, NULL,
709:   #undef t   }    + static INLINE int hls_value(double n1, double n2, double hue) + { +  double value; +  +  if (hue > 255) +  hue -= 255; +  else if (hue < 0) +  hue += 255; +  if (hue < 42.5) +  value = n1 + (n2 - n1) * (hue / 42.5); +  else if (hue < 127.5) +  value = n2; +  else if (hue < 170) +  value = n1 + (n2 - n1) * ((170 - hue) / 42.5); +  else +  value = n1; +  +  return (int) (value * 255); + } +  +  + static INLINE void hls_to_rgb(double h,double l,double s,rgb_group *rgb) + { +  double m1, m2; +  +  if (s == 0) +  { + /* achromatic case */ +  rgb->r = l; +  rgb->g = l; +  rgb->b = l; +  } +  else +  { +  if (l < 128) +  m2 = (l * (255 + s)) / 65025.0; +  else +  m2 = (l + s - (l * s) / 255.0) / 255.0; +  +  m1 = (l / 127.5) - m2; +  + /* chromatic case */ +  rgb->r = hls_value (m1, m2, h + 85); +  rgb->g = hls_value (m1, m2, h); +  rgb->b = hls_value (m1, m2, h - 85); +  } + } +  + static INLINE void rgb_to_hls(rgb_group color, +  double *hue, +  double *lightness, +  double *saturation) + { +  int r, g, b; +  double h, l, s; +  int min, max; +  int delta; +  +  r = color.r; +  g = color.g; +  b = color.b; +  +  if (r > g) +  { +  max = MAX (r, b); +  min = MIN (g, b); +  } +  else +  { +  max = MAX (g, b); +  min = MIN (r, b); +  } +  +  l = (max + min) / 2.0; +  +  if (max == min) +  { +  s = 0.0; +  h = 0.0; +  } +  else +  { +  delta = (max - min); +  +  if (l < 128) +  s = 255 * (double) delta / (double) (max + min); +  else +  s = 255 * (double) delta / (double) (511 - max - min); +  +  if (r == max) +  h = (g - b) / (double) delta; +  else if (g == max) +  h = 2 + (b - r) / (double) delta; +  else +  h = 4 + (r - g) / (double) delta; +  +  h = h * 42.5; +  +  if (h < 0) +  h += 255; +  else if (h > 255) +  h -= 255; +  } +  +  *hue = h; +  *lightness = l; +  *saturation = s; + } +  +    /*** helper ***********************************************/      static int really_optimize_p(struct layer *l)
1916:   #undef L_CHANNEL_DO_V   #undef LM_FUNC    + /* darken: min v */ +  + #define LM_FUNC lm_darken + #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); \ +  hsv_to_rgb(sh,ss,MINIMUM(sv,lv),&(D)); \ +  } while (0) + #include "layer_channel.h" + #undef L_CHANNEL_DO_V + #undef LM_FUNC +    /* saturate: max s */      #define LM_FUNC lm_saturate
1948:   #undef L_CHANNEL_DO_V   #undef LM_FUNC    + /******************************************************************/ +  + #define LM_FUNC lm_hls_replace + #define L_CHANNEL_DO_V(S,L,D,A,V) \ +  do { \ +  double lh,ll,ls; \ +  double sh,sl,ss; \ +  double dh,dl,ds; \ +  rgb_to_hls((S),&sh,&sl,&ss); \ +  rgb_to_hls((L),&lh,&ll,&ls); \ +  dh=lh*(V)*C2F((A).r)+sh*(1-(V)*C2F((A).r)); \ +  dl=ll*(V)*C2F((A).g)+sl*(1-(V)*C2F((A).g)); \ +  ds=ls*(V)*C2F((A).b)+ss*(1-(V)*C2F((A).b)); \ +  hls_to_rgb(dh,dl,ds,&(D)); \ +  } while (0) +  + #include "layer_channel.h" + #undef L_CHANNEL_DO_V + #undef LM_FUNC +  + /* replace h, l or s (by alpha channel (r=h, g=l, b=s), only that one used) */ +  + #define LM_FUNC lm_hls_hue + #define L_CHANNEL_DO_V(S,L,D,A,V) \ +  do { \ +  double lh,ll,ls; \ +  double sh,sl,ss; \ +  double dh,dl,ds; \ +  rgb_to_hls((S),&sh,&sl,&ss); \ +  rgb_to_hls((L),&lh,&ll,&ls); \ +  dh=lh*(V)*C2F((A).r)+sh*(1-(V)*C2F((A).r)); \ +  hls_to_rgb(dh,sl,ss,&(D)); \ +  } while (0) +  + #include "layer_channel.h" + #undef L_CHANNEL_DO_V + #undef LM_FUNC +  + #define LM_FUNC lm_hls_saturation + #define L_CHANNEL_DO_V(S,L,D,A,V) \ +  do { \ +  double lh,ll,ls; \ +  double sh,sl,ss; \ +  double dh,dl,ds; \ +  rgb_to_hls((S),&sh,&sl,&ss); \ +  rgb_to_hls((L),&lh,&ll,&ls); \ +  ds=ls*(V)*C2F((A).b)+ss*(1-(V)*C2F((A).b)); \ +  hls_to_rgb(sh,sl,ds,&(D)); \ +  } while (0) +  + #include "layer_channel.h" + #undef L_CHANNEL_DO_V + #undef LM_FUNC +  + #define LM_FUNC lm_hls_lightness + #define L_CHANNEL_DO_V(S,L,D,A,V) \ +  do { \ +  double lh,ll,ls; \ +  double sh,sl,ss; \ +  double dh,dl,ds; \ +  rgb_to_hls((S),&sh,&sl,&ss); \ +  rgb_to_hls((L),&lh,&ll,&ls); \ +  dl=ll*(V)*C2F((A).g)+sl*(1-(V)*C2F((A).g)); \ +  hls_to_rgb(sh,dl,ss,&(D)); \ +  } while (0) + #include "layer_channel.h" + #undef L_CHANNEL_DO_V + #undef LM_FUNC +  + #define LM_FUNC lm_hls_lightness_mul + #define L_CHANNEL_DO_V(S,L,D,A,V) \ +  do { \ +  double lh,ll,ls; \ +  double sh,sl,ss; \ +  double dh,dl,ds; \ +  rgb_to_hls((S),&sh,&sl,&ss); \ +  rgb_to_hls((L),&lh,&ll,&ls); \ +  dl=sl*ll*(V)*C2F((A).g)+sl*(1-(V)*C2F((A).g)); \ +  hls_to_rgb(sh,dl,ss,&(D)); \ +  } while (0) + #include "layer_channel.h" + #undef L_CHANNEL_DO_V + #undef LM_FUNC +  + /* h, s */ +  + #define LM_FUNC lm_hls_color + #define L_CHANNEL_DO_V(S,L,D,A,V) \ +  do { \ +  double lh,ll,ls; \ +  double sh,sl,ss; \ +  double dh,dl,ds; \ +  rgb_to_hls((S),&sh,&sl,&ss); \ +  rgb_to_hls((L),&lh,&ll,&ls); \ +  dh=lh*(V)*C2F((A).r)+sh*(1-(V)*C2F((A).r)); \ +  ds=ls*(V)*C2F((A).b)+ss*(1-(V)*C2F((A).b)); \ +  hls_to_rgb(dh,sl,ds,&(D)); \ +  } while (0) + #include "layer_channel.h" + #undef L_CHANNEL_DO_V + #undef LM_FUNC +  + /* lighten: max v */ +  + #define LM_FUNC lm_hls_lighten + #define L_CHANNEL_DO_V(S,L,D,A,V) \ +  do { \ +  double lh,ll,ls; \ +  double sh,sl,ss; \ +  double dh,dl,ds; \ +  rgb_to_hls((S),&sh,&sl,&ss); \ +  rgb_to_hls((L),&lh,&ll,&ls); \ +  hls_to_rgb(sh,MAXIMUM(sl,ll),ss,&(D)); \ +  } while (0) + #include "layer_channel.h" + #undef L_CHANNEL_DO_V + #undef LM_FUNC +  + /* darken: min v */ +  + #define LM_FUNC lm_hls_darken + #define L_CHANNEL_DO_V(S,L,D,A,V) \ +  do { \ +  double lh,ll,ls; \ +  double sh,sl,ss; \ +  double dh,dl,ds; \ +  rgb_to_hls((S),&sh,&sl,&ss); \ +  rgb_to_hls((L),&lh,&ll,&ls); \ +  hls_to_rgb(sh,MINIMUM(sl,ll),ss,&(D)); \ +  } while (0) + #include "layer_channel.h" + #undef L_CHANNEL_DO_V + #undef LM_FUNC +  +  + /* saturate: max s */ +  + #define LM_FUNC lm_hls_saturate + #define L_CHANNEL_DO_V(S,L,D,A,V) \ +  do { \ +  double lh,ll,ls; \ +  double sh,sl,ss; \ +  double dh,dl,ds; \ +  rgb_to_hls((S),&sh,&sl,&ss); \ +  rgb_to_hls((L),&lh,&ll,&ls); \ +  hls_to_rgb(sh,sl,MAXIMUM(ss,ls),&(D)); \ +  } while (0) + #include "layer_channel.h" + #undef L_CHANNEL_DO_V + #undef LM_FUNC +  + /* desaturate: min s */ +  + #define LM_FUNC lm_hls_desaturate + #define L_CHANNEL_DO_V(S,L,D,A,V) \ +  do { \ +  double lh,ll,ls; \ +  double sh,sl,ss; \ +  double dh,dl,ds; \ +  rgb_to_hls((S),&sh,&sl,&ss); \ +  rgb_to_hls((L),&lh,&ll,&ls); \ +  hls_to_rgb(sh,sl,MINIMUM(ss,ls),&(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
1971:   #undef L_TRUNC   #undef L_OPER    - /* darken: min v */ -  - #define LM_FUNC lm_darken - #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); \ -  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