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

version» Context lines:

pike.git/src/modules/Image/layers.c:1:   /*   **! module Image   **! note - **! $Id: layers.c,v 1.19 1999/06/19 22:11:35 grubba Exp $ + **! $Id: layers.c,v 1.20 1999/06/21 18:03:19 mirar Exp $   **! class Layer   */      #include "global.h"      #include <math.h> /* floor */    - RCSID("$Id: layers.c,v 1.19 1999/06/19 22:11:35 grubba Exp $"); + RCSID("$Id: layers.c,v 1.20 1999/06/21 18:03:19 mirar Exp $");      #include "image_machine.h"      #include "stralloc.h"   #include "pike_macros.h"   #include "object.h"   #include "constants.h"   #include "interpret.h"   #include "svalue.h"   #include "array.h"
pike.git/src/modules/Image/layers.c:97:   LMFUNC(lm_modulo);   LMFUNC(lm_invsubtract);   LMFUNC(lm_invdivide);   LMFUNC(lm_invmodulo);   LMFUNC(lm_difference);   LMFUNC(lm_min);   LMFUNC(lm_max);   LMFUNC(lm_bitwise_and);   LMFUNC(lm_bitwise_or);   LMFUNC(lm_bitwise_xor); + 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);      LMFUNC(lm_replace);   LMFUNC(lm_red);   LMFUNC(lm_green);   LMFUNC(lm_blue);      LMFUNC(lm_replace_hsv);   LMFUNC(lm_hue);   LMFUNC(lm_saturation);   LMFUNC(lm_value);
pike.git/src/modules/Image/layers.c:135:    {"subtract", lm_subtract, 1, NULL },    {"multiply", lm_multiply, 1, NULL },    {"divide", lm_divide, 1, NULL },    {"modulo", lm_modulo, 1, NULL },    {"invsubtract", lm_invsubtract, 1, NULL },    {"invdivide", lm_invdivide, 1, NULL },    {"invmodulo", lm_invmodulo, 1, NULL },    {"difference", lm_difference, 1, NULL },    {"max", lm_max, 1, NULL },    {"min", lm_min, 1, NULL }, -  {"bitwize_and", lm_bitwise_and, 1, NULL }, -  {"bitwize_or", lm_bitwise_or, 1, NULL }, -  {"bitwize_xor", lm_bitwise_xor, 1, NULL }, +  {"bitwise_and", lm_bitwise_and, 1, NULL }, +  {"bitwise_or", lm_bitwise_or, 1, NULL }, +  {"bitwise_xor", lm_bitwise_xor, 1, NULL }, +  {"equal", lm_equal, 0, NULL }, +  {"not_equal", lm_not_equal, 0, NULL }, +  {"less", lm_less, 0, NULL }, +  {"more", lm_more, 0, NULL }, +  {"less_or_equal", lm_less_or_equal, 0, NULL }, +  {"more_or_equal", lm_more_or_equal, 0, NULL }, +  {"logic_equal", lm_logic_equal, 0, NULL }, +  {"logic_not_equal",lm_logic_not_equal,0, NULL }, +  {"logic_strict_less",lm_logic_strict_less,0, NULL }, +  {"logic_strict_more",lm_logic_strict_more,0, NULL }, +  {"logic_strict_less_equal",lm_logic_strict_less_or_equal,0, NULL }, +  {"logic_strict_more_equal",lm_logic_strict_more_or_equal,0, NULL },       {"replace", lm_replace, 1, NULL },    {"red", lm_red, 1, NULL },    {"green", lm_green, 1, NULL },    {"blue", lm_blue, 1, NULL },       {"replace_hsv", lm_replace_hsv, 1, NULL },    {"hue", lm_hue, 1, NULL },    {"saturation", lm_saturation, 1, NULL },    {"value", lm_value, 1, NULL },
pike.git/src/modules/Image/layers.c:582:   **! "subtract",   **! "multiply",   **! "divide",   **! "modulo",   **! "invsubtract",   **! "invdivide",   **! "invmodulo",   **! "difference",   **! "max",   **! "min", - **! "bitwize_and", - **! "bitwize_or", - **! "bitwize_xor", + **! "bitwise_and", + **! "bitwise_or", + **! "bitwise_xor",   **!   **! "replace",   **! "red",   **! "green",   **! "blue",   **!   **! "replace_hsv",   **! "hue",   **! "saturation",   **! "value",
pike.git/src/modules/Image/layers.c:1161:   #undef L_OPER      #define LM_FUNC lm_bitwise_xor   #define L_TRUNC(X) ((COLORTYPE)(X))   #define L_OPER(A,B) ((A)^(B))   #include "layer_oper.h"   #undef LM_FUNC   #undef L_TRUNC   #undef L_OPER    + #define LM_FUNC lm_equal + #define L_TRUNC(X) ((COLORTYPE)(X)) + #define L_OPER(A,B) (((A)==(B))?COLORMAX:0) + #include "layer_oper.h" + #undef LM_FUNC + #undef L_TRUNC + #undef L_OPER +  + #define LM_FUNC lm_not_equal + #define L_TRUNC(X) ((COLORTYPE)(X)) + #define L_OPER(A,B) (((A)!=(B))?COLORMAX:0) + #include "layer_oper.h" + #undef LM_FUNC + #undef L_TRUNC + #undef L_OPER +  + #define LM_FUNC lm_less + #define L_TRUNC(X) ((COLORTYPE)(X)) + #define L_OPER(A,B) (((A)>(B))?COLORMAX:0) + #include "layer_oper.h" + #undef LM_FUNC + #undef L_TRUNC + #undef L_OPER +  + #define LM_FUNC lm_more + #define L_TRUNC(X) ((COLORTYPE)(X)) + #define L_OPER(A,B) (((A)<(B))?COLORMAX:0) + #include "layer_oper.h" + #undef LM_FUNC + #undef L_TRUNC + #undef L_OPER +  + #define LM_FUNC lm_less_or_equal + #define L_TRUNC(X) ((COLORTYPE)(X)) + #define L_OPER(A,B) (((A)>=(B))?COLORMAX:0) + #include "layer_oper.h" + #undef LM_FUNC + #undef L_TRUNC + #undef L_OPER +  + #define LM_FUNC lm_more_or_equal + #define L_TRUNC(X) ((COLORTYPE)(X)) + #define L_OPER(A,B) (((A)<=(B))?COLORMAX:0) + #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 + #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 + #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 + #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 + #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 + #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 + #include "layer_oper.h" + #undef L_TRANS + #undef L_OPER + #undef LM_FUNC + #undef L_LOGIC +    /* 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) \
pike.git/src/modules/Image/layers.c:1508:    while (len--)    {    da->r=CCUT(sa->r*(int)(COLORMAX-alpha*la->r));    da->g=CCUT(sa->g*(int)(COLORMAX-alpha*la->g));    da->b=CCUT(sa->b*(int)(COLORMAX-alpha*la->b));       la++; sa++; da++;    }   }    -  +    /*** the add-layer function ***************************/      static INLINE void img_lay_first_line(struct layer *l,    int xoffs,int xsize,    int y, /* in _this_ layer */    rgb_group *d,rgb_group *da)   {    if (!l->tiled)    {    rgb_group *s,*sa;
pike.git/src/modules/Image/layers.c:1951:    /* ok, do it! */    img_lay(l,layers,dest);       sp--;    pop_n_elems(args);    push_object(o);   }      /** image-object operations *************************/    - /* - **! 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. - **! returns a new layer object - **! note: - **! The new layer object may have the same image object, - **! if there was no cropping to be done. - */ -  +    static INLINE struct layer *push_new_layer()   {    push_object(clone_object(image_layer_program,0));    return (struct layer*)get_storage(sp[-1].u.object,image_layer_program);   }      static INLINE struct layer *clone_this_layer()   {    struct layer *l;    l=push_new_layer();
pike.git/src/modules/Image/layers.c:1993:    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;    return l;   }    + /* + **! 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. + */ +    static void image_layer_crop(INT32 args)   {    struct layer *l;    int x,y,xz,yz,xi,yi;    int zot=0;    struct image *img;       get_all_args("Image.Layer->crop",args,"%d%d%d%d",&x,&y,&xz,&yz);       l=clone_this_layer();
pike.git/src/modules/Image/layers.c:2016:    if (l->ysize+l->yoffs<=y+yz) yz=l->ysize-(y-l->yoffs); else zot++;       fprintf(stderr,"old %d,%d + %d,%d\n",l->xoffs,l->yoffs,l->xsize,l->ysize);    fprintf(stderr,"new %d,%d + %d,%d zot=%d\n",x,y,xz,yz,zot);    xi=x-l->xoffs;    yi=y-l->yoffs;    l->xoffs=x;    l->yoffs=y;    fprintf(stderr,"crop %d,%d + %d,%d zot=%d\n",xi,yi,xz,yz,zot);    -  if (l->image) +  if (zot && l->image)    {    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); -  f_call_function(5); +  push_int(THIS->fill.r); +  push_int(THIS->fill.g); +  push_int(THIS->fill.b); +  f_call_function(8);    if (sp[-1].type!=T_OBJECT ||    !(img=(struct image*)get_storage(sp[-1].u.object,image_program)))    error("No image returned from image->copy\n");    if (img->xsize!=xz || img->ysize!=yz)    error("Image returned from image->copy had "    "unexpected size (%d,%d, expected %d,%d)\n",    img->xsize,img->ysize,xz,yz);       free_object(l->image);    l->image=sp[-1].u.object;    sp--;    l->img=img;    }    -  if (l->alpha) +  if (zot && l->alpha)    {    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); -  f_call_function(5); +  push_int(THIS->fill_alpha.r); +  push_int(THIS->fill_alpha.g); +  push_int(THIS->fill_alpha.b); +  f_call_function(8);    if (sp[-1].type!=T_OBJECT ||    !(img=(struct image*)get_storage(sp[-1].u.object,image_program)))    error("No image returned from alpha->copy\n");    if (img->xsize!=xz || img->ysize!=yz)    error("Image returned from alpha->copy had "    "unexpected size (%d,%d, expected %d,%d)\n",    img->xsize,img->ysize,xz,yz);    free_object(l->alpha);    l->alpha=sp[-1].u.object;    sp--;    l->alp=img;    }    -  +  l->xoffs=x; +  l->yoffs=y; +  l->xsize=xz; +  l->ysize=yz; +     stack_pop_n_elems_keep_top(args);   }    -  + /* + **! 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. + **! + **! (What really happens is that the image and alpha channel is checked, + **! 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. + **! + **! see also: + **! crop, Image.Image->autocrop + */ +  + static void image_layer_find_autocrop(INT32 args) + { +  int x1=0,y1=0,x2=THIS->xsize-1,y2=THIS->ysize-1; +  int l=1,r=1,t=1,b=1; +  +  if (args>3) +  get_all_args("find_autocrop",args,"%d%d%d%d",&l,&r,&t,&b); +  +  if (!THIS->tiled) +  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 */ +  { +  int ix1,iy1,ix2,iy2; +  img_find_autocrop(THIS->img, &ix1,&iy1,&ix2,&iy2, +  0,l,r,t,b,1,THIS->fill); +  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, +  0,l,r,t,b,1,THIS->fill); +  } +  +  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); +  sp--; +  push_array_items(sp->u.array); /* frees */ +  image_layer_crop(4); + } +  +    /******************************************************/      void init_image_layers(void)   {    char buf[100];    char buf2[sizeof(INT32)];    int i;       for (i=0; i<LAYER_MODES; i++)    layer_mode[i].ps=make_shared_string(layer_mode[i].name);
pike.git/src/modules/Image/layers.c:2129:    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);       /* image-object operations */       ADD_FUNCTION("crop",image_layer_crop,    tFunc(tInt tInt tInt tInt,tObj),0); +  ADD_FUNCTION("autocrop",image_layer_autocrop, +  tFuncV(,tOr(tVoid,tInt),tObj),0); +  ADD_FUNCTION("find_autocrop",image_layer_find_autocrop, +  tFuncV(,tOr(tVoid,tInt),tObj),0);       /*    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("autocrop",image_layer_autocrop, -  tFuncV(,tOr(tVoid,tInt),tObj),0); -  ADD_FUNCTION("find_autocrop",image_layer_autocrop, -  tFuncV(,tOr(tVoid,tInt),tObj),0); +     ADD_FUNCTION("translate",image_layer_translate,    tFunc(tOr(tInt,tFlt) tOr(tInt,tFlt),tObj),0);    */   }      void exit_image_layers(void)   {    int i;       for (i=0; i<LAYER_MODES; i++)    free_string(layer_mode[i].ps);   }