From 91c0003b158e5f0ed9d0677fb136ae8bb6f86ec5 Mon Sep 17 00:00:00 2001 From: "N.N." Date: Mon, 28 Apr 2008 18:10:15 +0000 Subject: this is an old gridflow, and there's already a svn repository at http://gridflow.ca/svn/trunk svn path=/trunk/; revision=9739 --- externals/gridflow/base/flow_objects_for_image.c | 619 ----------------------- 1 file changed, 619 deletions(-) delete mode 100644 externals/gridflow/base/flow_objects_for_image.c (limited to 'externals/gridflow/base/flow_objects_for_image.c') diff --git a/externals/gridflow/base/flow_objects_for_image.c b/externals/gridflow/base/flow_objects_for_image.c deleted file mode 100644 index f6d6398d..00000000 --- a/externals/gridflow/base/flow_objects_for_image.c +++ /dev/null @@ -1,619 +0,0 @@ -/* - $Id: flow_objects_for_image.c,v 1.2 2006-03-15 04:37:08 matju Exp $ - - GridFlow - Copyright (c) 2001,2002,2003,2004,2005 by Mathieu Bouchard - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - See file ../COPYING for further informations on licensing terms. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include "grid.h.fcs" - -static void expect_picture (P d) { - if (d->n!=3) RAISE("(height,width,chans) dimensions please");} -static void expect_rgb_picture (P d) { - expect_picture(d); - if (d->get(2)!=3) RAISE("(red,green,blue) channels please");} -static void expect_rgba_picture (P d) { - expect_picture(d); - if (d->get(2)!=4) RAISE("(red,green,blue,alpha) channels please");} -static void expect_max_one_dim (P d) { - if (d->n>1) { RAISE("expecting Dim[] or Dim[n], got %s",d->to_s()); }} - -//**************************************************************** -//{ Dim[A,B,*Cs],Dim[D,E] -> Dim[A,B,*Cs] } - -static void expect_convolution_matrix (P d) { - if (d->n != 2) RAISE("only exactly two dimensions allowed for now (got %d)", - d->n); -} - -// entry in a compiled convolution kernel -struct PlanEntry { int y,x; bool neutral; }; - -\class GridConvolve < GridObject -struct GridConvolve : GridObject { - \attr Numop *op_para; - \attr Numop *op_fold; - \attr PtrGrid seed; - \attr PtrGrid b; - PtrGrid a; - int plann; - PlanEntry *plan; //Pt? - int margx,margy; // margins - GridConvolve () : plan(0) { b.constrain(expect_convolution_matrix); plan=0; } - \decl void initialize (Grid *r=0); - \decl void _0_op (Numop *op); - \decl void _0_fold (Numop *op); - \decl void _0_seed (Grid *seed); - \grin 0 - \grin 1 - template void copy_row (Pt buf, int sx, int y, int x); - template void make_plan (T bogus); - ~GridConvolve () {if (plan) delete[] plan;} -}; - -template void GridConvolve::copy_row (Pt buf, int sx, int y, int x) { - int day = a->dim->get(0), dax = a->dim->get(1), dac = a->dim->prod(2); - y=mod(y,day); x=mod(x,dax); - Pt ap = (Pt)*a + y*dax*dac; - while (sx) { - int sx1 = min(sx,dax-x); - COPY(buf,ap+x*dac,sx1*dac); - x=0; - buf += sx1*dac; - sx -= sx1; - } -} - -static Numop *OP(Ruby x) {return FIX2PTR(Numop,rb_hash_aref(op_dict,x));} - -template void GridConvolve::make_plan (T bogus) { - P da = a->dim, db = b->dim; - int dby = db->get(0); - int dbx = db->get(1); - if (plan) delete[] plan; - plan = new PlanEntry[dbx*dby]; - int i=0; - for (int y=0; y)*b)[y*dbx+x]; - bool neutral = op_para->on(rh)->is_neutral(rh,at_right); - bool absorbent = op_para->on(rh)->is_absorbent(rh,at_right); - STACK_ARRAY(T,foo,1); - if (absorbent) { - foo[0] = 0; - op_para->map(1,foo,rh); - absorbent = op_fold->on(rh)->is_neutral(foo[0],at_right); - } - if (absorbent) continue; - plan[i].y = y; - plan[i].x = x; - plan[i].neutral = neutral; - i++; - } - } - plann = i; -} - -GRID_INLET(GridConvolve,0) { - SAME_TYPE(in,b); - SAME_TYPE(in,seed); - P da = in->dim, db = b->dim; - if (!db) RAISE("right inlet has no grid"); - if (!seed) RAISE("seed missing"); - if (db->n != 2) RAISE("right grid must have two dimensions"); - if (da->n < 2) RAISE("left grid has less than two dimensions"); - if (seed->dim->n != 0) RAISE("seed must be scalar"); - if (da->get(0) < db->get(0)) RAISE("grid too small (y): %d < %d", da->get(0), db->get(0)); - if (da->get(1) < db->get(1)) RAISE("grid too small (x): %d < %d", da->get(1), db->get(1)); - margy = (db->get(0)-1)/2; - margx = (db->get(1)-1)/2; - a=new Grid(in->dim,in->nt); - out=new GridOutlet(this,0,da,in->nt); -} GRID_FLOW { - COPY((Pt)*a+in->dex, data, n); -} GRID_FINISH { - Numop *op_put = OP(SYM(put)); - make_plan((T)0); - int dbx = b->dim->get(1); - int day = a->dim->get(0); - int n = a->dim->prod(1); - int sx = a->dim->get(1)+dbx-1; - int n2 = sx*a->dim->prod(2); - STACK_ARRAY(T,buf,n); - STACK_ARRAY(T,buf2,n2); - T orh=0; - for (int iy=0; iymap(n,buf,*(T *)*seed); - for (int i=0; i)*b)[jy*dbx+jx]; - if (i==0 || plan[i].y!=plan[i-1].y || orh!=rh) { - copy_row(buf2,sx,iy+jy-margy,-margx); - if (!plan[i].neutral) op_para->map(n2,buf2,rh); - } - op_fold->zip(n,buf,buf2+jx*a->dim->prod(2)); - orh=rh; - } - out->send(n,buf); - } - a=0; -} GRID_END - -GRID_INPUT(GridConvolve,1,b) {} GRID_END - -\def void _0_op (Numop *op ) { this->op_para=op; } -\def void _0_fold (Numop *op ) { this->op_fold=op; } -\def void _0_seed (Grid *seed) { this->seed=seed; } - -\def void initialize (Grid *r) { - rb_call_super(argc,argv); - this->op_para = op_mul; - this->op_fold = op_add; - this->seed = new Grid(new Dim(),int32_e,true); - this->b= r ? r : new Grid(new Dim(1,1),int32_e,true); -} - -\classinfo { IEVAL(rself,"install '#convolve',2,1"); } -\end class GridConvolve - -/* ---------------------------------------------------------------- */ -/* "#scale_by" does quick scaling of pictures by integer factors */ -/*{ Dim[A,B,3] -> Dim[C,D,3] }*/ -\class GridScaleBy < GridObject -struct GridScaleBy : GridObject { - \attr PtrGrid scale; // integer scale factor - int scaley; - int scalex; - \decl void initialize (Grid *factor=0); - \grin 0 - \grin 1 - void prepare_scale_factor () { - scaley = ((Pt)*scale)[0]; - scalex = ((Pt)*scale)[scale->dim->prod()==1 ? 0 : 1]; - if (scaley<1) scaley=2; - if (scalex<1) scalex=2; - } -}; - -GRID_INLET(GridScaleBy,0) { - P a = in->dim; - expect_picture(a); - out=new GridOutlet(this,0,new Dim(a->get(0)*scaley,a->get(1)*scalex,a->get(2)),in->nt); - in->set_factor(a->get(1)*a->get(2)); -} GRID_FLOW { - int rowsize = in->dim->prod(1); - STACK_ARRAY(T,buf,rowsize*scalex); - int chans = in->dim->get(2); - #define Z(z) buf[p+z]=data[i+z] - for (; n>0; data+=rowsize, n-=rowsize) { - int p=0; - #define LOOP(z) \ - for (int i=0; isend(rowsize*scalex,buf); - } - #undef Z -} GRID_END - -static void expect_scale_factor (P dim) { - if (dim->prod()!=1 && dim->prod()!=2) - RAISE("expecting only one or two numbers"); -} - -GRID_INPUT(GridScaleBy,1,scale) { prepare_scale_factor(); } GRID_END - -\def void initialize (Grid *factor) { - scale.constrain(expect_scale_factor); - rb_call_super(argc,argv); - scale=new Grid(INT2NUM(2)); - if (factor) scale=factor; - prepare_scale_factor(); -} - -\classinfo { IEVAL(rself,"install '#scale_by',2,1"); } -\end class GridScaleBy - -// ---------------------------------------------------------------- -//{ Dim[A,B,3] -> Dim[C,D,3] } -\class GridDownscaleBy < GridObject -struct GridDownscaleBy : GridObject { - \attr PtrGrid scale; - \attr bool smoothly; - int scaley; - int scalex; - PtrGrid temp; - \decl void initialize (Grid *factor=0, Symbol option=Qnil); - \grin 0 - \grin 1 - void prepare_scale_factor () { - scaley = ((Pt)*scale)[0]; - scalex = ((Pt)*scale)[scale->dim->prod()==1 ? 0 : 1]; - if (scaley<1) scaley=2; - if (scalex<1) scalex=2; - } -}; - -GRID_INLET(GridDownscaleBy,0) { - - P a = in->dim; - if (a->n!=3) RAISE("(height,width,chans) please"); - out=new GridOutlet(this,0,new Dim(a->get(0)/scaley,a->get(1)/scalex,a->get(2)),in->nt); - in->set_factor(a->get(1)*a->get(2)); - // i don't remember why two rows instead of just one. - temp=new Grid(new Dim(2,in->dim->get(1)/scalex,in->dim->get(2)),in->nt); -} GRID_FLOW { - int rowsize = in->dim->prod(1); - int rowsize2 = temp->dim->prod(1); - Pt buf = (Pt)*temp; //!@#$ maybe should be something else than T ? - int xinc = in->dim->get(2)*scalex; - int y = in->dex / rowsize; - int chans=in->dim->get(2); - #define Z(z) buf[p+z]+=data[i+z] - if (smoothly) { - while (n>0) { - if (y%scaley==0) CLEAR(buf,rowsize2); - #define LOOP(z) \ - for (int i=0,p=0; pdim) { - op_div->map(rowsize2,buf,(T)(scalex*scaley)); - out->send(rowsize2,buf); - CLEAR(buf,rowsize2); - } - data+=rowsize; - n-=rowsize; - } - #undef Z - } else { - #define Z(z) buf[p+z]=data[i+z] - for (; n>0 && out->dim; data+=rowsize, n-=rowsize,y++) { - if (y%scaley!=0) continue; - #define LOOP(z) for (int i=0,p=0; pdim->get(2)) { - case 1: LOOP(1) {Z(0);} break; - case 2: LOOP(2) {Z(0);Z(1);} break; - case 3: LOOP(3) {Z(0);Z(1);Z(2);} break; - case 4: LOOP(4) {Z(0);Z(1);Z(2);Z(3);} break; - default:LOOP(chans) {for (int k=0; ksend(rowsize2,buf); - } - } - #undef Z -} GRID_END - -GRID_INPUT(GridDownscaleBy,1,scale) { prepare_scale_factor(); } GRID_END - -\def void initialize (Grid *factor, Symbol option) { - scale.constrain(expect_scale_factor); - rb_call_super(argc,argv); - scale=new Grid(INT2NUM(2)); - if (factor) scale=factor; - prepare_scale_factor(); - smoothly = option==SYM(smoothly); -} - -\classinfo { IEVAL(rself,"install '#downscale_by',2,1"); } -\end class GridDownscaleBy - -//**************************************************************** -\class GridLayer < GridObject -struct GridLayer : GridObject { - PtrGrid r; - GridLayer() { r.constrain(expect_rgb_picture); } - \grin 0 int - \grin 1 int -}; - -GRID_INLET(GridLayer,0) { - NOTEMPTY(r); - SAME_TYPE(in,r); - P a = in->dim; - expect_rgba_picture(a); - if (a->get(1)!=r->dim->get(1)) RAISE("same width please"); - if (a->get(0)!=r->dim->get(0)) RAISE("same height please"); - in->set_factor(a->prod(2)); - out=new GridOutlet(this,0,r->dim); -} GRID_FLOW { - Pt rr = ((Pt)*r) + in->dex*3/4; - STACK_ARRAY(T,foo,n*3/4); -#define COMPUTE_ALPHA(c,a) \ - foo[j+c] = (data[i+c]*data[i+a] + rr[j+c]*(256-data[i+a])) >> 8 - for (int i=0,j=0; isend(n*3/4,foo); -} GRID_END - -GRID_INPUT(GridLayer,1,r) {} GRID_END - -\classinfo { IEVAL(rself,"install '#layer',2,1"); } -\end class GridLayer - -// **************************************************************** -// pad1,pad2 only are there for 32-byte alignment -struct Line { int32 y1,x1,y2,x2,x,m,pad1,pad2; }; - -static void expect_polygon (P d) { - if (d->n!=2 || d->get(1)!=2) RAISE("expecting Dim[n,2] polygon"); -} - -\class DrawPolygon < GridObject -struct DrawPolygon : GridObject { - \attr Numop *op; - \attr PtrGrid color; - \attr PtrGrid polygon; - PtrGrid color2; - PtrGrid lines; - int lines_start; - int lines_stop; - DrawPolygon() { - color.constrain(expect_max_one_dim); - polygon.constrain(expect_polygon); - } - \decl void initialize (Numop *op, Grid *color=0, Grid *polygon=0); - \grin 0 - \grin 1 - \grin 2 int32 - void init_lines(); - -}; - -void DrawPolygon::init_lines () { - int nl = polygon->dim->get(0); - lines=new Grid(new Dim(nl,8), int32_e); - Pt ld = Pt((Line *)(int32 *)*lines,nl); - Pt pd = *polygon; - for (int i=0,j=0; ild[i].y2) memswap(Pt(ld+i)+0,Pt(ld+i)+2,2); - } -} - -static int order_by_starting_scanline (const void *a, const void *b) { - return ((Line *)a)->y1 - ((Line *)b)->y1; -} - -static int order_by_column (const void *a, const void *b) { - return ((Line *)a)->x - ((Line *)b)->x; -} - -GRID_INLET(DrawPolygon,0) { - NOTEMPTY(color); - NOTEMPTY(polygon); - NOTEMPTY(lines); - SAME_TYPE(in,color); - if (in->dim->n!=3) RAISE("expecting 3 dimensions"); - if (in->dim->get(2)!=color->dim->get(0)) - RAISE("image does not have same number of channels as stored color"); - out=new GridOutlet(this,0,in->dim,in->nt); - lines_start = lines_stop = 0; - in->set_factor(in->dim->get(1)*in->dim->get(2)); - int nl = polygon->dim->get(0); - qsort((int32 *)*lines,nl,sizeof(Line),order_by_starting_scanline); - int cn = color->dim->prod(); - color2=new Grid(new Dim(cn*16), color->nt); - for (int i=0; i<16; i++) COPY((Pt)*color2+cn*i,(Pt)*color,cn); -} GRID_FLOW { - int nl = polygon->dim->get(0); - Pt ld = Pt((Line *)(int32 *)*lines,nl); - int f = in->factor(); - int y = in->dex/f; - int cn = color->dim->prod(); - Pt cd = (Pt)*color2; - - while (n) { - while (lines_stop != nl && ld[lines_stop].y1<=y) lines_stop++; - for (int i=lines_start; isend(f,data); - } else { - int32 xl = in->dim->get(1); - Pt data2 = ARRAY_NEW(T,f); - COPY(data2,data,f); - for (int i=lines_start; i=xe) continue; /* !@#$ WHAT? */ - while (xe-xs>=16) { op->zip(16*cn,data2+cn*xs,cd); xs+=16; } - op->zip((xe-xs)*cn,data2+cn*xs,cd); - } - out->give(f,data2); - } - n-=f; - data+=f; - y++; - } -} GRID_END - - -GRID_INPUT(DrawPolygon,1,color) {} GRID_END -GRID_INPUT(DrawPolygon,2,polygon) {init_lines();} GRID_END - -\def void initialize (Numop *op, Grid *color, Grid *polygon) { - rb_call_super(argc,argv); - this->op = op; - if (color) this->color=color; - if (polygon) { this->polygon=polygon; init_lines(); } -} - -\classinfo { IEVAL(rself,"install '#draw_polygon',3,1"); } -\end class DrawPolygon - -//**************************************************************** -static void expect_position(P d) { - if (d->n!=1) RAISE("position should have 1 dimension, not %d", d->n); - if (d->v[0]!=2) RAISE("position dim 0 should have 2 elements, not %d", d->v[0]); -} - -\class DrawImage < GridObject -struct DrawImage : GridObject { - \attr Numop *op; - \attr PtrGrid image; - \attr PtrGrid position; - \attr bool alpha; - \attr bool tile; - - DrawImage() : alpha(false), tile(false) { - position.constrain(expect_position); - image.constrain(expect_picture); - } - - \decl void initialize (Numop *op, Grid *image=0, Grid *position=0); - \decl void _0_alpha (bool v=true); - \decl void _0_tile (bool v=true); - \grin 0 - \grin 1 - \grin 2 int32 - // draw row # ry of right image in row buffer buf, starting at xs - // overflow on both sides has to be handled automatically by this method - template void draw_segment(Pt obuf, Pt ibuf, int ry, int x0); -}; - -#define COMPUTE_ALPHA(c,a) obuf[j+(c)] = ibuf[j+(c)] + (rbuf[a])*(obuf[j+(c)]-ibuf[j+(c)])/256; -#define COMPUTE_ALPHA4(b) \ - COMPUTE_ALPHA(b+0,b+3); \ - COMPUTE_ALPHA(b+1,b+3); \ - COMPUTE_ALPHA(b+2,b+3); \ - obuf[b+3] = rbuf[b+3] + (255-rbuf[b+3])*(ibuf[j+b+3])/256; - -template void DrawImage::draw_segment(Pt obuf, Pt ibuf, int ry, int x0) { - if (ry<0 || ry>=image->dim->get(0)) return; // outside of image - int sx = in[0]->dim->get(1), rsx = image->dim->get(1); - int sc = in[0]->dim->get(2), rsc = image->dim->get(2); - Pt rbuf = (Pt)*image + ry*rsx*rsc; - if (x0>sx || x0<=-rsx) return; // outside of buffer - int n=rsx; - if (x0+n>sx) n=sx-x0; - if (x0<0) { rbuf-=rsc*x0; n+=x0; x0=0; } - if (alpha && rsc==4 && sc==3) { // RGB by RGBA //!@#$ optimise - int j=sc*x0; - for (; n; n--, rbuf+=4, j+=3) { - op->zip(sc,obuf+j,rbuf); COMPUTE_ALPHA(0,3); COMPUTE_ALPHA(1,3); COMPUTE_ALPHA(2,3); - } - } else if (alpha && rsc==4 && sc==4) { // RGBA by RGBA - op->zip(n*rsc,obuf+x0*rsc,rbuf); - int j=sc*x0; - for (; n>=4; n-=4, rbuf+=16, j+=16) { - COMPUTE_ALPHA4(0);COMPUTE_ALPHA4(4); - COMPUTE_ALPHA4(8);COMPUTE_ALPHA4(12); - } - for (; n; n--, rbuf+=4, j+=4) { - COMPUTE_ALPHA4(0); - } - } else { // RGB by RGB, etc - op->zip(n*rsc,obuf+sc*x0,rbuf); - } -} - -GRID_INLET(DrawImage,0) { - NOTEMPTY(image); - NOTEMPTY(position); - SAME_TYPE(in,image); - if (in->dim->n!=3) RAISE("expecting 3 dimensions"); - int lchan = in->dim->get(2); - int rchan = image->dim->get(2); - if (alpha && rchan!=4) { - RAISE("alpha mode works only with 4 channels in right_hand"); - } - if (lchan != rchan-(alpha?1:0) && lchan != rchan) { - RAISE("right_hand has %d channels, alpha=%d, left_hand has %d, expecting %d or %d", - rchan, alpha?1:0, lchan, rchan-(alpha?1:0), rchan); - } - out=new GridOutlet(this,0,in->dim,in->nt); - in->set_factor(in->dim->get(1)*in->dim->get(2)); -} GRID_FLOW { - int f = in->factor(); - int y = in->dex/f; - if (position->nt != int32_e) RAISE("position has to be int32"); - int py = ((int32*)*position)[0], rsy = image->dim->v[0], sy=in->dim->get(0); - int px = ((int32*)*position)[1], rsx = image->dim->v[1], sx=in->dim->get(1); - for (; n; y++, n-=f, data+=f) { - int ty = div2(y-py,rsy); - if (tile || ty==0) { - Pt data2 = ARRAY_NEW(T,f); - COPY(data2,data,f); - if (tile) { - for (int x=px-div2(px+rsx-1,rsx)*rsx; xgive(f,data2); - } else { - out->send(f,data); - } - } -} GRID_END - -GRID_INPUT(DrawImage,1,image) {} GRID_END -GRID_INPUT(DrawImage,2,position) {} GRID_END -\def void _0_alpha (bool v=true) { alpha = v; gfpost("ALPHA=%d",v); } -\def void _0_tile (bool v=true) { tile = v; } - -\def void initialize (Numop *op, Grid *image, Grid *position) { - rb_call_super(argc,argv); - this->op = op; - if (image) this->image=image; - if (position) this->position=position; - else this->position=new Grid(new Dim(2),int32_e,true); -} - -\classinfo { IEVAL(rself,"install '#draw_image',3,1"); } -\end class DrawImage - -void startup_flow_objects_for_image () { - \startall -} -- cgit v1.2.1