7e8e2d1999-04-17Mirar (Pontus Hagland) /* **! module Image **! note
9e3e5a2001-09-24Henrik Grubbström (Grubba) **! $Id: layers.c,v 1.74 2001/09/24 11:35:00 grubba Exp $
7e8e2d1999-04-17Mirar (Pontus Hagland) **! class Layer
400f921999-06-22Mirar (Pontus Hagland) **! see also: layers **! **! **!
47897e2001-07-17Martin Nilsson **! appendix Image.Layer modes **!
726c7a1999-08-12Mirar (Pontus Hagland) **! <dl compact>
d028992001-07-17Martin Nilsson **! <dt><i>The variables in the expression:</i></dt> **! <dt>L</dt><dd><i>The active layer</i></dd> **! <dt>S</dt><dd><i>The source layer (the sum of the layers below)</i></dd> **! <dt>D</dt><dd><i>The destintion layer (the result)</i></dd> **! <dt>Xrgb</dt><dd><i>Layer red (<b>Xr</b>), green (<b>Xg</b>) or blue channel (<b>Xb</b>) </i></dd> **! <dt>Xhsv</dt><dd><i>Layer hue (<b>Xh</b>), saturation (<b>Xs</b>) or value channel (<b>Xv</b>) (virtual channels)</i></dd> **! <dt>Xhls</dt><dd><i>Layer hue (<b>Xh</b>), lightness channel (<b>Xl</b>) or saturation (<b>Xs</b>) (virtual channels)</i></dd> **! <dt>aX</dt><dd><i>Layer alpha, channel in layer alpha</i></dd>
726c7a1999-08-12Mirar (Pontus Hagland) **! </dl> **! <i>All channels are calculated separately, if nothing else is specified.</i> **! <execute>
400f921999-06-22Mirar (Pontus Hagland) **! import Image;
e01a022000-02-08Per Hedbor **!
400f921999-06-22Mirar (Pontus Hagland) **! void write_image(string desc, **! string filename,
b77f951999-08-10Mirar (Pontus Hagland) **! Image img, **! string longdesc)
400f921999-06-22Mirar (Pontus Hagland) **! {
c9db842001-07-27Martin Nilsson **! longdesc = replace(longdesc, ([ "&lt;":"&amp;lt;", "&gt;":"&amp;gt;", "&amp;":"&amp;amp;" ])); **! write(begin_tag("tr"));
400f921999-06-22Mirar (Pontus Hagland) **! write(mktag("td",(["align":"right","valign":"center"]), **! mktag("b",0,desc)));
c3b5b41999-07-20Fredrik Hübinette (Hubbe) **! write(mktag("td",(["align":"right"]),illustration_jpeg(img,(["dpi":150.0]))));
726c7a1999-08-12Mirar (Pontus Hagland) **! write(mktag("td",(["align":"left","valign":"center"]),longdesc)); ** (replace(longdesc,({",",";",")"}), ** ({",<wbr>",";<wbr>",")<wbr>"}))/ ** "<wbr>")/1*({mktag("wbr")}) ) );
c9db842001-07-27Martin Nilsson **! write(end_tag()+"\n");
400f921999-06-22Mirar (Pontus Hagland) **! }
e01a022000-02-08Per Hedbor **!
400f921999-06-22Mirar (Pontus Hagland) **! int main() **! { **! object ltrans=Layer((["image": **! Image(32,32,160,160,160)-> **! box(0,0,15,15,96,96,96)-> **! box(16,16,31,31,96,96,96)->scale(0.5), **! "tiled":1, **! "mode":"normal"]));
e01a022000-02-08Per Hedbor **!
c9db842001-07-27Martin Nilsson **! object circle=load(fix_image_path("circle50.pnm")); **! object image_test=load(fix_image_path("image_ill.pnm")); **! object ryoki=load_layer(fix_image_path("ryoki_carrot.png"));
e01a022000-02-08Per Hedbor **!
400f921999-06-22Mirar (Pontus Hagland) **! object lc1=
f9c8eb1999-07-02Mirar (Pontus Hagland) **! Layer((["image":circle->clear(255,0,0), **! "alpha":circle, **! "xoffset":5, **! "yoffset":5])); **!
400f921999-06-22Mirar (Pontus Hagland) **! object lc2= **! Layer((["image":circle->clear(0,0,255), **! "alpha":circle, **! "xoffset":25, **! "yoffset":25])); **! object lc2b= **! Layer((["image":circle, **! "alpha":circle*({0,0,255}), **! "xoffset":25, **! "yoffset":25]));
e01a022000-02-08Per Hedbor **!
400f921999-06-22Mirar (Pontus Hagland) **! object lr1= **! Layer((["image":circle->test(63)->scale(1.25), **! "alpha":circle->scale(1.25), **! "xoffset":10, **! "yoffset":5])); **! object lr2=
f9c8eb1999-07-02Mirar (Pontus Hagland) **! Layer((["image":ryoki->image(), **! "alpha":ryoki->alpha(),
400f921999-06-22Mirar (Pontus Hagland) **! "xoffset":5, **! "yoffset":20]));
e01a022000-02-08Per Hedbor **!
400f921999-06-22Mirar (Pontus Hagland) **! object li1= **! Layer((["image":image_test->scale(80,0), **! "mode":"normal", **! "xoffset":0, **! "yoffset":0]));
e01a022000-02-08Per Hedbor **!
400f921999-06-22Mirar (Pontus Hagland) **! object li2= **! lay( **! ({ **! (["image":circle->clear(255,0,0),"alpha":circle, **! "xoffset":5,"yoffset":0,"mode":"add"]), **! (["image":circle->clear(0,255,0),"alpha":circle, **! "xoffset":25,"yoffset":0,"mode":"add"]), **! (["image":circle->clear(0,0,255),"alpha":circle, **! "xoffset":15,"yoffset":20,"mode":"add"]), **! (["image":circle->clear(0,0,0)->scale(0.5), **! "alpha":circle->scale(0.5), **! "xoffset":0,"yoffset":55]), **! (["image":circle->clear(255,255,255)->scale(0.5), **! "alpha":circle->scale(0.5), **! "xoffset":55,"yoffset":55]) **! }));
e01a022000-02-08Per Hedbor **!
400f921999-06-22Mirar (Pontus Hagland) **! Layer li2b=Layer(li2->image()->clear(255,255,255),li2->image());
e01a022000-02-08Per Hedbor **!
f9c8eb1999-07-02Mirar (Pontus Hagland) **! object lzo0=
e01a022000-02-08Per Hedbor **! lay( ({
f9c8eb1999-07-02Mirar (Pontus Hagland) **! Layer(Image(4,10) **! ->tuned_box(0,0,3,8,({({255,255,255}),({255,255,255}), **! ({0,0,0}),({0,0,0})})) **! ->scale(40,80)) **! ->set_offset(0,0), **! Layer(Image(40,80) **! ->tuned_box(0,0,40,78,({({255,255,255}),({255,255,255}), **! ({0,0,0}),({0,0,0})}))) **! ->set_offset(40,0), **! Layer(Image(80,80) **! ->tuned_box(0,0,80,80,({({255,0,0}),({255,255,0}), **! ({0,0,255}),({0,255,0})}))) **! ->set_offset(80,0), **! }) );
e01a022000-02-08Per Hedbor **!
f9c8eb1999-07-02Mirar (Pontus Hagland) **! object scale= **! Image(4,80) **! ->tuned_box(0,0,40,78,({({255,255,255}),({255,255,255}), **! ({0,0,0}),({0,0,0})})); **! object lzo1=
e01a022000-02-08Per Hedbor **! lay( ({
f9c8eb1999-07-02Mirar (Pontus Hagland) **! Layer(scale)->set_offset(2,0), **! Layer(scale->invert())->set_offset(6,0), **! Layer(Image(26,80)->test())->set_offset(12,0), **! Layer(scale)->set_offset(42,0), **! Layer(scale->invert())->set_offset(46,0), **! Layer(Image(26,80)->test())->set_offset(52,0), **! Layer(scale)->set_offset(82,0), **! Layer(scale->invert())->set_offset(86,0), **! Layer(Image(26,80)->test())->set_offset(92,0), **! Layer(scale)->set_offset(122,0), **! Layer(scale->invert())->set_offset(126,0), **! Layer(Image(26,80,"white"), **! Image(26,80)->test())->set_offset(132,0), **! }));
e01a022000-02-08Per Hedbor **!
f9c8eb1999-07-02Mirar (Pontus Hagland) **! object lca1; **!
400f921999-06-22Mirar (Pontus Hagland) **! object a=
f9c8eb1999-07-02Mirar (Pontus Hagland) **! lay( ({ lca1=lay(({Layer((["fill":"white"])), **! lc1}),0,0,80,80),
400f921999-06-22Mirar (Pontus Hagland) **! lay(({lc1}),0,0,80,80)->set_offset(80,0), **! lay(({li1}),0,0,80,80)->set_offset(160,0), **! lay(({li1}),0,0,80,80)->set_offset(240,0),
f9c8eb1999-07-02Mirar (Pontus Hagland) **! lay(({lr1}),0,0,80,80)->set_offset(320,0), **! lzo0->set_offset(400,0)}), **! 0,0,560,80);
e01a022000-02-08Per Hedbor **!
400f921999-06-22Mirar (Pontus Hagland) **! object b= **! lay( ({ lay(({lc2}),0,0,80,80), **! lay(({lc2b}),0,0,80,80)->set_offset(80,0), **! lay(({li2}),0,0,80,80)->set_offset(160,0), **! lay(({li2b}),0,0,80,80)->set_offset(240,0),
f9c8eb1999-07-02Mirar (Pontus Hagland) **! lay(({lr2}),0,0,80,80)->set_offset(320,0), **! lzo1->set_offset(400,0)}), **! 0,0,560,80); **! ** xv(a); xv(b);
e01a022000-02-08Per Hedbor **!
c9db842001-07-27Martin Nilsson **! write(begin_tag("table",(["cellspacing":"0","cellpadding":"1"])));
e01a022000-02-08Per Hedbor **!
400f921999-06-22Mirar (Pontus Hagland) **! // write_image("top layer image","bi",b->image()); **! // write_image("top layer alpha","ba",b->alpha());
e01a022000-02-08Per Hedbor **!
400f921999-06-22Mirar (Pontus Hagland) **! // write_image("bottom layer image","ai",a->image()); **! // write_image("bottom layer alpha","aa",b->alpha());
e01a022000-02-08Per Hedbor **!
b77f951999-08-10Mirar (Pontus Hagland) **! write_image("top layer","b",lay(({ltrans,b}))->image(), **! ""); **! write_image("bottom layer","a",lay(({ltrans,a}))->image(), **! "");
e01a022000-02-08Per Hedbor **!
8ae60b1999-07-23Mirar (Pontus Hagland) **! write(mktag("tr",0,mktag("td",0,"\240")));
e01a022000-02-08Per Hedbor **!
b77f951999-08-10Mirar (Pontus Hagland) **! foreach (Array.transpose(({Layer()->available_modes(), **! Layer()->descriptions()})), **! [string mode,string desc])
400f921999-06-22Mirar (Pontus Hagland) **! {
9974301999-07-03Mirar (Pontus Hagland) **! if ((&lt;"add","equal","replace","replace_hsv","darken", **! "dissolve","screen","logic_equal">)[mode])
8ae60b1999-07-23Mirar (Pontus Hagland) **! write(mktag("tr",0,mktag("td",0,"\240")));
9974301999-07-03Mirar (Pontus Hagland) **!
f9c8eb1999-07-02Mirar (Pontus Hagland) **! ({lc2,lc2b,li2,li2b,lr2,lzo1})->set_mode(mode);
e01a022000-02-08Per Hedbor **!
400f921999-06-22Mirar (Pontus Hagland) **! object r=
f9c8eb1999-07-02Mirar (Pontus Hagland) **! lay( ({ lay(({lca1,lc2}),0,0,80,80),
400f921999-06-22Mirar (Pontus Hagland) **! lay(({lc1,lc2b}),0,0,80,80)->set_offset(80,0), **! lay(({li1,li2}),0,0,80,80)->set_offset(160,0), **! lay(({li1,li2b}),0,0,80,80)->set_offset(240,0),
f9c8eb1999-07-02Mirar (Pontus Hagland) **! lay(({lr1,lr2}),0,0,80,80)->set_offset(320,0), **! lay(({lzo0,lzo1}),400,0,160,80) }), **! 0,0,560,80); ** xv(r);
e01a022000-02-08Per Hedbor **!
b77f951999-08-10Mirar (Pontus Hagland) **! write_image(mode,mode,lay(({ltrans,r}))->image(),desc);
400f921999-06-22Mirar (Pontus Hagland) **! }
e01a022000-02-08Per Hedbor **!
400f921999-06-22Mirar (Pontus Hagland) **! write(end_tag()); **! return 0; **! } **! **! </execute>
7e8e2d1999-04-17Mirar (Pontus Hagland) */ #include "global.h"
25aaeb1999-04-23Mirar (Pontus Hagland) #include <math.h> /* floor */
9e3e5a2001-09-24Henrik Grubbström (Grubba) RCSID("$Id: layers.c,v 1.74 2001/09/24 11:35:00 grubba Exp $");
7e8e2d1999-04-17Mirar (Pontus Hagland) 
d9db231999-05-30Mirar (Pontus Hagland) #include "image_machine.h"
7e8e2d1999-04-17Mirar (Pontus Hagland)  #include "stralloc.h" #include "pike_macros.h" #include "object.h" #include "constants.h" #include "interpret.h" #include "svalue.h" #include "array.h" #include "mapping.h" #include "threads.h" #include "builtin_functions.h" #include "dmalloc.h" #include "operators.h" #include "module_support.h" #include "opcodes.h" #include "image.h"
6dc2772000-07-28Fredrik Hübinette (Hubbe) /* This must be included last! */ #include "module_magic.h"
8223ea1999-08-13Per Hedbor  #ifdef TRY_USE_MMX #include <mmx.h> #endif
7e8e2d1999-04-17Mirar (Pontus Hagland) extern struct program *image_program;
15e40e1999-06-03Mirar (Pontus Hagland) extern struct program *image_layer_program; extern struct program *image_colortable_program;
7e8e2d1999-04-17Mirar (Pontus Hagland)  static struct mapping *colors=NULL; static struct object *colortable=NULL; static struct array *colornames=NULL; static const rgb_group black={0,0,0}; static const rgb_group white={COLORMAX,COLORMAX,COLORMAX}; typedef void lm_row_func(rgb_group *s, rgb_group *l, rgb_group *d, rgb_group *sa, rgb_group *la, /* may be NULL */ rgb_group *da, int len,
25aaeb1999-04-23Mirar (Pontus Hagland)  double alpha);
e01a022000-02-08Per Hedbor 
7e8e2d1999-04-17Mirar (Pontus Hagland) 
1856b31999-04-19Mirar (Pontus Hagland) #define SNUMPIXS 64 /* pixels in short-stroke buffer */
7e8e2d1999-04-17Mirar (Pontus Hagland) struct layer {
b875ff2001-03-04Mirar (Pontus Hagland)  INT32 xsize; /* underlaying image size */ INT32 ysize;
e01a022000-02-08Per Hedbor 
b875ff2001-03-04Mirar (Pontus Hagland)  INT32 xoffs,yoffs; /* clip offset */
7e8e2d1999-04-17Mirar (Pontus Hagland)  struct object *image; /* image object */ struct object *alpha; /* alpha object or null */ struct image *img; /* image object storage */ struct image *alp; /* alpha object storage */
65a5492000-08-10Per Hedbor  FLOAT_TYPE alpha_value; /* overall alpha value (1.0=opaque) */
7e8e2d1999-04-17Mirar (Pontus Hagland)  rgb_group fill; /* fill color ("outside" the layer) */
e01a022000-02-08Per Hedbor  rgb_group fill_alpha; /* fill alpha */
7e8e2d1999-04-17Mirar (Pontus Hagland) 
1856b31999-04-19Mirar (Pontus Hagland)  rgb_group sfill[SNUMPIXS]; /* pre-calculated rows */
e01a022000-02-08Per Hedbor  rgb_group sfill_alpha[SNUMPIXS];
1856b31999-04-19Mirar (Pontus Hagland) 
b875ff2001-03-04Mirar (Pontus Hagland)  int tiled; /* true if tiled */
7e8e2d1999-04-17Mirar (Pontus Hagland)  lm_row_func *row_func;/* layer mode */
b875ff2001-03-04Mirar (Pontus Hagland)  int optimize_alpha; int really_optimize_alpha;
e01a022000-02-08Per Hedbor  struct mapping *misc; /* Misc associated data. Added by per, rather useful for some things... */
7e8e2d1999-04-17Mirar (Pontus Hagland) };
a7692c1999-05-07Fredrik Hübinette (Hubbe) #undef THIS
5923b12000-07-06Fredrik Hübinette (Hubbe) #define THIS ((struct layer *)(Pike_fp->current_storage)) #define THISOBJ (Pike_fp->current_object)
7e8e2d1999-04-17Mirar (Pontus Hagland) 
5e39651999-04-22Mirar (Pontus Hagland) #define LMFUNC(X) \ static void X(rgb_group *s,rgb_group *l,rgb_group *d, \ rgb_group *sa,rgb_group *la,rgb_group *da, \
25aaeb1999-04-23Mirar (Pontus Hagland)  int len,double alpha)
5e39651999-04-22Mirar (Pontus Hagland)  LMFUNC(lm_normal);
9974301999-07-03Mirar (Pontus Hagland) 
5e39651999-04-22Mirar (Pontus Hagland) LMFUNC(lm_add); LMFUNC(lm_subtract); LMFUNC(lm_multiply); LMFUNC(lm_divide);
7fd2cb2001-03-28Per Hedbor LMFUNC(lm_negdivide);
5e39651999-04-22Mirar (Pontus Hagland) LMFUNC(lm_modulo); LMFUNC(lm_invsubtract); LMFUNC(lm_invdivide); LMFUNC(lm_invmodulo);
a0c6c32001-03-17Mirar (Pontus Hagland) LMFUNC(lm_imultiply); LMFUNC(lm_idivide); LMFUNC(lm_invidivide);
55e2dd1999-04-23Mirar (Pontus Hagland) LMFUNC(lm_difference); LMFUNC(lm_min); LMFUNC(lm_max); LMFUNC(lm_bitwise_and); LMFUNC(lm_bitwise_or); LMFUNC(lm_bitwise_xor);
25aaeb1999-04-23Mirar (Pontus Hagland)  LMFUNC(lm_replace); LMFUNC(lm_red); LMFUNC(lm_green); LMFUNC(lm_blue);
7fd2cb2001-03-28Per Hedbor LMFUNC(lm_hardlight);
25aaeb1999-04-23Mirar (Pontus Hagland)  LMFUNC(lm_replace_hsv); LMFUNC(lm_hue); LMFUNC(lm_saturation); LMFUNC(lm_value);
a0c6c32001-03-17Mirar (Pontus Hagland) LMFUNC(lm_value_mul);
e01a022000-02-08Per Hedbor LMFUNC(lm_color);
5e39651999-04-22Mirar (Pontus Hagland) LMFUNC(lm_darken); LMFUNC(lm_lighten);
9974301999-07-03Mirar (Pontus Hagland) LMFUNC(lm_saturate); LMFUNC(lm_desaturate);
a7c6a11999-04-23Mirar (Pontus Hagland) 
7bdf522001-03-26Mirar (Pontus Hagland) 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);
a7c6a11999-04-23Mirar (Pontus Hagland) LMFUNC(lm_dissolve); LMFUNC(lm_behind);
5e39651999-04-22Mirar (Pontus Hagland) LMFUNC(lm_erase);
7e8e2d1999-04-17Mirar (Pontus Hagland) 
d883131999-06-28Per Hedbor LMFUNC(lm_screen); LMFUNC(lm_overlay);
9974301999-07-03Mirar (Pontus Hagland) LMFUNC(lm_equal); LMFUNC(lm_not_equal); LMFUNC(lm_less); LMFUNC(lm_more); 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);
776acd1999-08-10Mirar (Pontus Hagland) 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);
7e8e2d1999-04-17Mirar (Pontus Hagland) struct layer_mode_desc { char *name; lm_row_func *func;
1856b31999-04-19Mirar (Pontus Hagland)  int optimize_alpha; /* alpha 0 -> skip layer */
7e8e2d1999-04-17Mirar (Pontus Hagland)  struct pike_string *ps;
b77f951999-08-10Mirar (Pontus Hagland)  char *desc;
7e8e2d1999-04-17Mirar (Pontus Hagland) } layer_mode[]= {
b77f951999-08-10Mirar (Pontus Hagland)  {"normal", lm_normal, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=L applied with alpha: " "D=(L*aL+S*(1-aL)*aS) / (aL+(1-aL)*aS), " "aD=(aL+(1-aL)*aS)"},
b77f951999-08-10Mirar (Pontus Hagland)  {"add", lm_add, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=L+S applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"subtract", lm_subtract, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=S-L applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"multiply", lm_multiply, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=S*L applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"divide", lm_divide, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=S/L applied with alpha, aD=aS"},
7fd2cb2001-03-28Per Hedbor  {"negdivide", lm_negdivide, 1, NULL, "D=1.0-S/L applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"modulo", lm_modulo, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=S%L applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"invsubtract", lm_invsubtract, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=L-S applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"invdivide", lm_invdivide, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=L/S applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"invmodulo", lm_invmodulo, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "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"},
b77f951999-08-10Mirar (Pontus Hagland)  {"difference", lm_difference, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=abs(L-S) applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"max", lm_max, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=max(L,S) applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"min", lm_min, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=min(L,S) applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"bitwise_and", lm_bitwise_and, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=L&S applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"bitwise_or", lm_bitwise_or, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=L|S applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"bitwise_xor", lm_bitwise_xor, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "D=L^S applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"replace", lm_replace, 1, NULL,
726c7a1999-08-12Mirar (Pontus Hagland)  "D=(L*aL+S*(1-aL)*aS) / (aL+(1-aL)*aS), aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"red", lm_red, 1, NULL,
726c7a1999-08-12Mirar (Pontus Hagland)  "Dr=(Lr*aLr+Sr*(1-aLr)*aSr) / (aLr+(1-aLr)*aSr), Dgb=Sgb, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"green", lm_green, 1, NULL,
726c7a1999-08-12Mirar (Pontus Hagland)  "Dg=(Lg*aLg+Sg*(1-aLg)*aSg) / (aLg+(1-aLg)*aSg), Drb=Srb, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"blue", lm_blue, 1, NULL,
726c7a1999-08-12Mirar (Pontus Hagland)  "Db=(Lb*aLb+Sb*(1-aLb)*aSb) / (aLb+(1-aLb)*aSb), Drg=Srg, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland) 
7fd2cb2001-03-28Per Hedbor  {"hardlight", lm_hardlight, 1, NULL, "Like photoshop hardlight layer mode, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"replace_hsv", lm_replace_hsv, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dhsv=Lhsv apply with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"hue", lm_hue, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dh=Lh apply with alpha, Dsv=Lsv, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"saturation", lm_saturation, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Ds=Ls apply with alpha, Dhv=Lhv, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"value", lm_value, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dv=Lv apply with alpha, Dhs=Lhs, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"color", lm_color, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dhs=Lhs apply with alpha, Dv=Lv, aD=aS"},
a0c6c32001-03-17Mirar (Pontus Hagland)  {"value_mul", lm_value_mul, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dv=Lv*Sv apply with alpha, Dhs=Lhs, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"darken", lm_darken, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dv=min(Lv,Sv) apply with alpha, Dhs=Lhs, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"lighten", lm_lighten, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dv=max(Lv,Sv) apply with alpha, Dhs=Lhs, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"saturate", lm_saturate, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Ds=max(Ls,Ss) apply with alpha, Dhv=Lhv, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"desaturate", lm_desaturate, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Ds=min(Ls,Ss) apply with alpha, Dhv=Lhv, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland) 
7bdf522001-03-26Mirar (Pontus Hagland)  {"hls_replace", lm_hls_replace, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dhls=Lhls apply with alpha, aD=aS"},
7bdf522001-03-26Mirar (Pontus Hagland)  {"hls_hue", lm_hls_hue, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dh=Lh apply with alpha, Dsv=Lsv, aD=aS"},
7bdf522001-03-26Mirar (Pontus Hagland)  {"hls_saturation",lm_hls_saturation, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Ds=Ls apply with alpha, Dhv=Lhv, aD=aS"},
7bdf522001-03-26Mirar (Pontus Hagland)  {"hls_lightness", lm_hls_lightness, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dl=Ll apply with alpha, Dhs=Lhs, aD=aS"},
7bdf522001-03-26Mirar (Pontus Hagland)  {"hls_color", lm_hls_color, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dhs=Lhs apply with alpha, Dl=Ll, aD=aS"},
7bdf522001-03-26Mirar (Pontus Hagland)  {"hls_lightness_mul",lm_hls_lightness_mul, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dl=Ll*Sl apply with alpha, Dhs=Lhs, aD=aS"},
7bdf522001-03-26Mirar (Pontus Hagland)  {"hls_darken", lm_hls_darken, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dl=min(Ll,Sl) apply with alpha, Dhs=Lhs, aD=aS"},
7bdf522001-03-26Mirar (Pontus Hagland)  {"hls_lighten", lm_hls_lighten, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Dl=max(Ll,Sl) apply with alpha, Dhs=Lhs, aD=aS"},
7bdf522001-03-26Mirar (Pontus Hagland)  {"hls_saturate", lm_hls_saturate, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Ds=max(Ls,Ss) apply with alpha, Dhl=Lhl, aD=aS"},
7bdf522001-03-26Mirar (Pontus Hagland)  {"hls_desaturate",lm_hls_desaturate, 1, NULL,
7fd2cb2001-03-28Per Hedbor  "Ds=min(Ls,Ss) apply with alpha, Dhl=Lhl, aD=aS"},
7bdf522001-03-26Mirar (Pontus Hagland) 
b77f951999-08-10Mirar (Pontus Hagland)  {"dissolve", lm_dissolve, 1, NULL,
e01a022000-02-08Per Hedbor  "i=random 0 or 1, D=i?L:S, aD=i+aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"behind", lm_behind, 1, NULL,
726c7a1999-08-12Mirar (Pontus Hagland)  "D=(S*aS+L*(1-aS)*aL) / (aS+(1-aS)*aL), aD=(aS+(1-aS)*aL); "
b77f951999-08-10Mirar (Pontus Hagland)  "simply swap S and L"}, {"erase", lm_erase, 1, NULL,
e01a022000-02-08Per Hedbor  "D=S, aD=aS*(1-aL)"},
b77f951999-08-10Mirar (Pontus Hagland)  {"screen", lm_screen, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "1-(1-S)*(1-L) applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"overlay", lm_overlay, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "(1-(1-a)*(1-b)-a*b)*a+a*b applied with alpha, aD=aS"},
b77f951999-08-10Mirar (Pontus Hagland)  {"burn_alpha", (lm_row_func*)lm_spec_burn_alpha, 1, NULL,
a0c6c32001-03-17Mirar (Pontus Hagland)  "aD=aL+aS applied with alpha, D=L+S;" " experimental, may change or be removed"},
b77f951999-08-10Mirar (Pontus Hagland)  {"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, "each channel D=max if L<=S, 0 otherwise, apply with alpha"}, {"more_or_equal", lm_more_or_equal, 0, NULL, "each channel D=max if L>=S, 0 otherwise, apply with alpha"}, {"logic_equal", lm_logic_equal, 0, NULL, "logic: D=white and opaque if L==S, black and transparent otherwise"}, {"logic_not_equal",lm_logic_not_equal,0, NULL, "logic: D=white and opaque if any L!=S, " "black and transparent otherwise"}, {"logic_strict_less",lm_logic_strict_less,0, NULL, "logic: D=white and opaque if all L<S, black and transparent otherwise"}, {"logic_strict_more",lm_logic_strict_more,0, NULL, "logic: D=white and opaque if all L>S, black and transparent otherwise"}, {"logic_strict_less_equal",lm_logic_strict_less_or_equal,0, NULL, "logic: D=white and opaque if all L<=L, " "black and transparent otherwise"}, {"logic_strict_more_equal",lm_logic_strict_more_or_equal,0, NULL, "logic: D=white and opaque if all L>=L, " "black and transparent otherwise"},
7e8e2d1999-04-17Mirar (Pontus Hagland) } ; #define LAYER_MODES ((int)NELEM(layer_mode))
6b7e331999-04-19Mirar (Pontus Hagland) 
1856b31999-04-19Mirar (Pontus Hagland) /*** layer helpers ****************************************/
25aaeb1999-04-23Mirar (Pontus Hagland) #define COMBINE_METHOD_INT #define CCUT_METHOD_INT #define qMAX (1.0/COLORMAX) #define C2F(Z) (qMAX*(Z)) #ifdef CCUT_METHOD_FLOAT
41162a2000-08-06Henrik Grubbström (Grubba) #define CCUT(Z) (DOUBLE_TO_COLORTYPE(qMAX*Z))
25aaeb1999-04-23Mirar (Pontus Hagland) #else /* CCUT_METHOD_INT */
41162a2000-08-06Henrik Grubbström (Grubba) #define CCUT(Z) (DOUBLE_TO_COLORTYPE((Z)/COLORMAX))
25aaeb1999-04-23Mirar (Pontus Hagland) #endif #ifdef COMBINE_METHOD_INT #define COMBINE_ALPHA_SUM(aS,aL) \
41162a2000-08-06Henrik Grubbström (Grubba)  CCUT((COLORMAX*DOUBLE_TO_INT(aL))+(COLORMAX-DOUBLE_TO_INT(aL))*(aS))
25aaeb1999-04-23Mirar (Pontus Hagland) #define COMBINE_ALPHA_SUM_V(aS,aL,V) \ COMBINE_ALPHA_SUM(aS,(aL)*(V)) #define COMBINE_ALPHA(S,L,aS,aL) \
41162a2000-08-06Henrik Grubbström (Grubba)  ( (COLORTYPE)((((S)*(DOUBLE_TO_INT(COLORMAX-(aL)))*(aS))+ \ ((L)*(DOUBLE_TO_INT(aL))*COLORMAX))/ \ (((COLORMAX*DOUBLE_TO_INT(aL))+(COLORMAX-DOUBLE_TO_INT(aL))*(aS))) ) )
25aaeb1999-04-23Mirar (Pontus Hagland)  #define COMBINE_ALPHA_V(S,L,aS,aL,V) \
a33cdf2000-02-22Per Hedbor  COMBINE_ALPHA((S),(L),(aS),((aL)*(V)))
25aaeb1999-04-23Mirar (Pontus Hagland) 
e01a022000-02-08Per Hedbor #else
25aaeb1999-04-23Mirar (Pontus Hagland) #ifdef COMBINE_METHOD_FLOAT #define COMBINE_ALPHA(S,L,aS,aL) \ ( (COLORTYPE)( ( (S)*(1.0-C2F(aL))*C2F(aS) + (L)*C2F(aL) ) / \ ( (C2F(aL)+(1-C2F(aL))*C2F(aS))) ) ) #define COMBINE_ALPHA_V(S,L,aS,aL,V) \ COMBINE_ALPHA(S,(L)*(V),aS,aL) #define COMBINE_ALPHA_SUM(aS,aL) \ ((COLORTYPE)(COLORMAX*(C2F(aL)+(1.0-C2F(aL))*C2F(aS)))) #define COMBINE_ALPHA_SUM_V(aS,aL,V) \ COMBINE_ALPHA_SUM(aS,(aL)*(V)) #else /* unknown COMBINE_METHOD */
a4a1722000-12-05Per Hedbor #error unknown COMBINE_METHOD
25aaeb1999-04-23Mirar (Pontus Hagland) #endif /* COMBINE_METHOD_FLOAT */
e01a022000-02-08Per Hedbor #endif
25aaeb1999-04-23Mirar (Pontus Hagland) 
e94b872000-08-05Henrik Grubbström (Grubba) #define COMBINE(P,A) CCUT((DOUBLE_TO_INT(P))*(A))
41162a2000-08-06Henrik Grubbström (Grubba) #define COMBINE_A(P,A) (DOUBLE_TO_COLORTYPE((P)*(A)))
25aaeb1999-04-23Mirar (Pontus Hagland) #define COMBINE_V(P,V,A) CCUT((V)*(P)*(A))
41162a2000-08-06Henrik Grubbström (Grubba) #define F2C(Z) (DOUBLE_TO_COLORTYPE(COLORMAX*(Z)))
25aaeb1999-04-23Mirar (Pontus Hagland) 
55e2dd1999-04-23Mirar (Pontus Hagland) #define ALPHA_ADD(S,L,D,SA,LA,DA,C) \ if (!(LA)->C) (D)->C=(S)->C,(DA)->C=(SA)->C; \ else if (!(SA)->C) (D)->C=(L)->C,(DA)->C=(LA)->C; \ else if ((LA)->C==COLORMAX) (D)->C=(L)->C,(DA)->C=(LA)->C; \ else \ (D)->C=COMBINE_ALPHA((S)->C,(L)->C,(SA)->C,(LA)->C), \ (DA)->C=COMBINE_ALPHA_SUM((SA)->C,(LA)->C); #define ALPHA_ADD_V_NOLA(L,S,D,SA,DA,V,C) \ do { \ if (!(SA)->C) (D)->C=(L)->C,(DA)->C=0; \ 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); \ (DA)->C=COMBINE_ALPHA_SUM_V((SA)->C,255,V); \ } \
25aaeb1999-04-23Mirar (Pontus Hagland)  } while(0)
55e2dd1999-04-23Mirar (Pontus Hagland) #define ALPHA_ADD_V(L,S,D,LA,SA,DA,V,C) \ do { \
72283a1999-06-30Mirar (Pontus Hagland)  if (!(LA)->C) (D)->C=(S)->C,(DA)->C=(SA)->C; \
55e2dd1999-04-23Mirar (Pontus Hagland)  else if (!(SA)->C) \ { \ (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); \ } \
e01a022000-02-08Per Hedbor  } while (0)
25aaeb1999-04-23Mirar (Pontus Hagland) 
a0c6c32001-03-17Mirar (Pontus Hagland) #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)
25aaeb1999-04-23Mirar (Pontus Hagland) 
1856b31999-04-19Mirar (Pontus Hagland) static INLINE void smear_color(rgb_group *d,rgb_group s,int len) { while (len--) *(d++)=s; }
25aaeb1999-04-23Mirar (Pontus Hagland) #define MAX3(X,Y,Z) MAXIMUM(MAXIMUM(X,Y),Z) #define MIN3(X,Y,Z) MINIMUM(MINIMUM(X,Y),Z)
5923b12000-07-06Fredrik Hübinette (Hubbe) /* Pike_sp was renamed to not_sp by hubbe */ static INLINE void rgb_to_hsv(rgb_group color, double *hp, double *not_sp, double *vp)
25aaeb1999-04-23Mirar (Pontus Hagland) { double max,min,delta; double r,g,b; if (color.r==color.g && color.g==color.b) {
5923b12000-07-06Fredrik Hübinette (Hubbe)  *hp=*not_sp=0.0;
25aaeb1999-04-23Mirar (Pontus Hagland)  *vp=C2F(color.r); return; } r=C2F(color.r); g=C2F(color.g); b=C2F(color.b); max = MAX3(r,g,b); min = MIN3(r,g,b); *vp = max;
5923b12000-07-06Fredrik Hübinette (Hubbe)  *not_sp = (max - min)/max;
25aaeb1999-04-23Mirar (Pontus Hagland)  delta = max-min; if(r==max) *hp = 6+(g-b)/delta; else if(g==max) *hp = 2+(b-r)/delta; else /*if(b==max)*/ *hp = 4+(r-g)/delta; } static INLINE void hsv_to_rgb(double h,double s,double v,rgb_group *colorp) { if (s==0.0) { colorp->r=colorp->g=colorp->b=F2C(v); return; } #define i floor(h) #define f (h-i) #define p F2C(v * (1 - s)) #define q F2C(v * (1 - (s * f))) #define t F2C(v * (1 - (s * (1 -f)))) #define V F2C(v)
e94b872000-08-05Henrik Grubbström (Grubba)  switch(DOUBLE_TO_INT(i))
25aaeb1999-04-23Mirar (Pontus Hagland)  {
e01a022000-02-08Per Hedbor  case 6:
25aaeb1999-04-23Mirar (Pontus Hagland)  case 0: colorp->r = V; colorp->g = t; colorp->b = p; break; case 7: case 1: colorp->r = q; colorp->g = V; colorp->b = p; break; case 2: colorp->r = p; colorp->g = V; colorp->b = t; break; case 3: colorp->r = p; colorp->g = q; colorp->b = V; break; case 4: colorp->r = t; colorp->g = p; colorp->b = V; break; case 5: colorp->r = V; colorp->g = p; colorp->b = q; break; default: fatal("unhandled case\n"); } #undef V #undef i #undef f #undef p #undef q #undef t }
7bdf522001-03-26Mirar (Pontus Hagland) 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 */
9e3e5a2001-09-24Henrik Grubbström (Grubba)  rgb->r = (COLORTYPE)l; rgb->g = (COLORTYPE)l; rgb->b = (COLORTYPE)l;
7bdf522001-03-26Mirar (Pontus Hagland)  } 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) {
15d3ae2001-03-27Henrik Grubbström (Grubba)  max = MAXIMUM(r, b); min = MINIMUM(g, b);
7bdf522001-03-26Mirar (Pontus Hagland)  } else {
15d3ae2001-03-27Henrik Grubbström (Grubba)  max = MAXIMUM(g, b); min = MINIMUM(r, b);
7bdf522001-03-26Mirar (Pontus Hagland)  } 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; }
97d2601999-08-09Mirar (Pontus Hagland) /*** helper ***********************************************/ static int really_optimize_p(struct layer *l) {
e01a022000-02-08Per Hedbor  return
97d2601999-08-09Mirar (Pontus Hagland)  l->optimize_alpha && l->fill_alpha.r==0 && l->fill_alpha.g==0 && l->fill_alpha.b==0 && !l->tiled; }
7e8e2d1999-04-17Mirar (Pontus Hagland) /*** layer object : init and exit *************************/ static void init_layer(struct object *dummy) { THIS->xsize=0; THIS->ysize=0; THIS->xoffs=0; THIS->yoffs=0; THIS->image=NULL; THIS->alpha=NULL; THIS->img=NULL; THIS->alp=NULL; THIS->fill=black; THIS->fill_alpha=black; THIS->tiled=0; THIS->alpha_value=1.0; THIS->row_func=lm_normal;
1856b31999-04-19Mirar (Pontus Hagland)  THIS->optimize_alpha=1;
97d2601999-08-09Mirar (Pontus Hagland)  THIS->really_optimize_alpha=1;
e01a022000-02-08Per Hedbor  THIS->misc=0;
1856b31999-04-19Mirar (Pontus Hagland)  smear_color(THIS->sfill,THIS->fill,SNUMPIXS); smear_color(THIS->sfill_alpha,THIS->fill_alpha,SNUMPIXS);
7e8e2d1999-04-17Mirar (Pontus Hagland) } static void free_layer(struct layer *l) { if (THIS->image) free_object(THIS->image); if (THIS->alpha) free_object(THIS->alpha);
e01a022000-02-08Per Hedbor  if (THIS->misc) free_mapping(THIS->misc);
7e8e2d1999-04-17Mirar (Pontus Hagland)  THIS->image=NULL; THIS->alpha=NULL; THIS->img=NULL; THIS->alp=NULL; } static void exit_layer(struct object *dummy) { free_layer(THIS); } /* **! method object set_image(object(Image.Image) image) **! method object set_image(object(Image.Image) image,object(Image.Image) alpha_channel) **! method object|int(0) image() **! method object|int(0) alpha() **! Set/change/get image and alpha channel for the layer.
e01a022000-02-08Per Hedbor **! You could also cancel the channels giving 0
7e8e2d1999-04-17Mirar (Pontus Hagland) **! instead of an image object. **! note: **! image and alpha channel must be of the same size, **! or canceled. */ static void image_layer_set_image(INT32 args) { struct image *img; if (THIS->image) free_object(THIS->image); THIS->image=NULL; THIS->img=NULL; if (THIS->alpha) free_object(THIS->alpha); THIS->alpha=NULL; THIS->alp=NULL;
132f0d2000-08-13Henrik Grubbström (Grubba)  if (args>=1) {
5923b12000-07-06Fredrik Hübinette (Hubbe)  if ( Pike_sp[-args].type!=T_OBJECT )
7e8e2d1999-04-17Mirar (Pontus Hagland)  {
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (Pike_sp[-args].type!=T_INT || Pike_sp[-args].u.integer!=0)
7e8e2d1999-04-17Mirar (Pontus Hagland)  SIMPLE_BAD_ARG_ERROR("Image.Layer->set_image",1,
1856b31999-04-19Mirar (Pontus Hagland)  "object(Image)|int(0)");
7e8e2d1999-04-17Mirar (Pontus Hagland)  } else if ((img=(struct image*)
5923b12000-07-06Fredrik Hübinette (Hubbe)  get_storage(Pike_sp[-args].u.object,image_program)))
7e8e2d1999-04-17Mirar (Pontus Hagland)  {
5923b12000-07-06Fredrik Hübinette (Hubbe)  THIS->image=Pike_sp[-args].u.object;
7e8e2d1999-04-17Mirar (Pontus Hagland)  add_ref(THIS->image); THIS->img=img; THIS->xsize=img->xsize; THIS->ysize=img->ysize; } else SIMPLE_BAD_ARG_ERROR("Image.Layer->set_image",1,
1856b31999-04-19Mirar (Pontus Hagland)  "object(Image)|int(0)");
132f0d2000-08-13Henrik Grubbström (Grubba)  }
7e8e2d1999-04-17Mirar (Pontus Hagland) 
132f0d2000-08-13Henrik Grubbström (Grubba)  if (args>=2) {
5923b12000-07-06Fredrik Hübinette (Hubbe)  if ( Pike_sp[1-args].type!=T_OBJECT )
7e8e2d1999-04-17Mirar (Pontus Hagland)  {
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (Pike_sp[1-args].type!=T_INT || Pike_sp[1-args].u.integer!=0)
7e8e2d1999-04-17Mirar (Pontus Hagland)  SIMPLE_BAD_ARG_ERROR("Image.Layer->set_image",2,
1856b31999-04-19Mirar (Pontus Hagland)  "object(Image)|int(0)");
7e8e2d1999-04-17Mirar (Pontus Hagland)  } else if ((img=(struct image*)
5923b12000-07-06Fredrik Hübinette (Hubbe)  get_storage(Pike_sp[1-args].u.object,image_program)))
7e8e2d1999-04-17Mirar (Pontus Hagland)  { if (THIS->img && (img->xsize!=THIS->xsize || img->ysize!=THIS->ysize)) SIMPLE_BAD_ARG_ERROR("Image.Layer->set_image",2, "image of same size"); if (!THIS->img) { THIS->xsize=img->xsize; THIS->ysize=img->ysize; }
5923b12000-07-06Fredrik Hübinette (Hubbe)  THIS->alpha=Pike_sp[1-args].u.object;
7e8e2d1999-04-17Mirar (Pontus Hagland)  add_ref(THIS->alpha); THIS->alp=img; } else SIMPLE_BAD_ARG_ERROR("Image.Layer->set_image",2,
1856b31999-04-19Mirar (Pontus Hagland)  "object(Image)|int(0)");
132f0d2000-08-13Henrik Grubbström (Grubba)  }
7e8e2d1999-04-17Mirar (Pontus Hagland)  pop_n_elems(args); ref_push_object(THISOBJ); }
e01a022000-02-08Per Hedbor static void image_layer_get_misc_value( INT32 args ) { if( args != 1 )
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Wrong number of arguments to get_misc_value\n");
e01a022000-02-08Per Hedbor  if( THIS->misc ) { ref_push_mapping( THIS->misc ); stack_swap(); f_index( 2 ); } else { pop_n_elems( args ); push_int( 0 ); } } /* **! method mixed set_misc_value( mixed what, mixed to ) **! method mixed get_misc_value( mixed what ) **! Set or query misc. attributes for the layer. **! **! As an example, the XCF and PSD image decoders set the 'name' attribute **! to the name the layer had in the source file. */ static void image_layer_set_misc_value( INT32 args ) { if( args != 2 )
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Wrong number of arguments to set_misc_value\n");
e01a022000-02-08Per Hedbor  if( !THIS->misc ) THIS->misc = allocate_mapping( 4 );
5923b12000-07-06Fredrik Hübinette (Hubbe)  mapping_insert( THIS->misc, Pike_sp-2, Pike_sp-1 );
e01a022000-02-08Per Hedbor  stack_swap(); pop_stack(); }
7e8e2d1999-04-17Mirar (Pontus Hagland) static void image_layer_image(INT32 args) { pop_n_elems(args); if (THIS->image) ref_push_object(THIS->image); else push_int(0); }
6b7e331999-04-19Mirar (Pontus Hagland) 
7e8e2d1999-04-17Mirar (Pontus Hagland) static void image_layer_alpha(INT32 args) { pop_n_elems(args); if (THIS->alpha) ref_push_object(THIS->alpha); else push_int(0); } /* **! method object set_alpha_value(float value)
25aaeb1999-04-23Mirar (Pontus Hagland) **! method double alpha_value()
7e8e2d1999-04-17Mirar (Pontus Hagland) **! Set/get the general alpha value of this layer. **! This is a float value between 0 and 1, **! and is multiplied with the alpha channel. */ static void image_layer_set_alpha_value(INT32 args) {
65a5492000-08-10Per Hedbor  FLOAT_TYPE f;
7e8e2d1999-04-17Mirar (Pontus Hagland)  get_all_args("Image.Layer->set_alpha_value",args,"%F",&f);
d883131999-06-28Per Hedbor  if (f<0.0 || f>1.0)
7e8e2d1999-04-17Mirar (Pontus Hagland)  SIMPLE_BAD_ARG_ERROR("Image.Layer->set_alpha_value",1,"float(0..1)"); THIS->alpha_value=f;
72283a1999-06-30Mirar (Pontus Hagland)  pop_n_elems(args); ref_push_object(THISOBJ);
7e8e2d1999-04-17Mirar (Pontus Hagland) } static void image_layer_alpha_value(INT32 args) { pop_n_elems(args); push_float(THIS->alpha_value); } /* **! method object set_mode(string mode) **! method string mode()
3695ff1999-04-19Mirar (Pontus Hagland) **! method array(string) available_modes()
e01a022000-02-08Per Hedbor **! Set/get layer mode. Mode is one of these: **! **! "normal", **! "add", **! "subtract", **! "multiply", **! "divide", **! "modulo", **! "invsubtract", **! "invdivide", **! "invmodulo", **! "difference", **! "max", **! "min", **! "bitwise_and", **! "bitwise_or", **! "bitwise_xor", **! **! "replace", **! "red", **! "green", **! "blue", **! **! "replace_hsv", **! "hue", **! "saturation", **! "value", **! "color",
7e8e2d1999-04-17Mirar (Pontus Hagland) **!
e01a022000-02-08Per Hedbor **! "darken", **! "lighten",
7e8e2d1999-04-17Mirar (Pontus Hagland) **!
e01a022000-02-08Per Hedbor **! "dissolve", **! "behind", **! "erase", **! **! <ref>available_modes</ref>() simply gives an array
3695ff1999-04-19Mirar (Pontus Hagland) **! containing the names of these modes. **!
7e8e2d1999-04-17Mirar (Pontus Hagland) **! note: **! image and alpha channel must be of the same size, **! or canceled. */ static void image_layer_set_mode(INT32 args) { int i; if (args!=1) SIMPLE_TOO_FEW_ARGS_ERROR("Image.Layer->set_mode",1);
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (Pike_sp[-args].type!=T_STRING)
7e8e2d1999-04-17Mirar (Pontus Hagland)  SIMPLE_BAD_ARG_ERROR("Image.Layer->set_mode",1,"string");
e01a022000-02-08Per Hedbor 
7e8e2d1999-04-17Mirar (Pontus Hagland)  for (i=0; i<LAYER_MODES; i++)
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (Pike_sp[-args].u.string==layer_mode[i].ps)
7e8e2d1999-04-17Mirar (Pontus Hagland)  { THIS->row_func=layer_mode[i].func;
1856b31999-04-19Mirar (Pontus Hagland)  THIS->optimize_alpha=layer_mode[i].optimize_alpha;
97d2601999-08-09Mirar (Pontus Hagland)  THIS->really_optimize_alpha=really_optimize_p(THIS);
e01a022000-02-08Per Hedbor 
7e8e2d1999-04-17Mirar (Pontus Hagland)  pop_n_elems(args); ref_push_object(THISOBJ); return; }
1856b31999-04-19Mirar (Pontus Hagland)  SIMPLE_BAD_ARG_ERROR("Image.Layer->set_mode",1,"existing mode");
7e8e2d1999-04-17Mirar (Pontus Hagland) } static void image_layer_mode(INT32 args) { int i; pop_n_elems(args);
e01a022000-02-08Per Hedbor 
7e8e2d1999-04-17Mirar (Pontus Hagland)  for (i=0; i<LAYER_MODES; i++) if (THIS->row_func==layer_mode[i].func) { ref_push_string(layer_mode[i].ps); return; }
e3b79d2001-01-19Henrik Grubbström (Grubba)  fatal("illegal mode: %p\n", (void *)layer_mode[i].func);
7e8e2d1999-04-17Mirar (Pontus Hagland) }
3695ff1999-04-19Mirar (Pontus Hagland) static void image_layer_available_modes(INT32 args) { int i; pop_n_elems(args);
e01a022000-02-08Per Hedbor 
3695ff1999-04-19Mirar (Pontus Hagland)  for (i=0; i<LAYER_MODES; i++) ref_push_string(layer_mode[i].ps); f_aggregate(LAYER_MODES); }
b77f951999-08-10Mirar (Pontus Hagland) static void image_layer_descriptions(INT32 args) { int i; pop_n_elems(args);
e01a022000-02-08Per Hedbor 
b77f951999-08-10Mirar (Pontus Hagland)  for (i=0; i<LAYER_MODES; i++)
61126d2000-01-30Fredrik Hübinette (Hubbe)  push_string(make_shared_string(layer_mode[i].desc));
b77f951999-08-10Mirar (Pontus Hagland)  f_aggregate(LAYER_MODES); }
7e8e2d1999-04-17Mirar (Pontus Hagland) /* **! method object set_fill(Color color) **! method object set_fill(Color color,Color alpha) **! method object fill() **! method object fill_alpha()
e01a022000-02-08Per Hedbor **! Set/query fill color and alpha, ie the color used "outside" the
7e8e2d1999-04-17Mirar (Pontus Hagland) **! image. This is mostly useful if you want to "frame" **! a layer. */ static void image_layer_set_fill(INT32 args) { if (!args) SIMPLE_TOO_FEW_ARGS_ERROR("Image.Layer->set_fill",1);
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (Pike_sp[-args].type==T_INT && !Pike_sp[-args].u.integer)
7e8e2d1999-04-17Mirar (Pontus Hagland)  THIS->fill=black; else if (!image_color_arg(-args,&(THIS->fill))) SIMPLE_BAD_ARG_ERROR("Image.Layer->set_fill",1,"color");
1856b31999-04-19Mirar (Pontus Hagland)  smear_color(THIS->sfill,THIS->fill,SNUMPIXS); THIS->fill_alpha=white;
132f0d2000-08-13Henrik Grubbström (Grubba)  if (args>1) {
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (Pike_sp[1-args].type==T_INT && !Pike_sp[1-args].u.integer)
1856b31999-04-19Mirar (Pontus Hagland)  ; /* white is good */
7e8e2d1999-04-17Mirar (Pontus Hagland)  else if (!image_color_arg(1-args,&(THIS->fill_alpha)))
1856b31999-04-19Mirar (Pontus Hagland)  { smear_color(THIS->sfill_alpha,THIS->fill_alpha,SNUMPIXS);
7e8e2d1999-04-17Mirar (Pontus Hagland)  SIMPLE_BAD_ARG_ERROR("Image.Layer->set_fill",2,"color");
1856b31999-04-19Mirar (Pontus Hagland)  }
132f0d2000-08-13Henrik Grubbström (Grubba)  }
1856b31999-04-19Mirar (Pontus Hagland)  smear_color(THIS->sfill_alpha,THIS->fill_alpha,SNUMPIXS); #if 0 { int i; for (i=0; i<SNUMPIXS; i++) fprintf(stderr,"#%02x%02x%02x ",THIS->sfill_alpha[i].r,THIS->sfill_alpha[i].g,THIS->sfill_alpha[i].b); fprintf(stderr,"\n"); for (i=0; i<SNUMPIXS; i++) fprintf("stderr,#%02x%02x%02x ",THIS->sfill[i].r,THIS->sfill[i].g,THIS->sfill[i].b); fprintf(stderr,"\n"); } #endif
7e8e2d1999-04-17Mirar (Pontus Hagland) 
97d2601999-08-09Mirar (Pontus Hagland)  THIS->really_optimize_alpha=really_optimize_p(THIS);
7e8e2d1999-04-17Mirar (Pontus Hagland)  pop_n_elems(args); ref_push_object(THISOBJ); } static void image_layer_fill(INT32 args) { pop_n_elems(args); _image_make_rgb_color(THIS->fill.r,THIS->fill.g,THIS->fill.b); } static void image_layer_fill_alpha(INT32 args) { pop_n_elems(args); _image_make_rgb_color(THIS->fill_alpha.r, THIS->fill_alpha.g, THIS->fill_alpha.b); } /* **! method object set_offset(int x,int y) **! method int xoffset() **! method int yoffset() **! Set/query layer offset.
55e2dd1999-04-23Mirar (Pontus Hagland) **! **! method int xsize() **! method int ysize() **! Query layer offset. This is the same as layer **! image/alpha image size.
7e8e2d1999-04-17Mirar (Pontus Hagland) */ static void image_layer_set_offset(INT32 args) { get_all_args("Image.Layer->set_offset",args,"%i%i", &(THIS->xoffs),&(THIS->yoffs)); pop_n_elems(args); ref_push_object(THISOBJ); } static void image_layer_xoffset(INT32 args) { pop_n_elems(args); push_int(THIS->xoffs); } static void image_layer_yoffset(INT32 args) { pop_n_elems(args); push_int(THIS->yoffs); }
55e2dd1999-04-23Mirar (Pontus Hagland) static void image_layer_xsize(INT32 args) { pop_n_elems(args); push_int(THIS->xsize); } static void image_layer_ysize(INT32 args) { pop_n_elems(args); push_int(THIS->ysize); }
7e8e2d1999-04-17Mirar (Pontus Hagland) /* **! method object set_tiled(int yes) **! method int tiled() **! Set/query <i>tiled</i> flag. If set, the **! image and alpha channel will be tiled rather **! then framed by the <ref>fill</ref> values. */ static void image_layer_set_tiled(INT32 args) { get_all_args("Image.Layer->set_offset",args,"%i", &(THIS->tiled)); THIS->tiled=!!THIS->tiled;
97d2601999-08-09Mirar (Pontus Hagland)  THIS->really_optimize_alpha=really_optimize_p(THIS);
7e8e2d1999-04-17Mirar (Pontus Hagland)  pop_n_elems(args); ref_push_object(THISOBJ); } static void image_layer_tiled(INT32 args) { pop_n_elems(args); push_int(THIS->tiled); } /* **! method void create(object image,object alpha,string mode) **! method void create(mapping info) **! method void create()
f9c8eb1999-07-02Mirar (Pontus Hagland) **
7e8e2d1999-04-17Mirar (Pontus Hagland) **! method void create(int xsize,int ysize,object color) **! method void create(object color) **! The Layer construct either three arguments, **! the image object, alpha channel and mode, or **! a mapping with optional elements: **! <pre>
e01a022000-02-08Per Hedbor **! "image":image,
7e8e2d1999-04-17Mirar (Pontus Hagland) **! // default: black **!
e01a022000-02-08Per Hedbor **! "alpha":alpha,
7e8e2d1999-04-17Mirar (Pontus Hagland) **! // alpha channel object **! // default: full opaque **! **! "mode":string mode, **! // layer mode, see <ref>mode</ref>. **! // default: "normal" **! **! "alpha_value":float(0.0-1.0), **! // layer general alpha value **! // default is 1.0; this is multiplied **! // with the alpha channel. **! **! "xoffset":int, **! "yoffset":int, **! // offset of this layer **!
e01a022000-02-08Per Hedbor **! "fill":Color,
7e8e2d1999-04-17Mirar (Pontus Hagland) **! "fill_alpha":Color, **! // fill color, ie what color is used **! // "outside" the image. default: black **! // and black (full transparency). **! **! "tiled":int(0|1), **! // select tiling; if 1, the image **! // will be tiled. deafult: 0, off
e01a022000-02-08Per Hedbor **! </pre>
7e8e2d1999-04-17Mirar (Pontus Hagland) **! The layer can also be created "empty", **! either giving a size and color - **! this will give a filled opaque square, **! or a color, which will set the "fill" **! values and fill the whole layer with an **! opaque color. **! **! All values can be modified after object creation. **! **! note: **! image and alpha channel must be of the same size.
e01a022000-02-08Per Hedbor **!
7e8e2d1999-04-17Mirar (Pontus Hagland) */ static INLINE void try_parameter(char *a,void (*f)(INT32)) { stack_dup(); push_text(a); f_index(2);
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (!IS_UNDEFINED(Pike_sp-1))
7e8e2d1999-04-17Mirar (Pontus Hagland)  f(1); pop_stack(); } static INLINE void try_parameter_pair(char *a,char *b,void (*f)(INT32)) { stack_dup(); /* map map */ stack_dup(); /* map map map */ push_text(a); /* map map map a */ f_index(2); /* map map map[a] */ stack_swap(); /* map map[a] map */ push_text(b); /* map map[a] map b */ f_index(2); /* map map[a] map[b] */
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (!IS_UNDEFINED(Pike_sp-2) || !IS_UNDEFINED(Pike_sp-1))
7e8e2d1999-04-17Mirar (Pontus Hagland)  { f(2); pop_stack(); }
e01a022000-02-08Per Hedbor  else
7e8e2d1999-04-17Mirar (Pontus Hagland)  pop_n_elems(2); } static void image_layer_create(INT32 args) { if (!args) return;
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (Pike_sp[-args].type==T_MAPPING)
7e8e2d1999-04-17Mirar (Pontus Hagland)  { pop_n_elems(args-1); try_parameter_pair("image","alpha",image_layer_set_image); try_parameter("mode",image_layer_set_mode); try_parameter("alpha_value",image_layer_set_alpha_value); try_parameter_pair("xoffset","yoffset",image_layer_set_offset); try_parameter_pair("fill","fill_alpha",image_layer_set_fill); try_parameter("tiled",image_layer_set_tiled); pop_stack(); return; }
5923b12000-07-06Fredrik Hübinette (Hubbe)  else if (Pike_sp[-args].type==T_INT && args>1 && Pike_sp[1-args].type==T_INT)
7e8e2d1999-04-17Mirar (Pontus Hagland)  { rgb_group col=black,alpha=white; get_all_args("Image.Layer",args,"%i%i",&(THIS->xsize),&(THIS->ysize)); if (args>2) if (!image_color_arg(2-args,&col)) SIMPLE_BAD_ARG_ERROR("Image.Layer",3,"Image.Color");
e01a022000-02-08Per Hedbor 
7e8e2d1999-04-17Mirar (Pontus Hagland)  if (args>3) if (!image_color_arg(3-args,&alpha)) SIMPLE_BAD_ARG_ERROR("Image.Layer",4,"Image.Color");
e01a022000-02-08Per Hedbor 
7e8e2d1999-04-17Mirar (Pontus Hagland)  push_int(THIS->xsize); push_int(THIS->ysize); push_int(col.r); push_int(col.g); push_int(col.b); push_object(clone_object(image_program,5)); push_int(THIS->xsize); push_int(THIS->ysize); push_int(alpha.r); push_int(alpha.g); push_int(alpha.b); push_object(clone_object(image_program,5));
e01a022000-02-08Per Hedbor 
7e8e2d1999-04-17Mirar (Pontus Hagland)  image_layer_set_image(2); pop_n_elems(args); }
5923b12000-07-06Fredrik Hübinette (Hubbe)  else if (Pike_sp[-args].type==T_OBJECT || args>1)
7e8e2d1999-04-17Mirar (Pontus Hagland)  { if (args>2) { image_layer_set_mode(args-2);
1856b31999-04-19Mirar (Pontus Hagland)  pop_stack();
7e8e2d1999-04-17Mirar (Pontus Hagland)  args=2; } image_layer_set_image(args); pop_stack(); } else SIMPLE_BAD_ARG_ERROR("Image.Layer",1,"mapping|int|Image.Image"); } /*** layer object *****************************************/ static void image_layer_cast(INT32 args) { if (!args) SIMPLE_TOO_FEW_ARGS_ERROR("Image.Layer->cast",1);
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (Pike_sp[-args].type==T_STRING||Pike_sp[-args].u.string->size_shift)
7e8e2d1999-04-17Mirar (Pontus Hagland)  {
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (strncmp(Pike_sp[-args].u.string->str,"mapping",7)==0)
7e8e2d1999-04-17Mirar (Pontus Hagland)  { int n=0; pop_n_elems(args);
e01a022000-02-08Per Hedbor 
7e8e2d1999-04-17Mirar (Pontus Hagland)  push_text("xsize"); push_int(THIS->xsize); n++; push_text("ysize"); push_int(THIS->ysize); n++; push_text("image"); image_layer_image(0); n++;
fc74581999-07-01Per Hedbor  push_text("alpha"); image_layer_alpha(0); n++;
7e8e2d1999-04-17Mirar (Pontus Hagland)  push_text("xoffset"); push_int(THIS->xoffs); n++; push_text("yoffset"); push_int(THIS->yoffs); n++; push_text("alpha_value"); push_float(THIS->alpha_value); n++; push_text("fill"); image_layer_fill(0); n++; push_text("fill_alpha"); image_layer_fill_alpha(0); n++; push_text("tiled"); push_int(THIS->tiled); n++; push_text("mode"); image_layer_mode(0); n++; f_aggregate_mapping(n*2); return; } } SIMPLE_BAD_ARG_ERROR("Image.Colortable->cast",1, "string(\"mapping\"|\"array\"|\"string\")"); } /*** 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,
25aaeb1999-04-23Mirar (Pontus Hagland)  int len,double alpha)
7e8e2d1999-04-17Mirar (Pontus Hagland) { /* la may be NULL, no other */ if (alpha==0.0) /* optimized */ {
776acd1999-08-10Mirar (Pontus Hagland) #ifdef LAYERS_DUAL
25aaeb1999-04-23Mirar (Pontus Hagland)  MEMCPY(d,s,sizeof(rgb_group)*len); MEMCPY(da,sa,sizeof(rgb_group)*len);
776acd1999-08-10Mirar (Pontus Hagland) #endif
e01a022000-02-08Per Hedbor  return;
7e8e2d1999-04-17Mirar (Pontus Hagland)  } else if (alpha==1.0) { if (!la) /* no layer alpha => full opaque */ {
1856b31999-04-19Mirar (Pontus Hagland)  MEMCPY(d,l,sizeof(rgb_group)*len);
7e8e2d1999-04-17Mirar (Pontus Hagland)  smear_color(da,white,len); } else
776acd1999-08-10Mirar (Pontus Hagland)  {
7e8e2d1999-04-17Mirar (Pontus Hagland)  while (len--) {
776acd1999-08-10Mirar (Pontus Hagland)  if (la->r==0 && la->g==0 && la->b==0) {
4317241999-08-16Mirar (Pontus Hagland)  *d=*s; *da=*sa;
776acd1999-08-10Mirar (Pontus Hagland)  } else if (la->r==COLORMAX && la->g==COLORMAX && la->b==COLORMAX)
7e8e2d1999-04-17Mirar (Pontus Hagland)  { *d=*l; *da=*la; }
776acd1999-08-10Mirar (Pontus Hagland)  else if (l->r==COLORMAX && l->g==COLORMAX && l->b==COLORMAX)
7e8e2d1999-04-17Mirar (Pontus Hagland)  {
776acd1999-08-10Mirar (Pontus Hagland)  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);
7e8e2d1999-04-17Mirar (Pontus Hagland)  } 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++; }
776acd1999-08-10Mirar (Pontus Hagland)  }
7e8e2d1999-04-17Mirar (Pontus Hagland)  } 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);
a33cdf2000-02-22Per Hedbor  l++; s++; sa++; da++; d++;
7e8e2d1999-04-17Mirar (Pontus Hagland)  } else while (len--) { ALPHA_ADD_V(s,l,d,sa,la,da,alpha,r); ALPHA_ADD_V(s,l,d,sa,la,da,alpha,g); ALPHA_ADD_V(s,l,d,sa,la,da,alpha,b); l++; s++; la++; sa++; da++; d++; } return; } }
e58a6f2000-08-06Henrik Grubbström (Grubba) 
32f88c2000-08-07Henrik Grubbström (Grubba) #if defined(__ECL) && 0
8c2eb12000-08-06Henrik Grubbström (Grubba) #define WARN_TRACE(X) static char PIKE_CONCAT(foo__, X) (double d) { return (char)d; }
e58a6f2000-08-06Henrik Grubbström (Grubba) #else /* !__ECL */ #define WARN_TRACE(X) #endif /* __ECL */
5e39651999-04-22Mirar (Pontus Hagland) /* operators from template */
a0c6c32001-03-17Mirar (Pontus Hagland) #define L_COPY_ALPHA
5e39651999-04-22Mirar (Pontus Hagland) #define LM_FUNC lm_add #define L_TRUNC(X) MINIMUM(255,(X))
a0c6c32001-03-17Mirar (Pontus Hagland) #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))
726c7a1999-08-12Mirar (Pontus Hagland) #define L_MMX_OPER(A,MMXR) paddusb_m2r(A,MMXR)
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(1);
5e39651999-04-22Mirar (Pontus Hagland) #include "layer_oper.h"
726c7a1999-08-12Mirar (Pontus Hagland) #undef L_MMX_OPER
5e39651999-04-22Mirar (Pontus Hagland) #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_subtract #define L_TRUNC(X) MAXIMUM(0,(X))
a0c6c32001-03-17Mirar (Pontus Hagland) #define L_OPER(A,B) ((A)-(int)(B))
8223ea1999-08-13Per Hedbor #define L_MMX_OPER(A,MMXR) psubusb_m2r(A,MMXR)
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(2);
5e39651999-04-22Mirar (Pontus Hagland) #include "layer_oper.h"
8223ea1999-08-13Per Hedbor #undef L_MMX_OPER
5e39651999-04-22Mirar (Pontus Hagland) #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_multiply #define L_TRUNC(X) (X)
a0c6c32001-03-17Mirar (Pontus Hagland) #define L_OPER(A,B) CCUT((A)*(int)(B))
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(3);
5e39651999-04-22Mirar (Pontus Hagland) #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))
a0c6c32001-03-17Mirar (Pontus Hagland) #define L_OPER(A,B) MINIMUM( DOUBLE_TO_INT((A)/C2F(1+(int)(B))), COLORMAX)
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(4);
5e39651999-04-22Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER
7fd2cb2001-03-28Per Hedbor #define LM_FUNC lm_negdivide #define L_TRUNC(X) MINIMUM(255,(X)) #define L_OPER(A,B) 1.0-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
5e39651999-04-22Mirar (Pontus Hagland) #define LM_FUNC lm_modulo
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
5e39651999-04-22Mirar (Pontus Hagland) #define L_OPER(A,B) ((A)%((B)?(B):1))
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(5);
5e39651999-04-22Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER
54e0781999-04-24Mirar (Pontus Hagland) #define L_USE_SA #define LM_FUNC lm_invsubtract #define L_TRUNC(X) MAXIMUM(0,(X))
a0c6c32001-03-17Mirar (Pontus Hagland) #define L_OPER(A,B) ((B)-(int)(A))
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(6);
54e0781999-04-24Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER
5e39651999-04-22Mirar (Pontus Hagland) #define LM_FUNC lm_invdivide #define L_TRUNC(X) MINIMUM(255,(X))
a0c6c32001-03-17Mirar (Pontus Hagland) #define L_OPER(A,B) MINIMUM( DOUBLE_TO_INT((B)/C2F(1+(int)(A))), COLORMAX)
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(7);
5e39651999-04-22Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_invmodulo
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
54e0781999-04-24Mirar (Pontus Hagland) #define L_OPER(A,B) ((B)%((A)?(A):1))
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(8);
5e39651999-04-22Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER
eae4da1999-04-19Mirar (Pontus Hagland) 
a0c6c32001-03-17Mirar (Pontus Hagland) #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
54e0781999-04-24Mirar (Pontus Hagland) #undef L_USE_SA
55e2dd1999-04-23Mirar (Pontus Hagland) #define LM_FUNC lm_difference
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
55e2dd1999-04-23Mirar (Pontus Hagland) #define L_OPER(A,B) abs((A)-(B))
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(9);
55e2dd1999-04-23Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_max
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
55e2dd1999-04-23Mirar (Pontus Hagland) #define L_OPER(A,B) MAXIMUM((A),(B))
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(10);
55e2dd1999-04-23Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_min
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
55e2dd1999-04-23Mirar (Pontus Hagland) #define L_OPER(A,B) MINIMUM((A),(B))
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(11);
55e2dd1999-04-23Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_bitwise_and
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
55e2dd1999-04-23Mirar (Pontus Hagland) #define L_OPER(A,B) ((A)&(B))
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(12);
55e2dd1999-04-23Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_bitwise_or
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
55e2dd1999-04-23Mirar (Pontus Hagland) #define L_OPER(A,B) ((A)|(B))
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(13);
55e2dd1999-04-23Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_bitwise_xor
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
55e2dd1999-04-23Mirar (Pontus Hagland) #define L_OPER(A,B) ((A)^(B))
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(14);
55e2dd1999-04-23Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER
a0c6c32001-03-17Mirar (Pontus Hagland) #undef L_COPY_ALPHA
7383191999-06-21Mirar (Pontus Hagland) #define LM_FUNC lm_equal
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
7383191999-06-21Mirar (Pontus Hagland) #define L_OPER(A,B) (((A)==(B))?COLORMAX:0)
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(15);
7383191999-06-21Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_not_equal
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
7383191999-06-21Mirar (Pontus Hagland) #define L_OPER(A,B) (((A)!=(B))?COLORMAX:0)
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(16);
7383191999-06-21Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_less
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
7383191999-06-21Mirar (Pontus Hagland) #define L_OPER(A,B) (((A)>(B))?COLORMAX:0)
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(17);
7383191999-06-21Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_more
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
7383191999-06-21Mirar (Pontus Hagland) #define L_OPER(A,B) (((A)<(B))?COLORMAX:0)
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(18);
7383191999-06-21Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_less_or_equal
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
7383191999-06-21Mirar (Pontus Hagland) #define L_OPER(A,B) (((A)>=(B))?COLORMAX:0)
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(19);
7383191999-06-21Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER #define LM_FUNC lm_more_or_equal
41162a2000-08-06Henrik Grubbström (Grubba) #define L_TRUNC(X) (DOUBLE_TO_COLORTYPE(X))
7383191999-06-21Mirar (Pontus Hagland) #define L_OPER(A,B) (((A)<=(B))?COLORMAX:0)
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(20);
7383191999-06-21Mirar (Pontus Hagland) #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER /* logic functions */ #define L_LOGIC(A,B,C) (((A)&&(B)&&(C))?white:black) #define LM_FUNC lm_logic_equal #define L_OPER(A,B) ((A)==(B)) #define L_TRANS white
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(21);
7383191999-06-21Mirar (Pontus Hagland) #include "layer_oper.h" #undef L_TRANS #undef L_OPER #undef LM_FUNC #undef L_LOGIC #define L_LOGIC(A,B,C) (((A)||(B)||(C))?white:black) #define LM_FUNC lm_logic_not_equal #define L_OPER(A,B) ((A)!=(B)) #define L_TRANS black
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(22);
7383191999-06-21Mirar (Pontus Hagland) #include "layer_oper.h" #undef L_TRANS #undef L_OPER #undef LM_FUNC #undef L_LOGIC #define L_LOGIC(A,B,C) (((A)&&(B)&&(C))?white:black) #define LM_FUNC lm_logic_strict_less #define L_OPER(A,B) ((A)>(B)) #define L_TRANS white
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(23);
7383191999-06-21Mirar (Pontus Hagland) #include "layer_oper.h" #undef L_TRANS #undef L_OPER #undef LM_FUNC #undef L_LOGIC #define L_LOGIC(A,B,C) (((A)&&(B)&&(C))?white:black) #define LM_FUNC lm_logic_strict_more #define L_OPER(A,B) ((A)<(B)) #define L_TRANS white
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(24);
7383191999-06-21Mirar (Pontus Hagland) #include "layer_oper.h" #undef L_TRANS #undef L_OPER #undef LM_FUNC #undef L_LOGIC #define L_LOGIC(A,B,C) (((A)&&(B)&&(C))?white:black) #define LM_FUNC lm_logic_strict_less_or_equal #define L_OPER(A,B) ((A)>=(B)) #define L_TRANS white
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(25);
7383191999-06-21Mirar (Pontus Hagland) #include "layer_oper.h" #undef L_TRANS #undef L_OPER #undef LM_FUNC #undef L_LOGIC #define L_LOGIC(A,B,C) (((A)&&(B)&&(C))?white:black) #define LM_FUNC lm_logic_strict_more_or_equal #define L_OPER(A,B) ((A)<=(B)) #define L_TRANS white
db819d2000-08-06Henrik Grubbström (Grubba) WARN_TRACE(26);
7383191999-06-21Mirar (Pontus Hagland) #include "layer_oper.h" #undef L_TRANS #undef L_OPER #undef LM_FUNC #undef L_LOGIC
25aaeb1999-04-23Mirar (Pontus Hagland) /* channels from template */ /* replace rgb by alpha channel */ #define LM_FUNC lm_replace #define L_CHANNEL_DO(S,L,D,A) \ ((D).r=COMBINE_ALPHA((S).r,(L).r,COLORMAX,(A).r), \ (D).g=COMBINE_ALPHA((S).g,(L).g,COLORMAX,(A).g), \ (D).b=COMBINE_ALPHA((S).b,(L).b,COLORMAX,(A).b)) #define L_CHANNEL_DO_V(S,L,D,A,V) \ ((D).r=COMBINE_ALPHA_V((S).r,(L).r,COLORMAX,(A).r,(V)), \ (D).g=COMBINE_ALPHA_V((S).g,(L).g,COLORMAX,(A).g,(V)), \ (D).b=COMBINE_ALPHA_V((S).b,(L).b,COLORMAX,(A).b,(V))) #include "layer_channel.h" #undef L_CHANNEL_DO #undef L_CHANNEL_DO_V #undef LM_FUNC /* replace r, g or b (by alpha channel, only that color counts) */ #define LM_FUNC lm_red #define L_CHANNEL_DO(S,L,D,A) \ ((D).r=COMBINE_ALPHA((S).r,(L).r,COLORMAX,(A).r), \ (D).g=(S).g,(D).b=(S).b) #define L_CHANNEL_DO_V(S,L,D,A,V) \ ((D).r=COMBINE_ALPHA_V((S).r,(L).r,COLORMAX,(A).r,(V)), \ (D).g=(S).g,(D).b=(S).b) #include "layer_channel.h" #undef L_CHANNEL_DO #undef L_CHANNEL_DO_V #undef LM_FUNC #define LM_FUNC lm_green #define L_CHANNEL_DO(S,L,D,A) \ ((D).g=COMBINE_ALPHA((S).g,(L).g,COLORMAX,(A).g), \ (D).r=(S).r,(D).b=(S).b) #define L_CHANNEL_DO_V(S,L,D,A,V) \ ((D).g=COMBINE_ALPHA_V((S).g,(L).g,COLORMAX,(A).g,(V)), \ (D).r=(S).r,(D).b=(S).b) #include "layer_channel.h" #undef L_CHANNEL_DO #undef L_CHANNEL_DO_V #undef LM_FUNC #define LM_FUNC lm_blue #define L_CHANNEL_DO(S,L,D,A) \ ((D).b=COMBINE_ALPHA((S).b,(L).b,COLORMAX,(A).b), \ (D).g=(S).g,(D).r=(S).r) #define L_CHANNEL_DO_V(S,L,D,A,V) \ ((D).b=COMBINE_ALPHA_V((S).b,(L).b,COLORMAX,(A).b,(V)), \ (D).g=(S).g,(D).r=(S).r) #include "layer_channel.h" #undef L_CHANNEL_DO #undef L_CHANNEL_DO_V #undef LM_FUNC
7fd2cb2001-03-28Per Hedbor  #define LM_FUNC lm_hardlight #define L_CHANNEL_DO(S,L,D,A) L_CHANNEL_DO_V(S,L,D,A,1.0) #define L_CHANNEL_DO_V(S,L,D,A,V) do { \ int v; \ rgb_group tmp; \ int tr, tg, tb; \ if( (L).r > 128 ) \ v = 255 - (((255 - (S).r) * (256 - (((L).r - 128)<<1))) >> 8); \ else \ v = ((S).r * ((L).r<<1))>>8; \ tmp.r = MAXIMUM(MINIMUM(v,255),0); \ \ if( (L).g > 128 ) \ v = 255 - (((255 - (S).g) * (256 - (((L).g - 128)<<1))) >> 8); \ else \ v = ((S).g * ((L).g<<1))>>8; \ tmp.g = MAXIMUM(MINIMUM(v,255),0); \ \ if( (L).b > 128 ) \ v = 255 - (((255 - (S).b) * (256 - (((L).b - 128)<<1))) >> 8); \ else \ v = ((S).b * ((L).b<<1))>>8; \ tmp.b = MAXIMUM(MINIMUM(v,255),0); \ \ tr = (int)((tmp.r*(V*C2F((A).r))) + ((S).r*(1-(V)*C2F((A).r)))); \ tg = (int)((tmp.g*(V*C2F((A).g))) + ((S).g*(1-(V)*C2F((A).g)))); \ tb = (int)((tmp.b*(V*C2F((A).b))) + ((S).b*(1-(V)*C2F((A).b)))); \ (D).r = MAXIMUM(MINIMUM(tr,255),0); \ (D).g = MAXIMUM(MINIMUM(tg,255),0); \ (D).b = MAXIMUM(MINIMUM(tb,255),0); \ }while(0) #include "layer_channel.h" #undef L_CHANNEL_DO #undef L_CHANNEL_DO_V #undef LM_FUNC
25aaeb1999-04-23Mirar (Pontus Hagland) /* replace hsv by alpha channel (r=h, g=s, b=v) */ #define L_CHANNEL_DO(S,L,D,A) L_CHANNEL_DO_V(S,L,D,A,1.0)
7fd2cb2001-03-28Per Hedbor  #define LM_HSV_DO(HSV_X,S,L,D,A,V) \ do { \ double lh,lv,ls; \ double sh,sv,ss; \ rgb_group tmp; \ int tr, tg, tb; \ rgb_to_hsv((S),&sh,&ss,&sv); \ rgb_to_hsv((L),&lh,&ls,&lv); \ HSV_X; \ hsv_to_rgb(sh,ss,sv,&(tmp)); \ tr = (int)((tmp.r*(V*C2F((A).r))) + ((S).r*(1-(V)*C2F((A).r)))); \ tg = (int)((tmp.g*(V*C2F((A).g))) + ((S).g*(1-(V)*C2F((A).g)))); \ tb = (int)((tmp.b*(V*C2F((A).b))) + ((S).b*(1-(V)*C2F((A).b)))); \ (D).r = MAXIMUM(MINIMUM(tr,255),0); \ (D).g = MAXIMUM(MINIMUM(tg,255),0); \ (D).b = MAXIMUM(MINIMUM(tb,255),0); \
25aaeb1999-04-23Mirar (Pontus Hagland)  } while (0)
7fd2cb2001-03-28Per Hedbor  #define LM_FUNC lm_replace_hsv #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HSV_DO(sh=lh;ss=ls;sv=lv,S,L,D,A,V)
25aaeb1999-04-23Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC /* replace h, s or v (by alpha channel (r=h, g=s, b=v), only that one used) */ #define LM_FUNC lm_hue
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HSV_DO(sh=lh,S,L,D,A,V)
25aaeb1999-04-23Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC #define LM_FUNC lm_saturation
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HSV_DO(ss=ls,S,L,D,A,V)
25aaeb1999-04-23Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC #define LM_FUNC lm_value
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HSV_DO(sv=lv,S,L,D,A,V)
25aaeb1999-04-23Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC
a0c6c32001-03-17Mirar (Pontus Hagland) #define LM_FUNC lm_value_mul
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HSV_DO(sv*=lv,S,L,D,A,V)
a0c6c32001-03-17Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC
25aaeb1999-04-23Mirar (Pontus Hagland) /* h, s */ #define LM_FUNC lm_color
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HSV_DO(sh=lh;ss=ls,S,L,D,A,V)
55e2dd1999-04-23Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC /* lighten: max v */ #define LM_FUNC lm_lighten
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HSV_DO(sv=MAXIMUM(sv,lv),S,L,D,A,V)
55e2dd1999-04-23Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC
25aaeb1999-04-23Mirar (Pontus Hagland) 
7bdf522001-03-26Mirar (Pontus Hagland) /* darken: min v */ #define LM_FUNC lm_darken
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HSV_DO(sv=MINIMUM(sv,lv),S,L,D,A,V)
7bdf522001-03-26Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC
9974301999-07-03Mirar (Pontus Hagland) /* saturate: max s */ #define LM_FUNC lm_saturate
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HSV_DO(ss=MAXIMUM(ss,ls),S,L,D,A,V)
9974301999-07-03Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC /* desaturate: min s */ #define LM_FUNC lm_desaturate
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HSV_DO(ss=MINIMUM(ss,ls),S,L,D,A,V)
9974301999-07-03Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC
7fd2cb2001-03-28Per Hedbor #undef LM_HSV_DO
7bdf522001-03-26Mirar (Pontus Hagland) /******************************************************************/
7fd2cb2001-03-28Per Hedbor #define LM_HLS_DO(HLS_X,S,L,D,A,V) \ do { \ double lh,ll,ls; \ double sh,sl,ss; \ rgb_group tmp; \ int tr, tg, tb; \ rgb_to_hls((S),&sh,&sl,&ss); \ rgb_to_hls((L),&lh,&ll,&ls); \ HLS_X; \ hls_to_rgb(sh,sl,ss,&(tmp)); \ tr = (int)((tmp.r*(V*C2F((A).r))) + ((S).r*(1-(V)*C2F((A).r)))); \ tg = (int)((tmp.g*(V*C2F((A).g))) + ((S).g*(1-(V)*C2F((A).g)))); \ tb = (int)((tmp.b*(V*C2F((A).b))) + ((S).b*(1-(V)*C2F((A).b)))); \ (D).r = MAXIMUM(MINIMUM(tr,255),0); \ (D).g = MAXIMUM(MINIMUM(tg,255),0); \ (D).b = MAXIMUM(MINIMUM(tb,255),0); \
7bdf522001-03-26Mirar (Pontus Hagland)  } while (0)
7fd2cb2001-03-28Per Hedbor  #define LM_FUNC lm_hls_replace #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HLS_DO(sh=lh;sl=ll;ss=ls,S,L,D,A,V)
7bdf522001-03-26Mirar (Pontus Hagland) #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
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HLS_DO(sh=lh,S,L,D,A,V)
7bdf522001-03-26Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC #define LM_FUNC lm_hls_saturation
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HLS_DO(ss=ls,S,L,D,A,V)
7bdf522001-03-26Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC #define LM_FUNC lm_hls_lightness
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HLS_DO(sl=ll,S,L,D,A,V)
7bdf522001-03-26Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC #define LM_FUNC lm_hls_lightness_mul
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HLS_DO(sl*=ll,S,L,D,A,V)
7bdf522001-03-26Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC /* h, s */ #define LM_FUNC lm_hls_color
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HLS_DO(sh=lh;ss=ls,S,L,D,A,V)
7bdf522001-03-26Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC /* lighten: max v */ #define LM_FUNC lm_hls_lighten
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HLS_DO(sl=MAXIMUM(sl,ll),S,L,D,A,V)
7bdf522001-03-26Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC /* darken: min v */ #define LM_FUNC lm_hls_darken
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HLS_DO(sl=MINIMUM(sl,ll),S,L,D,A,V)
7bdf522001-03-26Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC /* saturate: max s */ #define LM_FUNC lm_hls_saturate
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HLS_DO(sl=MAXIMUM(ss,ls),S,L,D,A,V)
7bdf522001-03-26Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC /* desaturate: min s */ #define LM_FUNC lm_hls_desaturate
7fd2cb2001-03-28Per Hedbor #define L_CHANNEL_DO_V(S,L,D,A,V) LM_HLS_DO(sl=MINIMUM(ss,ls),S,L,D,A,V)
7bdf522001-03-26Mirar (Pontus Hagland) #include "layer_channel.h" #undef L_CHANNEL_DO_V #undef LM_FUNC
7fd2cb2001-03-28Per Hedbor #undef LM_HLS_DO
7bdf522001-03-26Mirar (Pontus Hagland)  /******************************************************************/
d883131999-06-28Per Hedbor /* screen: 255 - ((255-A)*(255-B)/255) */
a0c6c32001-03-17Mirar (Pontus Hagland) #define L_COPY_ALPHA
d883131999-06-28Per Hedbor #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) #define INT_MULT(a,b) (((a) * (b) + 0x80)>>8) #define INT_BLEND(a,b,alpha) (INT_MULT((a)-(b), alpha) + (b)) #define L_OPER(A,B) INT_BLEND((255-INT_MULT((255-A),(255-B))),INT_MULT(A,B),A) /* screen mult source */ #include "layer_oper.h" #undef LM_FUNC #undef L_TRUNC #undef L_OPER
a0c6c32001-03-17Mirar (Pontus Hagland) #undef L_COPY_ALPHA
25aaeb1999-04-23Mirar (Pontus Hagland) #undef L_CHANNEL_DO /* special modes */
eae4da1999-04-19Mirar (Pontus Hagland) static void lm_dissolve(rgb_group *s,rgb_group *l,rgb_group *d, rgb_group *sa,rgb_group *la,rgb_group *da,
25aaeb1999-04-23Mirar (Pontus Hagland)  int len,double alpha)
eae4da1999-04-19Mirar (Pontus Hagland) { if (alpha==0.0) {
776acd1999-08-10Mirar (Pontus Hagland) #ifdef LAYERS_DUAL
25aaeb1999-04-23Mirar (Pontus Hagland)  MEMCPY(d,s,sizeof(rgb_group)*len); MEMCPY(da,sa,sizeof(rgb_group)*len);
776acd1999-08-10Mirar (Pontus Hagland) #endif
e01a022000-02-08Per Hedbor  return;
eae4da1999-04-19Mirar (Pontus Hagland)  } else if (alpha==1.0) { if (!la) /* no layer alpha => full opaque */
f9c8eb1999-07-02Mirar (Pontus Hagland)  { MEMCPY(d,l,sizeof(rgb_group)*len); smear_color(da,white,len); }
eae4da1999-04-19Mirar (Pontus Hagland)  else while (len--) {
e01a022000-02-08Per Hedbor  if ((my_rand()%(255*255)) < (unsigned)(la->r*87 + la->g*127 + la->b*41))
eae4da1999-04-19Mirar (Pontus Hagland)  *d=*l,*da=white;
e01a022000-02-08Per Hedbor  else
eae4da1999-04-19Mirar (Pontus Hagland)  *d=*s,*da=*sa; l++; s++; la++; sa++; da++; d++; } } else {
e58a6f2000-08-06Henrik Grubbström (Grubba)  int v = DOUBLE_TO_INT(COLORMAX*alpha);
eae4da1999-04-19Mirar (Pontus Hagland)  if (!la) /* no layer alpha => full opaque */ while (len--) {
e01a022000-02-08Per Hedbor  if ((my_rand()&255) < (unsigned)v)
eae4da1999-04-19Mirar (Pontus Hagland)  *d=*l,*da=white;
e01a022000-02-08Per Hedbor  else
eae4da1999-04-19Mirar (Pontus Hagland)  *d=*s,*da=*sa; l++; s++; sa++; da++; d++; } else { while (len--) {
e01a022000-02-08Per Hedbor  if ((my_rand()%(255*255)) <
ae9bb11999-06-18Mirar (Pontus Hagland)  (unsigned)((la->r*87 + la->g*127 + la->b*41)>>8)*v)
eae4da1999-04-19Mirar (Pontus Hagland)  *d=*l,*da=white;
e01a022000-02-08Per Hedbor  else
eae4da1999-04-19Mirar (Pontus Hagland)  *d=*s,*da=*sa; l++; s++; la++; sa++; da++; d++; } } } }
6b7e331999-04-19Mirar (Pontus Hagland) 
55e2dd1999-04-23Mirar (Pontus Hagland) 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 */ {
776acd1999-08-10Mirar (Pontus Hagland) #ifdef LAYERS_DUAL
55e2dd1999-04-23Mirar (Pontus Hagland)  MEMCPY(d,s,sizeof(rgb_group)*len); MEMCPY(da,sa,sizeof(rgb_group)*len);
776acd1999-08-10Mirar (Pontus Hagland) #endif
e01a022000-02-08Per Hedbor  return;
55e2dd1999-04-23Mirar (Pontus Hagland)  } else if (alpha==1.0) while (len--) { if (sa->r==COLORMAX && sa->g==COLORMAX && sa->b==COLORMAX) { *d=*s; *da=*sa; } else if (sa->r==0 && sa->g==0 && sa->b==0) { *d=*l; if (la) *da=*la; else *da=white; } else if (la) { ALPHA_ADD(l,s,d,la,sa,da,r); ALPHA_ADD(l,s,d,la,sa,da,g); ALPHA_ADD(l,s,d,la,sa,da,b); }
e01a022000-02-08Per Hedbor  else
55e2dd1999-04-23Mirar (Pontus Hagland)  { ALPHA_ADD(l,s,d,(&white),sa,da,r); ALPHA_ADD(l,s,d,(&white),sa,da,g); ALPHA_ADD(l,s,d,(&white),sa,da,b); } l++; s++; sa++; d++; da++;
e01a022000-02-08Per Hedbor  if (la) la++;
55e2dd1999-04-23Mirar (Pontus Hagland)  } else while (len--) { if (sa->r==COLORMAX && sa->g==COLORMAX && sa->b==COLORMAX) { *d=*s; *da=*sa; } else if (sa->r==0 && sa->g==0 && sa->b==0) { *d=*l; if (la) *da=*la; else *da=white; } else if (la) { ALPHA_ADD_V(l,s,d,la,sa,da,alpha,r); ALPHA_ADD_V(l,s,d,la,sa,da,alpha,g); ALPHA_ADD_V(l,s,d,la,sa,da,alpha,b); }
e01a022000-02-08Per Hedbor  else
55e2dd1999-04-23Mirar (Pontus Hagland)  { ALPHA_ADD_V(l,s,d,(&white),sa,da,alpha,r); ALPHA_ADD_V(l,s,d,(&white),sa,da,alpha,g); ALPHA_ADD_V(l,s,d,(&white),sa,da,alpha,b); } l++; s++; sa++; d++; da++;
e01a022000-02-08Per Hedbor  if (la) la++;
55e2dd1999-04-23Mirar (Pontus Hagland)  } } 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 */
776acd1999-08-10Mirar (Pontus Hagland) #ifdef LAYERS_DUAL
55e2dd1999-04-23Mirar (Pontus Hagland)  MEMCPY(d,s,sizeof(rgb_group)*len);
776acd1999-08-10Mirar (Pontus Hagland) #endif
55e2dd1999-04-23Mirar (Pontus Hagland)  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)); la++; sa++; da++; } else if (!la) /* full opaque */ { rgb_group a;
41162a2000-08-06Henrik Grubbström (Grubba)  a.r=a.g=a.b=COLORMAX-DOUBLE_TO_COLORTYPE(alpha*COLORMAX);
55e2dd1999-04-23Mirar (Pontus Hagland)  smear_color(da,a,len); } else while (len--) {
e58a6f2000-08-06Henrik Grubbström (Grubba)  da->r=CCUT(sa->r*DOUBLE_TO_INT(COLORMAX-alpha*la->r)); da->g=CCUT(sa->g*DOUBLE_TO_INT(COLORMAX-alpha*la->g)); da->b=CCUT(sa->b*DOUBLE_TO_INT(COLORMAX-alpha*la->b));
55e2dd1999-04-23Mirar (Pontus Hagland)  la++; sa++; da++; } }
776acd1999-08-10Mirar (Pontus Hagland) 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)
e01a022000-02-08Per Hedbor 
776acd1999-08-10Mirar (Pontus Hagland) { /* special optimized */
e01a022000-02-08Per Hedbor  if (!la)
776acd1999-08-10Mirar (Pontus Hagland)  {
e01a022000-02-08Per Hedbor #ifdef LAYERS_DUAL
776acd1999-08-10Mirar (Pontus Hagland)  MEMCPY(d,s,len*sizeof(rgb_group)); MEMCPY(da,sa,len*sizeof(rgb_group)); #endif return; } if (ly->alpha_value==1.0) if (!l)
726c7a1999-08-12Mirar (Pontus Hagland)  if (ly->fill.r!=0 ||
776acd1999-08-10Mirar (Pontus Hagland)  ly->fill.g!=0 || ly->fill.b!=0) { while (len--) {
726c7a1999-08-12Mirar (Pontus Hagland)  d->r=MINIMUM(s->r+la->r,COLORMAX); d->g=MINIMUM(s->g+la->g,COLORMAX); d->b=MINIMUM(s->b+la->b,COLORMAX);
776acd1999-08-10Mirar (Pontus Hagland)  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);
e01a022000-02-08Per Hedbor  da++; sa++; la++;
776acd1999-08-10Mirar (Pontus Hagland)  } } else while (len--) { if ((s->r==COLORMAX && s->g==COLORMAX && s->b==COLORMAX)) { *d=*s; }
e01a022000-02-08Per Hedbor  else
776acd1999-08-10Mirar (Pontus Hagland)  { 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;
41162a2000-08-06Henrik Grubbström (Grubba)  da->r=MINIMUM(sa->r+DOUBLE_TO_COLORTYPE(alpha*la->r),COLORMAX); da->g=MINIMUM(sa->g+DOUBLE_TO_COLORTYPE(alpha*la->g),COLORMAX); da->b=MINIMUM(sa->b+DOUBLE_TO_COLORTYPE(alpha*la->b),COLORMAX);
776acd1999-08-10Mirar (Pontus Hagland)  } else {
41162a2000-08-06Henrik Grubbström (Grubba)  d->r=s->r+DOUBLE_TO_COLORTYPE(alpha*l->r); d->g=s->g+DOUBLE_TO_COLORTYPE(alpha*l->g); d->b=s->b+DOUBLE_TO_COLORTYPE(alpha*l->b);
776acd1999-08-10Mirar (Pontus Hagland) 
41162a2000-08-06Henrik Grubbström (Grubba)  da->r=MINIMUM(sa->r+DOUBLE_TO_COLORTYPE(alpha*l->r),COLORMAX); da->g=MINIMUM(sa->g+DOUBLE_TO_COLORTYPE(alpha*l->g),COLORMAX); da->b=MINIMUM(sa->b+DOUBLE_TO_COLORTYPE(alpha*l->b),COLORMAX);
776acd1999-08-10Mirar (Pontus Hagland)  } da++; sa++; la++; s++; d++; } } }
7e8e2d1999-04-17Mirar (Pontus Hagland) /*** the add-layer function ***************************/
6b8a751999-06-13Mirar (Pontus Hagland) static INLINE void img_lay_first_line(struct layer *l,
7e8e2d1999-04-17Mirar (Pontus Hagland)  int xoffs,int xsize,
1856b31999-04-19Mirar (Pontus Hagland)  int y, /* in _this_ layer */
7e8e2d1999-04-17Mirar (Pontus Hagland)  rgb_group *d,rgb_group *da) { if (!l->tiled) { rgb_group *s,*sa; int len;
1856b31999-04-19Mirar (Pontus Hagland)  if (y<0 || y>=l->ysize ||
7e8e2d1999-04-17Mirar (Pontus Hagland)  l->xoffs+l->xsize<xoffs || l->xoffs>xoffs+xsize) /* outside */ { smear_color(d,l->fill,xsize); smear_color(da,l->fill_alpha,xsize); return; } if (l->img) s=l->img->img+y*l->xsize; else s=NULL; if (l->alp) sa=l->alp->img+y*l->xsize; else sa=NULL; len=l->xsize;
e01a022000-02-08Per Hedbor  if (l->xoffs>xoffs)
7e8e2d1999-04-17Mirar (Pontus Hagland)  { /* fill to the left */ smear_color(d,l->fill,l->xoffs-xoffs); smear_color(da,l->fill_alpha,l->xoffs-xoffs); xsize-=l->xoffs-xoffs; d+=l->xoffs-xoffs; da+=l->xoffs-xoffs; } else { if (s) s+=xoffs-l->xoffs; if (sa) sa+=xoffs-l->xoffs; len-=xoffs-l->xoffs; } if (len<xsize) /* copy bit, fill right */ {
e01a022000-02-08Per Hedbor  if (s) MEMCPY(d,s,len*sizeof(rgb_group));
7e8e2d1999-04-17Mirar (Pontus Hagland)  else smear_color(d,l->fill,len);
e01a022000-02-08Per Hedbor  if (sa) MEMCPY(da,sa,len*sizeof(rgb_group));
7e8e2d1999-04-17Mirar (Pontus Hagland)  else smear_color(da,white,len); smear_color(d+len,l->fill,xsize-len); smear_color(da+len,l->fill_alpha,xsize-len); } else /* copy rest */ {
e01a022000-02-08Per Hedbor  if (s) MEMCPY(d,s,xsize*sizeof(rgb_group));
7e8e2d1999-04-17Mirar (Pontus Hagland)  else smear_color(d,l->fill,xsize);
e01a022000-02-08Per Hedbor  if (sa) MEMCPY(da,sa,xsize*sizeof(rgb_group));
7e8e2d1999-04-17Mirar (Pontus Hagland)  else smear_color(da,white,xsize); } return; } else { rgb_group *s,*sa; y%=l->ysize; if (y<0) y+=l->ysize;
e01a022000-02-08Per Hedbor  if (l->img) s=l->img->img+y*l->xsize;
7e8e2d1999-04-17Mirar (Pontus Hagland)  else smear_color(d,l->fill,xsize),s=NULL;
e01a022000-02-08Per Hedbor  if (l->alp) sa=l->alp->img+y*l->xsize;
7e8e2d1999-04-17Mirar (Pontus Hagland)  else smear_color(da,white,xsize),sa=NULL; xoffs-=l->xoffs; /* position in source */ xoffs%=l->xsize; if (xoffs<0) xoffs+=l->xsize; if (xoffs) { int len=l->xsize-xoffs; if (len>l->xsize) len=l->xsize; if (s) MEMCPY(d,s+xoffs,len*sizeof(rgb_group)); if (sa) MEMCPY(da,sa+xoffs,len*sizeof(rgb_group)); da+=len; d+=len; xsize-=len; } while (xsize>l->xsize) { if (s) MEMCPY(d,s,l->xsize*sizeof(rgb_group)); if (sa) MEMCPY(d,sa,l->xsize*sizeof(rgb_group)); da+=l->xsize; d+=l->xsize; xsize-=l->xsize; } if (s) MEMCPY(d,s,xsize*sizeof(rgb_group)); if (sa) MEMCPY(d,sa,xsize*sizeof(rgb_group)); } } 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) {
2180562000-12-27Mirar (Pontus Hagland)  if (len<0) Pike_error("internal error: stroke len < 0\n");
4317241999-08-16Mirar (Pontus Hagland)  if (ly->row_func==(lm_row_func*)lm_spec_burn_alpha)
776acd1999-08-10Mirar (Pontus Hagland)  { lm_spec_burn_alpha(ly,l,la,s,sa,d,da,len); return; }
e01a022000-02-08Per Hedbor  if (l)
7e8e2d1999-04-17Mirar (Pontus Hagland)  { (ly->row_func)(s,l,d,sa,la,da,len,ly->alpha_value); return; }
97d2601999-08-09Mirar (Pontus Hagland)  if (!la && ly->really_optimize_alpha)
7e8e2d1999-04-17Mirar (Pontus Hagland)  {
97d2601999-08-09Mirar (Pontus Hagland) /* fprintf(stderr,"fast skip ly->yoffs=%d\n",ly->yoffs); */
e01a022000-02-08Per Hedbor #ifdef LAYERS_DUAL
1856b31999-04-19Mirar (Pontus Hagland)  MEMCPY(d,s,len*sizeof(rgb_group)); MEMCPY(da,sa,len*sizeof(rgb_group));
776acd1999-08-10Mirar (Pontus Hagland) #endif
1856b31999-04-19Mirar (Pontus Hagland)  return;
7e8e2d1999-04-17Mirar (Pontus Hagland)  }
e01a022000-02-08Per Hedbor  if (!la && ly->fill_alpha.r==COLORMAX && ly->fill_alpha.g==COLORMAX &&
1856b31999-04-19Mirar (Pontus Hagland)  ly->fill_alpha.b==COLORMAX)
7e8e2d1999-04-17Mirar (Pontus Hagland)  { while (len>SNUMPIXS) {
1856b31999-04-19Mirar (Pontus Hagland)  (ly->row_func)(s,l?l:ly->sfill,d,sa,NULL,da, SNUMPIXS,ly->alpha_value); s+=SNUMPIXS; d+=SNUMPIXS; sa+=SNUMPIXS;da+=SNUMPIXS;
e01a022000-02-08Per Hedbor  if (l) l+=SNUMPIXS;
1856b31999-04-19Mirar (Pontus Hagland)  len-=SNUMPIXS;
7e8e2d1999-04-17Mirar (Pontus Hagland)  }
1856b31999-04-19Mirar (Pontus Hagland)  if (len) (ly->row_func)(s,l?l:ly->sfill,d,sa,NULL,da,len,ly->alpha_value);
7e8e2d1999-04-17Mirar (Pontus Hagland)  } else {
776acd1999-08-10Mirar (Pontus Hagland) /* fprintf(stderr,"ly=%p len=%d\n",ly,len); */
7e8e2d1999-04-17Mirar (Pontus Hagland)  while (len>SNUMPIXS) {
1856b31999-04-19Mirar (Pontus Hagland)  (ly->row_func)(s,l?l:ly->sfill,d,sa,la?la:ly->sfill_alpha,da,
7e8e2d1999-04-17Mirar (Pontus Hagland)  SNUMPIXS,ly->alpha_value);
1856b31999-04-19Mirar (Pontus Hagland)  s+=SNUMPIXS; d+=SNUMPIXS; sa+=SNUMPIXS; da+=SNUMPIXS;
e01a022000-02-08Per Hedbor  if (l) l+=SNUMPIXS; if (la) la+=SNUMPIXS;
1856b31999-04-19Mirar (Pontus Hagland)  len-=SNUMPIXS;
7e8e2d1999-04-17Mirar (Pontus Hagland)  }
1856b31999-04-19Mirar (Pontus Hagland)  if (len) (ly->row_func)(s,l?l:ly->sfill,d,sa,la?la:ly->sfill_alpha, da,len,ly->alpha_value);
7e8e2d1999-04-17Mirar (Pontus Hagland)  } } static INLINE void img_lay_line(struct layer *ly, rgb_group *s,rgb_group *sa, int xoffs,int xsize,
1856b31999-04-19Mirar (Pontus Hagland)  int y, /* y in ly layer */
7e8e2d1999-04-17Mirar (Pontus Hagland)  rgb_group *d,rgb_group *da) {
6442b92001-06-03Mirar (Pontus Hagland) /* fprintf(stderr,"tiled:%d xoffs:%d xsize:%d y:%d\n", */ /* ly->tiled,xoffs,xsize,y); */
7e8e2d1999-04-17Mirar (Pontus Hagland)  if (!ly->tiled) { int len; rgb_group *l,*la;
1856b31999-04-19Mirar (Pontus Hagland)  if (y<0 || y>=ly->ysize ||
7e8e2d1999-04-17Mirar (Pontus Hagland)  ly->xoffs+ly->xsize<xoffs || ly->xoffs>xoffs+xsize) /* outside */ {
1856b31999-04-19Mirar (Pontus Hagland)  img_lay_stroke(ly,NULL,NULL,s,sa,d,da,xsize);
7e8e2d1999-04-17Mirar (Pontus Hagland)  return; } if (ly->img) l=ly->img->img+y*ly->xsize; else l=NULL; if (ly->alp) la=ly->alp->img+y*ly->xsize; else la=NULL; len=ly->xsize;
e01a022000-02-08Per Hedbor  if (ly->xoffs>xoffs)
7e8e2d1999-04-17Mirar (Pontus Hagland)  { /* fill to the left */
1856b31999-04-19Mirar (Pontus Hagland)  img_lay_stroke(ly,NULL,NULL,s,sa,d,da,ly->xoffs-xoffs);
7e8e2d1999-04-17Mirar (Pontus Hagland)  xsize-=ly->xoffs-xoffs; d+=ly->xoffs-xoffs; da+=ly->xoffs-xoffs; s+=ly->xoffs-xoffs; sa+=ly->xoffs-xoffs; } else { if (l) l+=xoffs-ly->xoffs; if (la) la+=xoffs-ly->xoffs; len-=xoffs-ly->xoffs; } if (len<xsize) /* copy stroke, fill right */ {
a33cdf2000-02-22Per Hedbor  img_lay_stroke(ly,l,la,s,sa,d,da,len);
7e8e2d1999-04-17Mirar (Pontus Hagland) 
1856b31999-04-19Mirar (Pontus Hagland)  img_lay_stroke(ly,NULL,NULL,s+len,sa+len,d+len,da+len,xsize-len);
7e8e2d1999-04-17Mirar (Pontus Hagland)  } else /* copy rest */ {
1856b31999-04-19Mirar (Pontus Hagland)  img_lay_stroke(ly,l,la,s,sa,d,da,xsize);
7e8e2d1999-04-17Mirar (Pontus Hagland)  } return; } else { rgb_group *l,*la; y%=ly->ysize; if (y<0) y+=ly->ysize;
1856b31999-04-19Mirar (Pontus Hagland)  if (ly->img) l=ly->img->img+y*ly->xsize; else l=NULL; if (ly->alp) la=ly->alp->img+y*ly->xsize; else la=NULL;
7e8e2d1999-04-17Mirar (Pontus Hagland)  xoffs-=ly->xoffs; /* position in source */
1856b31999-04-19Mirar (Pontus Hagland)  if ((xoffs=xoffs%ly->xsize))
7e8e2d1999-04-17Mirar (Pontus Hagland)  {
1856b31999-04-19Mirar (Pontus Hagland)  int len; if (xoffs<0) xoffs+=ly->xsize; len=ly->xsize-xoffs;
6442b92001-06-03Mirar (Pontus Hagland)  if (len>xsize) len=xsize; /* fprintf(stderr,"a xoffs=%d len=%d xsize=%d ly->xsize:%d\n",xoffs,len,xsize,ly->xsize); */
1856b31999-04-19Mirar (Pontus Hagland)  img_lay_stroke(ly,l?l+xoffs:NULL,
7e8e2d1999-04-17Mirar (Pontus Hagland)  la?la+(xoffs%ly->xsize):NULL, s,sa,d,da,len); da+=len; d+=len; sa+=len; s+=len; xsize-=len; } while (xsize>ly->xsize) {
6442b92001-06-03Mirar (Pontus Hagland) /* fprintf(stderr,"b xsize=%d\n",xsize); */
1856b31999-04-19Mirar (Pontus Hagland)  img_lay_stroke(ly,l,la,s,sa,d,da,ly->xsize);
7e8e2d1999-04-17Mirar (Pontus Hagland)  da+=ly->xsize; d+=ly->xsize; sa+=ly->xsize; s+=ly->xsize; xsize-=ly->xsize; } if (xsize)
6442b92001-06-03Mirar (Pontus Hagland)  { /* fprintf(stderr,"c xsize=%d\n",xsize); */
1856b31999-04-19Mirar (Pontus Hagland)  img_lay_stroke(ly,l,la,s,sa,d,da,xsize);
6442b92001-06-03Mirar (Pontus Hagland)  }
7e8e2d1999-04-17Mirar (Pontus Hagland)  } } void img_lay(struct layer **layer, int layers, struct layer *dest) {
776acd1999-08-10Mirar (Pontus Hagland) #ifdef LAYERS_DUAL rgb_group *line1,*aline1; rgb_group *line2,*aline2; #endif
7e8e2d1999-04-17Mirar (Pontus Hagland)  rgb_group *d,*da; int width=dest->xsize; int y,z; int xoffs=dest->xoffs,xsize=dest->xsize;
776acd1999-08-10Mirar (Pontus Hagland) #ifdef LAYERS_DUAL
7e8e2d1999-04-17Mirar (Pontus Hagland)  line1=malloc(sizeof(rgb_group)*width); aline1=malloc(sizeof(rgb_group)*width);
776acd1999-08-10Mirar (Pontus Hagland)  line2=malloc(sizeof(rgb_group)*width);
7e8e2d1999-04-17Mirar (Pontus Hagland)  aline2=malloc(sizeof(rgb_group)*width);
776acd1999-08-10Mirar (Pontus Hagland)  if (!line1 || !aline1 !line2 || !aline2)
7e8e2d1999-04-17Mirar (Pontus Hagland)  { if (line1) free(line1); if (aline1) free(aline1);
776acd1999-08-10Mirar (Pontus Hagland)  if (line2) free(line2);
7e8e2d1999-04-17Mirar (Pontus Hagland)  if (aline2) free(aline2); resource_error(NULL,0,0,"memory",sizeof(rgb_group)*4*width, "Out of memory.\n"); }
776acd1999-08-10Mirar (Pontus Hagland) #endif
7e8e2d1999-04-17Mirar (Pontus Hagland)  da=dest->alp->img; d=dest->img->img; /* loop over lines */ for (y=0; y<dest->ysize; y++) {
b365571999-06-30Mirar (Pontus Hagland)  if (layers>1 || layer[0]->row_func!=lm_normal || layer[0]->tiled)
7e8e2d1999-04-17Mirar (Pontus Hagland)  { /* add the bottom layer first */
b365571999-06-30Mirar (Pontus Hagland)  if (layer[0]->row_func==lm_normal && !layer[0]->tiled) /* cheat */
1856b31999-04-19Mirar (Pontus Hagland)  { img_lay_first_line(layer[0],xoffs,xsize, y+dest->yoffs-layer[0]->yoffs,
776acd1999-08-10Mirar (Pontus Hagland) #ifdef LAYERS_DUAL line1,aline1 #else d,da #endif ),z=1;
1856b31999-04-19Mirar (Pontus Hagland)  z=1; }
7e8e2d1999-04-17Mirar (Pontus Hagland)  else {
776acd1999-08-10Mirar (Pontus Hagland) #ifdef LAYERS_DUAL
7e8e2d1999-04-17Mirar (Pontus Hagland)  smear_color(line1,black,xsize); smear_color(aline1,black,xsize);
776acd1999-08-10Mirar (Pontus Hagland) #else smear_color(d,black,xsize); smear_color(da,black,xsize); #endif
7e8e2d1999-04-17Mirar (Pontus Hagland)  z=0; } /* loop over the rest of the layers, except the last */
1856b31999-04-19Mirar (Pontus Hagland)  for (; z<layers-1; z++)
97d2601999-08-09Mirar (Pontus Hagland)  if (!layer[z]->really_optimize_alpha ||
e01a022000-02-08Per Hedbor  (layer[z]->yoffs<=y+dest->yoffs &&
97d2601999-08-09Mirar (Pontus Hagland)  y+dest->yoffs<layer[z]->yoffs+layer[z]->ysize)) { /* 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); */
776acd1999-08-10Mirar (Pontus Hagland)  img_lay_line(layer[z], #ifdef LAYERS_DUAL line1,aline1, #else d,da, #endif
97d2601999-08-09Mirar (Pontus Hagland)  xoffs,xsize, y+dest->yoffs-layer[z]->yoffs,
776acd1999-08-10Mirar (Pontus Hagland) #ifdef LAYERS_DUAL line2,aline2 #else d,da #endif ); #ifdef LAYERS_DUAL
97d2601999-08-09Mirar (Pontus Hagland)  /* swap buffers */ tmp=line1; line1=line2; line2=tmp; tmp=aline1; aline1=aline2; aline2=tmp;
776acd1999-08-10Mirar (Pontus Hagland) #endif
97d2601999-08-09Mirar (Pontus Hagland)  } /* else */ /* fprintf(stderr,"skip %d\n",z); */
7e8e2d1999-04-17Mirar (Pontus Hagland)  /* make the last layer on the destionation */
776acd1999-08-10Mirar (Pontus Hagland)  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);
7e8e2d1999-04-17Mirar (Pontus Hagland)  }
e01a022000-02-08Per Hedbor  else
7e8e2d1999-04-17Mirar (Pontus Hagland)  { /* make the layer to destination*/
1856b31999-04-19Mirar (Pontus Hagland)  img_lay_first_line(layer[0],xoffs,xsize, y+dest->yoffs-layer[0]->yoffs,d,da);
7e8e2d1999-04-17Mirar (Pontus Hagland)  } d+=dest->xsize; da+=dest->xsize; }
776acd1999-08-10Mirar (Pontus Hagland) #ifdef LAYERS_DUAL
7e8e2d1999-04-17Mirar (Pontus Hagland)  free(line1); free(aline1); free(line2); free(aline2);
776acd1999-08-10Mirar (Pontus Hagland) #endif
7e8e2d1999-04-17Mirar (Pontus Hagland) } /* **! module Image
2849652001-07-19Martin Nilsson **! method Image.Layer lay(array(Image.Layer|mapping) layers) **! method Image.Layer lay(array(Image.Layer|mapping) layers,int xoffset,int yoffset,int xsize,int ysize)
e01a022000-02-08Per Hedbor **! Combine layers.
7e8e2d1999-04-17Mirar (Pontus Hagland) **! returns a new layer object. **! **! see also: Image.Layer */ void image_lay(INT32 args) { int layers,i; struct layer **l; struct object *o; struct layer *dest; struct array *a;
65a5492000-08-10Per Hedbor  INT_TYPE xoffset=0,yoffset=0,xsize=0,ysize=0;
7e8e2d1999-04-17Mirar (Pontus Hagland)  if (!args) SIMPLE_TOO_FEW_ARGS_ERROR("Image.lay",1);
e01a022000-02-08Per Hedbor 
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (Pike_sp[-args].type!=T_ARRAY)
7e8e2d1999-04-17Mirar (Pontus Hagland)  SIMPLE_BAD_ARG_ERROR("Image.lay",1, "array(Image.Layer|mapping)"); if (args>1) { get_all_args("Image.lay",args-1,"%i%i%i%i", &xoffset,&yoffset,&xsize,&ysize); if (xsize<1) SIMPLE_BAD_ARG_ERROR("Image.lay",4,"int(1..)"); if (ysize<1) SIMPLE_BAD_ARG_ERROR("Image.lay",5,"int(1..)"); }
e01a022000-02-08Per Hedbor 
5923b12000-07-06Fredrik Hübinette (Hubbe)  layers=(a=Pike_sp[-args].u.array)->size;
7e8e2d1999-04-17Mirar (Pontus Hagland)  if (!layers) /* dummy return empty layer */ { pop_n_elems(args); push_object(clone_object(image_layer_program,0)); return; }
e01a022000-02-08Per Hedbor 
7e8e2d1999-04-17Mirar (Pontus Hagland)  l=(struct layer**)xalloc(sizeof(struct layer)*layers); for (i=0; i<layers; i++) { if (a->item[i].type==T_OBJECT) { if (!(l[i]=(struct layer*)get_storage(a->item[i].u.object, image_layer_program))) SIMPLE_BAD_ARG_ERROR("Image.lay",1, "array(Image.Layer|mapping)"); } else if (a->item[i].type==T_MAPPING) { push_svalue(a->item+i); push_object(o=clone_object(image_layer_program,1)); args++; l[i]=(struct layer*)get_storage(o,image_layer_program); } else SIMPLE_BAD_ARG_ERROR("Image.lay",1, "array(Image.Layer|mapping)"); } if (xsize==0) /* figure offset and size */ { xoffset=l[0]->xoffs; yoffset=l[0]->yoffs; xsize=l[0]->xsize; ysize=l[0]->ysize;
b365571999-06-30Mirar (Pontus Hagland)  if (l[0]->tiled) /* set size from the first non-tiled */
7e8e2d1999-04-17Mirar (Pontus Hagland)  {
b365571999-06-30Mirar (Pontus Hagland)  for (i=1; i<layers; i++) if (!l[i]->tiled) { xoffset=l[i]->xoffs; yoffset=l[i]->yoffs; xsize=l[i]->xsize; ysize=l[i]->ysize; break; }
7e8e2d1999-04-17Mirar (Pontus Hagland)  }
b365571999-06-30Mirar (Pontus Hagland)  else i=1; for (; i<layers; i++) if (!l[i]->tiled) { int t;
e01a022000-02-08Per Hedbor  if (l[i]->xoffs<xoffset)
b365571999-06-30Mirar (Pontus Hagland)  t=xoffset-l[i]->xoffs,xoffset-=t,xsize+=t;
e01a022000-02-08Per Hedbor  if (l[i]->yoffs<yoffset)
b365571999-06-30Mirar (Pontus Hagland)  t=yoffset-l[i]->yoffs,yoffset-=t,ysize+=t; if (l[i]->xsize+l[i]->xoffs-xoffset>xsize) xsize=l[i]->xsize+l[i]->xoffs-xoffset; if (l[i]->ysize+l[i]->yoffs-yoffset>ysize) ysize=l[i]->ysize+l[i]->yoffs-yoffset; }
7e8e2d1999-04-17Mirar (Pontus Hagland)  } /* get destination layer */ push_int(xsize); push_int(ysize); push_object(o=clone_object(image_layer_program,2)); dest=(struct layer*)get_storage(o,image_layer_program); dest->xoffs=xoffset; dest->yoffs=yoffset; /* ok, do it! */ img_lay(l,layers,dest);
b77f951999-08-10Mirar (Pontus Hagland)  free(l);
e01a022000-02-08Per Hedbor 
5923b12000-07-06Fredrik Hübinette (Hubbe)  Pike_sp--;
7e8e2d1999-04-17Mirar (Pontus Hagland)  pop_n_elems(args); push_object(o); }
ae9bb11999-06-18Mirar (Pontus Hagland) /** image-object operations *************************/ static INLINE struct layer *push_new_layer() { push_object(clone_object(image_layer_program,0));
5923b12000-07-06Fredrik Hübinette (Hubbe)  return (struct layer*)get_storage(Pike_sp[-1].u.object,image_layer_program);
ae9bb11999-06-18Mirar (Pontus Hagland) } static INLINE struct layer *clone_this_layer() { struct layer *l; l=push_new_layer(); l->xsize=THIS->xsize; l->ysize=THIS->ysize; l->xoffs=THIS->xoffs; l->yoffs=THIS->yoffs; l->image=THIS->image; l->alpha=THIS->alpha; l->img=THIS->img; l->alp=THIS->alp; if (l->image) add_ref(l->image); if (l->alpha) add_ref(l->alpha); l->alpha_value=THIS->alpha_value; l->fill=THIS->fill; l->fill_alpha=THIS->fill_alpha; MEMCPY(l->sfill,THIS->sfill,sizeof(rgb_group)*SNUMPIXS); MEMCPY(l->sfill_alpha,THIS->sfill_alpha,sizeof(rgb_group)*SNUMPIXS); l->tiled=THIS->tiled; l->row_func=THIS->row_func; l->optimize_alpha=THIS->optimize_alpha;
97d2601999-08-09Mirar (Pontus Hagland)  l->really_optimize_alpha=THIS->really_optimize_alpha;
5305232001-04-10Mirar (Pontus Hagland)  if (THIS->misc) l->misc = copy_mapping( THIS->misc );
ae9bb11999-06-18Mirar (Pontus Hagland)  return l; }
7383191999-06-21Mirar (Pontus Hagland) /*
f9c8eb1999-07-02Mirar (Pontus Hagland) **! module Image **! class Layer
4317241999-08-16Mirar (Pontus Hagland)  **! method object clone() **! Creates a copy of the called object. **! returns the copy */ static void image_layer_clone(INT32 args) { pop_n_elems(args); clone_this_layer(); } /*
7383191999-06-21Mirar (Pontus Hagland) **! method object crop(int xoff,int yoff,int xsize,int ysize) **! Crops this layer at this offset and size. **! Offset is not relative the layer offset, so this **! can be used to crop a number of layers simuntaneously. **! **! The <ref>fill</ref> values are used if the layer is **! enlarged. **! returns a new layer object **! note: **! The new layer object may have the same image object, **! if there was no cropping to be done. */
ae9bb11999-06-18Mirar (Pontus Hagland) static void image_layer_crop(INT32 args) { struct layer *l;
65a5492000-08-10Per Hedbor  INT_TYPE x,y,xz,yz,xi,yi;
ae9bb11999-06-18Mirar (Pontus Hagland)  int zot=0;
36a00c2000-08-15Henrik Grubbström (Grubba)  struct image *img = NULL;
ae9bb11999-06-18Mirar (Pontus Hagland)  get_all_args("Image.Layer->crop",args,"%d%d%d%d",&x,&y,&xz,&yz); l=clone_this_layer(); if (x<=l->xoffs) x=l->xoffs; else zot++; if (y<=l->yoffs) y=l->yoffs; else zot++; if (l->xsize+l->xoffs<=x+xz) xz=l->xsize-(x-l->xoffs); else zot++; if (l->ysize+l->yoffs<=y+yz) yz=l->ysize-(y-l->yoffs); else zot++; xi=x-l->xoffs; yi=y-l->yoffs; l->xoffs=x; l->yoffs=y;
7383191999-06-21Mirar (Pontus Hagland)  if (zot && l->image)
ae9bb11999-06-18Mirar (Pontus Hagland)  { ref_push_object(l->image); push_constant_text("copy"); f_index(2); push_int(xi); push_int(yi); push_int(xz+xi-1); push_int(yz+yi-1);
7383191999-06-21Mirar (Pontus Hagland)  push_int(THIS->fill.r); push_int(THIS->fill.g); push_int(THIS->fill.b); f_call_function(8);
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (Pike_sp[-1].type!=T_OBJECT || !(img=(struct image*)get_storage(Pike_sp[-1].u.object,image_program)))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("No image returned from image->copy\n");
e01a022000-02-08Per Hedbor  if (img->xsize!=xz || img->ysize!=yz)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image returned from image->copy had "
ae9bb11999-06-18Mirar (Pontus Hagland)  "unexpected size (%d,%d, expected %d,%d)\n",
b875ff2001-03-04Mirar (Pontus Hagland)  img->xsize,img->ysize,(INT32)xz,(INT32)yz);
ae9bb11999-06-18Mirar (Pontus Hagland)  free_object(l->image);
5923b12000-07-06Fredrik Hübinette (Hubbe)  l->image=Pike_sp[-1].u.object; Pike_sp--; dmalloc_touch_svalue(Pike_sp);
ae9bb11999-06-18Mirar (Pontus Hagland)  l->img=img; }
7383191999-06-21Mirar (Pontus Hagland)  if (zot && l->alpha)
ae9bb11999-06-18Mirar (Pontus Hagland)  { ref_push_object(l->alpha); push_constant_text("copy"); f_index(2); push_int(xi); push_int(yi); push_int(xz+xi-1); push_int(yz+yi-1);
7383191999-06-21Mirar (Pontus Hagland)  push_int(THIS->fill_alpha.r); push_int(THIS->fill_alpha.g); push_int(THIS->fill_alpha.b); f_call_function(8);
5923b12000-07-06Fredrik Hübinette (Hubbe)  if (Pike_sp[-1].type!=T_OBJECT || !(img=(struct image*)get_storage(Pike_sp[-1].u.object,image_program)))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("No image returned from alpha->copy\n");
e01a022000-02-08Per Hedbor  if (img->xsize!=xz || img->ysize!=yz)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image returned from alpha->copy had "
ae9bb11999-06-18Mirar (Pontus Hagland)  "unexpected size (%d,%d, expected %d,%d)\n",
b875ff2001-03-04Mirar (Pontus Hagland)  img->xsize,img->ysize,(INT32)xz,(INT32)yz);
ae9bb11999-06-18Mirar (Pontus Hagland)  free_object(l->alpha);
5923b12000-07-06Fredrik Hübinette (Hubbe)  l->alpha=Pike_sp[-1].u.object; Pike_sp--; dmalloc_touch_svalue(Pike_sp);
ae9bb11999-06-18Mirar (Pontus Hagland)  l->alp=img; }
7383191999-06-21Mirar (Pontus Hagland)  l->xoffs=x; l->yoffs=y; l->xsize=xz; l->ysize=yz;
ae9bb11999-06-18Mirar (Pontus Hagland)  stack_pop_n_elems_keep_top(args); }
7383191999-06-21Mirar (Pontus Hagland) /* **! method object autocrop() **! method object autocrop(int(0..1) left,int(0..1) right,int(0..1) top,int(0..1) bottom) **! method array(int) find_autocrop() **! method array(int) find_autocrop(int(0..1) left,int(0..1) right,int(0..1) top,int(0..1) bottom) **! This crops (of finds) a suitable crop, non-destructive crop. **! The layer alpha channel is checked, and edges that is **! transparent is removed.
e01a022000-02-08Per Hedbor **! **! (What really happens is that the image and alpha channel is checked,
7383191999-06-21Mirar (Pontus Hagland) **! and edges equal the fill setup is cropped away.) **! **! <ref>find_autocrop</ref>() returns an array of xoff,yoff,xsize,ysize, **! which can be fed to <ref>crop</ref>(). **! **! note: **! A tiled image will not be cropped at all. **! **! <tt>left</tt>...<tt>bottom</tt> arguments can be used **! to tell what sides cropping are ok on. **!
f9c8eb1999-07-02Mirar (Pontus Hagland) **! see also: crop, Image.Image->autocrop
7383191999-06-21Mirar (Pontus Hagland) */ static void image_layer_find_autocrop(INT32 args) {
b875ff2001-03-04Mirar (Pontus Hagland)  INT32 x1=0,y1=0,x2=THIS->xsize-1,y2=THIS->ysize-1;
65a5492000-08-10Per Hedbor  INT_TYPE l=1,r=1,t=1,b=1;
7383191999-06-21Mirar (Pontus Hagland)  if (args>3) get_all_args("find_autocrop",args,"%d%d%d%d",&l,&r,&t,&b);
132f0d2000-08-13Henrik Grubbström (Grubba)  if (!THIS->tiled) {
7383191999-06-21Mirar (Pontus Hagland)  if (THIS->alpha) { img_find_autocrop(THIS->alp, &x1,&y1,&x2,&y2, 0,l,r,t,b,1,THIS->fill_alpha); if (THIS->image && (THIS->fill_alpha.r!=0 || THIS->fill_alpha.g!=0 || /* non-transparent fill */ THIS->fill_alpha.b!=0)) /* check image too */ {
b875ff2001-03-04Mirar (Pontus Hagland)  INT32 ix1,iy1,ix2,iy2;
7383191999-06-21Mirar (Pontus Hagland)  img_find_autocrop(THIS->img, &ix1,&iy1,&ix2,&iy2,
b875ff2001-03-04Mirar (Pontus Hagland)  0,(int)l,(int)r,(int)t,(int)b,1,THIS->fill);
7383191999-06-21Mirar (Pontus Hagland)  if (ix1<x1) x1=ix1; if (ix2>x2) x2=ix2; if (iy1<y1) y1=iy1; if (iy2>y2) y2=iy2; } } else if (THIS->image && /* image alpha is 'white'... */ (THIS->fill_alpha.r==255 || THIS->fill_alpha.g==255 || /* opaque fill */ THIS->fill_alpha.b==255)) /* we may be able to crop */ { img_find_autocrop(THIS->img, &x1,&y1,&x2,&y2,
b875ff2001-03-04Mirar (Pontus Hagland)  0,(int)l,(int)r,(int)t,(int)b,1,THIS->fill);
7383191999-06-21Mirar (Pontus Hagland)  }
132f0d2000-08-13Henrik Grubbström (Grubba)  }
7383191999-06-21Mirar (Pontus Hagland)  push_int(x1+THIS->xoffs); push_int(y1+THIS->yoffs); push_int(x2-x1+1); push_int(y2-y1+1); f_aggregate(4); } void image_layer_autocrop(INT32 args) { image_layer_find_autocrop(args);
5923b12000-07-06Fredrik Hübinette (Hubbe)  Pike_sp--; dmalloc_touch_svalue(Pike_sp); push_array_items(Pike_sp->u.array); /* frees */
7383191999-06-21Mirar (Pontus Hagland)  image_layer_crop(4); }
bf57c82000-09-10Per Hedbor static void image_layer__sprintf( INT32 args ) { int x; if (args != 2 ) SIMPLE_TOO_FEW_ARGS_ERROR("_sprintf",2); if (sp[-args].type!=T_INT) SIMPLE_BAD_ARG_ERROR("_sprintf",0,"integer"); if (sp[1-args].type!=T_MAPPING) SIMPLE_BAD_ARG_ERROR("_sprintf",1,"mapping"); x = sp[-2].u.integer; pop_n_elems( 2 ); switch( x ) { case 't': push_constant_text("Image.Layer"); return; case 'O': push_constant_text( "Image.Layer(%O i=%O a=%O)" ); image_layer_mode(0); if( THIS->image ) ref_push_object( THIS->image ); else push_int( 0 ); if( THIS->alpha ) ref_push_object( THIS->alpha ); else push_int( 0 ); f_sprintf( 4 ); return; default: push_int(0); return; } }
7e8e2d1999-04-17Mirar (Pontus Hagland) /******************************************************/ void init_image_layers(void) { int i;
9debfa1999-08-11Fredrik Hübinette (Hubbe) 
7e8e2d1999-04-17Mirar (Pontus Hagland)  for (i=0; i<LAYER_MODES; i++) layer_mode[i].ps=make_shared_string(layer_mode[i].name);
8db2c31999-05-23Mirar (Pontus Hagland)  /* layer object */
7e8e2d1999-04-17Mirar (Pontus Hagland)  ADD_STORAGE(struct layer); set_init_callback(init_layer); set_exit_callback(exit_layer);
e01a022000-02-08Per Hedbor 
7e8e2d1999-04-17Mirar (Pontus Hagland)  ADD_FUNCTION("create",image_layer_create,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tOr4(tFunc(tNone,tVoid),
7e8e2d1999-04-17Mirar (Pontus Hagland)  tFunc(tObj tOr(tObj,tVoid) tOr(tString,tVoid),tVoid), tFunc(tLayerMap,tVoid),
e01a022000-02-08Per Hedbor  tFunc(tInt tInt
7e8e2d1999-04-17Mirar (Pontus Hagland)  tOr(tColor,tVoid) tOr(tColor,tVoid),tVoid)),0);
bf57c82000-09-10Per Hedbor  ADD_FUNCTION("_sprintf",image_layer__sprintf, tFunc(tInt tMapping,tString),0);
7e8e2d1999-04-17Mirar (Pontus Hagland)  ADD_FUNCTION("cast",image_layer_cast, tFunc(tString,tMapping),0);
4317241999-08-16Mirar (Pontus Hagland)  ADD_FUNCTION("clone",image_layer_clone,
e76b4d1999-11-24Jonas Wallden  tFunc(tNone,tObj),0);
4317241999-08-16Mirar (Pontus Hagland) 
1856b31999-04-19Mirar (Pontus Hagland)  /* set */ ADD_FUNCTION("set_offset",image_layer_set_offset,tFunc(tInt tInt,tObj),0); ADD_FUNCTION("set_image",image_layer_set_image, tFunc(tOr(tObj,tVoid) tOr(tObj,tVoid),tObj),0); ADD_FUNCTION("set_fill",image_layer_set_fill, tFunc(tOr(tObj,tVoid) tOr(tObj,tVoid),tObj),0); ADD_FUNCTION("set_mode",image_layer_set_mode,tFunc(tStr,tObj),0);
d883131999-06-28Per Hedbor  ADD_FUNCTION("set_alpha_value",image_layer_set_alpha_value, tFunc(tFloat,tObj),0);
1856b31999-04-19Mirar (Pontus Hagland)  ADD_FUNCTION("set_tiled",image_layer_set_tiled,tFunc(tInt,tObj),0);
e01a022000-02-08Per Hedbor  ADD_FUNCTION("set_misc_value", image_layer_set_misc_value, tFunc(tMixed tMixed, tMixed),0 );
7e8e2d1999-04-17Mirar (Pontus Hagland)  /* query */
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("image",image_layer_image,tFunc(tNone,tObj),0); ADD_FUNCTION("alpha",image_layer_alpha,tFunc(tNone,tObj),0); ADD_FUNCTION("mode",image_layer_mode,tFunc(tNone,tStr),0);
7e8e2d1999-04-17Mirar (Pontus Hagland) 
3695ff1999-04-19Mirar (Pontus Hagland)  ADD_FUNCTION("available_modes",image_layer_available_modes,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tArr(tStr)),0);
b77f951999-08-10Mirar (Pontus Hagland)  ADD_FUNCTION("descriptions",image_layer_descriptions, tFunc(tNone,tArr(tStr)),0);
3695ff1999-04-19Mirar (Pontus Hagland) 
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("xsize",image_layer_xsize,tFunc(tNone,tInt),0); ADD_FUNCTION("ysize",image_layer_ysize,tFunc(tNone,tInt),0);
55e2dd1999-04-23Mirar (Pontus Hagland) 
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("xoffset",image_layer_xoffset,tFunc(tNone,tInt),0); ADD_FUNCTION("yoffset",image_layer_yoffset,tFunc(tNone,tInt),0);
7e8e2d1999-04-17Mirar (Pontus Hagland) 
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("alpha_value",image_layer_alpha_value,tFunc(tNone,tFloat),0); ADD_FUNCTION("fill",image_layer_fill,tFunc(tNone,tObj),0); ADD_FUNCTION("fill_alpha",image_layer_fill_alpha,tFunc(tNone,tObj),0); ADD_FUNCTION("tiled",image_layer_tiled,tFunc(tNone,tInt01),0);
ae9bb11999-06-18Mirar (Pontus Hagland) 
e01a022000-02-08Per Hedbor  ADD_FUNCTION("get_misc_value", image_layer_get_misc_value, tFunc(tMixed, tMixed),0 );
ae9bb11999-06-18Mirar (Pontus Hagland)  /* image-object operations */ ADD_FUNCTION("crop",image_layer_crop, tFunc(tInt tInt tInt tInt,tObj),0);
7383191999-06-21Mirar (Pontus Hagland)  ADD_FUNCTION("autocrop",image_layer_autocrop,
c3b5b41999-07-20Fredrik Hübinette (Hubbe)  tFuncV(tNone,tOr(tVoid,tInt),tObj),0);
7383191999-06-21Mirar (Pontus Hagland)  ADD_FUNCTION("find_autocrop",image_layer_find_autocrop,
c3b5b41999-07-20Fredrik Hübinette (Hubbe)  tFuncV(tNone,tOr(tVoid,tInt),tObj),0);
ae9bb11999-06-18Mirar (Pontus Hagland)  /* ADD_FUNCTION("rotate",image_layer_rotate,tFunc(tOr(tInt,tFloat),tObj),0); ADD_FUNCTION("scale",image_layer_scale,tOr3(tFunc(tInt tInt,tObj), tFunc(tFloat,tObj), tFunc(tFloat,tFloat,tObj)),0); ADD_FUNCTION("translate",image_layer_translate, tFunc(tOr(tInt,tFlt) tOr(tInt,tFlt),tObj),0); */
7e8e2d1999-04-17Mirar (Pontus Hagland) } void exit_image_layers(void) { int i;
e01a022000-02-08Per Hedbor 
7e8e2d1999-04-17Mirar (Pontus Hagland)  for (i=0; i<LAYER_MODES; i++) free_string(layer_mode[i].ps); }