/* $Id: gem.c 3865 2008-06-11 21:13:58Z matju $ GridFlow Copyright (c) 2001-2008 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 "../gridflow.h.fcs" #include "Base/GemPixDualObj.h" struct GridToPix; struct GridToPixHelper : GemPixObj { GridToPix *boss; CPPEXTERN_HEADER(GridToPixHelper,GemPixObj) public: GridToPixHelper () {} virtual void startRendering(); virtual void render(GemState *state); virtual bool isRunnable () {return true;} // required to keep GEM 0.9.1 (the real 0.9.1) happy }; CPPEXTERN_NEW(GridToPixHelper) // in 0: gem // in 1: grid // out 0: gem \class GridToPix : FObject { GridToPixHelper *helper; P bit_packing; pixBlock m_pixBlock; \attr bool yflip; GridToPix (BFObject *bself, MESSAGE) : FObject(bself,MESSAGE2) { yflip = false; imageStruct &im = m_pixBlock.image = imageStruct(); im.ysize = 1; im.xsize = 1; im.csize = 4; im.format = GL_RGBA; im.type = GL_UNSIGNED_BYTE; im.allocate(); *(int*)im.data = 0x0000ff; uint32 mask[4] = {0x0000ff,0x00ff00,0xff0000,0x000000}; bit_packing = new BitPacking(is_le(),4,4,mask); helper = new GridToPixHelper; helper->boss = this; bself->gemself = helper; } ~GridToPix () {} \grin 1 int }; GRID_INLET(GridToPix,1) { if (in->dim->n != 3) RAISE("expecting 3 dimensions: rows,columns,channels"); if (in->dim->get(2) != 4) RAISE("expecting 4 channels (got %d)",in->dim->get(2)); in->set_chunk(1); imageStruct &im = m_pixBlock.image; im.clear(); im.ysize = in->dim->get(0); im.xsize = in->dim->get(1); im.csize = in->dim->get(2); im.type = GL_UNSIGNED_BYTE; im.allocate(); im.format = GL_RGBA; /* switch (in->dim->get(2)) { case 4: im.format = GL_RGBA; break; default: RAISE("you shouldn't see this error message."); } */ } GRID_FLOW { uint8 *buf = (uint8 *)m_pixBlock.image.data; /*!@#$ it would be nice to skip the bitpacking when we can */ long sxc = in->dim->prod(1); long sx = in->dim->v[1]; long sy = in->dim->v[0]; if (yflip) {for (long y= in->dex/sxc; n; data+=sxc, n-=sxc, y++) bit_packing->pack(sx,data,buf+y*sxc);} else {for (long y=sy-1-in->dex/sxc; n; data+=sxc, n-=sxc, y--) bit_packing->pack(sx,data,buf+y*sxc);} } GRID_END \end class { install("#to_pix",2,0); // outlets are 0 because GEM makes its own outlet instead add_creator("#export_pix"); GridToPixHelper::real_obj_setupCallback(fclass->bfclass); } void GridToPixHelper::obj_setupCallback(t_class *) {} void GridToPixHelper::startRendering() {boss->m_pixBlock.newimage = 1;} void GridToPixHelper::render(GemState *state) {state->image = &boss->m_pixBlock;} //------------------------------------------------------------------------ struct GridFromPix; struct GridFromPixHelper : GemPixObj { GridFromPix *boss; CPPEXTERN_HEADER(GridFromPixHelper,GemPixObj) public: GridFromPixHelper () {} virtual void render(GemState *state); virtual bool isRunnable () {return true;} // required to keep GEM 0.9.1 (the real 0.9.1) happy }; CPPEXTERN_NEW(GridFromPixHelper) // in 0: gem (todo: auto 0 = manual mode; bang = send next frame; type = number type attr) // out 0: grid \class GridFromPix : FObject { GridFromPixHelper *helper; P bit_packing; \attr bool yflip; GridFromPix () : FObject(0,0,0,0) {RAISE("don't call this. this exists only to make GEM happy.");} GridFromPix (BFObject *bself, MESSAGE) : FObject(bself,MESSAGE2) { uint32 mask[4] = {0x0000ff,0x00ff00,0xff0000,0x000000}; bit_packing = new BitPacking(is_le(),4,4,mask); yflip = false; bself->gemself = (GemPixObj *)this; helper = new GridFromPixHelper; helper->boss = this; bself->gemself = helper; } virtual ~GridFromPix () {} void render(GemState *state) { if (!state->image) {::post("gemstate has no pix"); return;} imageStruct &im = state->image->image; if (im.format != GL_RGBA ) {::post("can't produce grid from pix format %d",im.format); return;} if (im.type != GL_UNSIGNED_BYTE) {::post("can't produce grid from pix type %d", im.type ); return;} int32 v[] = { im.ysize, im.xsize, im.csize }; GridOutlet out(this,0,new Dim(3,v)); long sxc = im.xsize*im.csize; long sy = v[0]; uint8 buf[sxc]; for (int y=0; ypack(im.xsize,data,buf); out.send(sxc,buf); } } }; void GridFromPixHelper::obj_setupCallback(t_class *) {} \end class { install("#from_pix",2,1); add_creator("#import_pix"); GridFromPixHelper::real_obj_setupCallback(fclass->bfclass); } void GridFromPixHelper::render(GemState *state) {boss->render(state);} //------------------------------------------------------------------------ void startup_gem () { \startall } /* virtual void processRGBAImage(imageStruct &image) {} virtual void processRGBImage (imageStruct &image) {} virtual void processGrayImage(imageStruct &image) {} virtual void processYUVImage (imageStruct &image) {} */