gaborarray.cc

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 2002-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Mon May 12 11:15:58 2003
00010 // commit: $Id: gaborarray.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/visx/gaborarray.cc $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00031 //
00033 
00034 #ifndef GROOVX_VISX_GABORARRAY_CC_UTC20050626084015_DEFINED
00035 #define GROOVX_VISX_GABORARRAY_CC_UTC20050626084015_DEFINED
00036 
00037 #include "gaborarray.h"
00038 
00039 #include "geom/geom.h"
00040 #include "geom/rect.h"
00041 
00042 #include "gfx/bbox.h"
00043 #include "gfx/canvas.h"
00044 #include "gfx/gxaligner.h"
00045 
00046 #include "io/ioproxy.h"
00047 #include "io/reader.h"
00048 #include "io/writer.h"
00049 
00050 #include "media/bmapdata.h"
00051 #include "media/imgfile.h"
00052 
00053 #include "rutz/error.h"
00054 #include "rutz/rand.h"
00055 #include "rutz/sfmt.h"
00056 
00057 #include "visx/gaborpatch.h"
00058 #include "visx/snake.h"
00059 
00060 #include <cstdio>
00061 
00062 #include "rutz/debug.h"
00063 GVX_DBG_REGISTER
00064 #include "rutz/trace.h"
00065 
00066 using geom::vec2i;
00067 using geom::vec2d;
00068 using geom::vec3d;
00069 
00070 using media::bmap_data;
00071 
00072 using rutz::shared_ptr;
00073 
00074 using Gfx::Bbox;
00075 using Gfx::Canvas;
00076 
00077 namespace
00078 {
00079   const int MAX_GABOR_NUMBER = 1800;
00080 
00081   void dumpFrame(shared_ptr<media::bmap_data> bmap)
00082   {
00083     GVX_TRACE("<gaborarray.cc>::dumpFrame");
00084 
00085     static int framecount = 0;
00086 
00087     char fname[256];
00088     snprintf(fname, 256, "frame_%06d.png", framecount++);
00089 
00090     media::save_image(fname, *bmap);
00091   }
00092 
00093   const int GABORARRAY_SVID = 0;
00094 }
00095 
00096 GaborArray::GaborArray(double gaborPeriod, double gaborSigma,
00097                        int foregNumber, double foregSpacing,
00098                        int sizeX, int sizeY,
00099                        double gridSpacing,
00100                        double minSpacing)
00101   :
00102   itsForegSeed(0),
00103   itsForegNumber(foregNumber),
00104   itsForegSpacing(foregSpacing),
00105   itsForegPosX(0),
00106   itsForegPosY(0),
00107 
00108   itsBackgSeed(0),
00109   itsSizeX(sizeX),
00110   itsSizeY(sizeY),
00111   itsGridSpacing(gridSpacing),
00112   itsMinSpacing(minSpacing),
00113   itsFillResolution(15.0),
00114 
00115   itsThetaSeed(0),
00116   itsPhaseSeed(0),
00117   itsThetaJitter(0.0),
00118   itsGaborPeriod(gaborPeriod),
00119   itsGaborSigma(gaborSigma),
00120   itsContrastSeed(0),
00121   itsContrastJitter(0.0),
00122 
00123   itsTotalNumber(0),
00124   itsArray(MAX_GABOR_NUMBER),
00125   itsBmap(),
00126 
00127   itsDumpingFrames(false),
00128   itsFrameDumpPeriod(20)
00129 {
00130 GVX_TRACE("GaborArray::GaborArray");
00131 
00132   setAlignmentMode(GxAligner::CENTER_ON_CENTER);
00133   setPercentBorder(0);
00134 }
00135 
00136 GaborArray::~GaborArray() throw() {}
00137 
00138 const FieldMap& GaborArray::classFields()
00139 {
00140   static const Field FIELD_ARRAY[] =
00141   {
00142     Field("foregSeed", &GaborArray::itsForegSeed, 0, 0, 20000, 1,
00143           Field::NEW_GROUP),
00144     Field("foregNumber", &GaborArray::itsForegNumber, 24, 1, 100, 1),
00145     Field("foregSpacing", &GaborArray::itsForegSpacing,
00146           45.0, 1.0, 100.0, 1.0),
00147     Field("foregPosX", &GaborArray::itsForegPosX, 0, -2048, 2048, 1),
00148     Field("foregPosY", &GaborArray::itsForegPosY, 0, -2048, 2048, 1),
00149 
00150     Field("backgSeed", &GaborArray::itsBackgSeed, 0, 0, 20000, 1),
00151     Field("sizeX", &GaborArray::itsSizeX, 512, 16, 2048, 16),
00152     Field("sizeY", &GaborArray::itsSizeY, 512, 16, 2048, 16),
00153     Field("gridSpacing", &GaborArray::itsGridSpacing, 48., 1., 200., 1.),
00154     Field("minSpacing", &GaborArray::itsMinSpacing, 36., 1., 200., 1.),
00155     Field("fillResolution", &GaborArray::itsFillResolution, 15., 1., 50., 1.),
00156 
00157     Field("thetaSeed", &GaborArray::itsThetaSeed, 0, 0, 20000, 1),
00158     Field("phaseSeed", &GaborArray::itsPhaseSeed, 0, 0, 20000, 1),
00159     Field("thetaJitter", &GaborArray::itsThetaJitter, 0.0, 0.0, 1.0, 0.01),
00160     Field("gaborPeriod", &GaborArray::itsGaborPeriod, 15.0, 1.0, 50.0, 1.0),
00161     Field("gaborSigma", &GaborArray::itsGaborSigma, 7.5, 0.5, 25.0, 0.5),
00162     Field("contrastSeed", &GaborArray::itsContrastSeed, 0, 0, 20000, 1),
00163     Field("contrastJitter", &GaborArray::itsContrastJitter, 0.0, 0.0, 2.0, 0.01),
00164 
00165     Field("dumpingFrames", &GaborArray::itsDumpingFrames,
00166           false, false, true, true, Field::BOOLEAN | Field::TRANSIENT),
00167     Field("frameDumpPeriod", &GaborArray::itsFrameDumpPeriod,
00168           20, 1, 100, 1, Field::TRANSIENT),
00169   };
00170 
00171   static FieldMap GABORARRAY_FIELDS(FIELD_ARRAY, &GxShapeKit::classFields());
00172 
00173   return GABORARRAY_FIELDS;
00174 }
00175 
00176 io::version_id GaborArray::class_version_id() const
00177 {
00178 GVX_TRACE("GaborArray::class_version_id");
00179   return GABORARRAY_SVID;
00180 }
00181 
00182 void GaborArray::read_from(io::reader& reader)
00183 {
00184 GVX_TRACE("GaborArray::read_from");
00185 
00186   readFieldsFrom(reader, classFields());
00187 
00188   reader.read_base_class("GxShapeKit", io::make_proxy<GxShapeKit>(this));
00189 }
00190 
00191 void GaborArray::write_to(io::writer& writer) const
00192 {
00193 GVX_TRACE("GaborArray::write_to");
00194 
00195   writeFieldsTo(writer, classFields(), GABORARRAY_SVID);
00196 
00197   writer.write_base_class("GxShapeKit", io::make_const_proxy<GxShapeKit>(this));
00198 }
00199 
00200 void GaborArray::saveImage(const char* filename) const
00201 {
00202 GVX_TRACE("GaborArray::saveImage");
00203 
00204   update();
00205 
00206   media::save_image(filename, *itsBmap);
00207 }
00208 
00209 void GaborArray::saveContourOnlyImage(const char* filename) const
00210 {
00211 GVX_TRACE("GaborArray::saveContourOnlyImage");
00212 
00213   updateForeg();
00214 
00215   const int npix = itsSizeX*itsSizeY;
00216 
00217   rutz::fixed_block<double> win(npix);
00218 
00219   for (int i = 0; i < npix; ++i)
00220     win[i] = 0.0;
00221 
00222   for (int i = 0; i < itsTotalNumber; ++i)
00223     {
00224       if (itsArray[i].type != GaborArrayElement::CONTOUR)
00225         continue;
00226 
00227       const double theta = geom::rad_0_2pi(itsArray[i].theta + M_PI_2);
00228 
00229       const int xcenter = int(itsArray[i].pos.x() + itsSizeX / 2.0 + 0.5);
00230       const int ycenter = int(itsArray[i].pos.y() + itsSizeY / 2.0 + 0.5);
00231 
00232       const double period = 1.5*itsForegSpacing;
00233 
00234       const GaborPatch& p =
00235         GaborPatch::lookup(itsForegSpacing/2.0, 2*M_PI/period,
00236                            theta, 0.0);
00237 
00238       // bottom left:
00239       const int x0 = xcenter - p.size() / 2;
00240       const int y0 = ycenter - p.size() / 2;
00241       // top right:
00242       const int x1 = x0 + p.size();
00243       const int y1 = y0 + p.size();
00244 
00245       for (int y = y0; y < y1; ++y)
00246         for (int x = x0; x < x1; ++x)
00247           {
00248             if (x >= 0 && x < itsSizeX && y >=0 && y < itsSizeY)
00249               win[x+y*itsSizeX] += p.at(x-x0, y-y0);
00250           }
00251     }
00252 
00253   shared_ptr<media::bmap_data> result
00254     (new media::bmap_data(vec2i(itsSizeX, itsSizeY), 8, 1));
00255 
00256   unsigned char* bytes = result->bytes_ptr();
00257 
00258   for (int k = 0; k < npix; ++k)
00259     {
00260       int val = int(win[k]*255);
00261 
00262       // Threshold anything below 128 here, so that we don't get "ghosts"
00263       // showing up from the second peaks of the gabor functions.
00264       if      (val < 128) { val = 0; }
00265       else if (val > 255) { val = 255; }
00266 
00267       *bytes++ = val;
00268     }
00269 
00270   media::save_image(filename, *result);
00271 }
00272 
00273 void GaborArray::grGetBoundingBox(Bbox& bbox) const
00274 {
00275 GVX_TRACE("GaborArray::grGetBoundingBox");
00276 
00277   bbox.drawScreenRect(vec3d::zeros(),
00278                       vec2i(itsSizeX, itsSizeY),
00279                       vec2d::ones());
00280 }
00281 
00282 void GaborArray::grRender(Canvas& canvas) const
00283 {
00284 GVX_TRACE("GaborArray::grRender");
00285 
00286   update();
00287 
00288   canvas.drawPixels(*itsBmap, vec3d::zeros(), vec2d::ones());
00289 }
00290 
00291 void GaborArray::updateForeg() const
00292 {
00293 GVX_TRACE("GaborArray::updateForeg");
00294 
00295   if (itsForegSeed.ok()
00296       && itsForegNumber.ok()
00297       && itsForegSpacing.ok()
00298       && itsForegPosX.ok()
00299       && itsForegPosY.ok())
00300     return;
00301 
00302   itsTotalNumber = 0;
00303 
00304   rutz::urand urand(itsForegSeed);
00305 
00306   Snake snake(itsForegNumber, itsForegSpacing, urand);
00307 
00308   // pull in elements from the snake
00309   for (int n = 0; n < itsForegNumber; ++n)
00310     {
00311       GaborArrayElement e = snake.getElement(n);
00312       e.pos.x() += itsForegPosX;
00313       e.pos.y() += itsForegPosY;
00314 
00315       if (!tryPush(e))
00316         {
00317           throw rutz::error("foreground elements were "
00318                             "too close together!\n", SRC_POS);
00319         }
00320     }
00321 
00322   itsForegSeed.save();
00323   itsForegNumber.save();
00324   itsForegSpacing.save();
00325   itsForegPosX.save();
00326   itsForegPosY.save();
00327 
00328   itsBackgSeed.touch(); // to force a redo in updateBackg()
00329 
00330   GVX_ASSERT(itsTotalNumber == itsForegNumber);
00331 }
00332 
00333 void GaborArray::updateBackg() const
00334 {
00335 GVX_TRACE("GaborArray::updateBackg");
00336 
00337   if (itsBackgSeed.ok()
00338       && itsSizeX.ok()
00339       && itsSizeY.ok()
00340       && itsGridSpacing.ok()
00341       && itsMinSpacing.ok()
00342       && itsFillResolution.ok())
00343     return;
00344 
00345   itsTotalNumber = itsForegNumber;
00346 
00347   backgHexGrid();
00348 
00349   const int diffusionCycles = 10;
00350 
00351   rutz::urand urand(itsBackgSeed);
00352 
00353   for (int i = 0; i < diffusionCycles; ++i)
00354     {
00355       backgJitter(urand);
00356       backgFill();
00357     }
00358 
00359   int insideNumber = itsForegNumber;
00360 
00361   for (int n = 0; n < itsTotalNumber; ++n)
00362     {
00363       if (itsArray[n].type == GaborArrayElement::CONTOUR)
00364         continue;
00365 
00366       bool inside = true;
00367 
00368       for (int i = 0; i < itsForegNumber; ++i)
00369         {
00370           const int j = (i+1) % itsForegNumber;
00371 
00372           // This is the vector perpendicular to the line connecting
00373           // contour nodes i and j
00374           const double Yij = itsArray[i].pos.x() - itsArray[j].pos.x();
00375           const double Xij = itsArray[j].pos.y() - itsArray[i].pos.y();
00376 
00377           // This is the vector connecting from contour node i to the
00378           // background node
00379           const double Xin = itsArray[n].pos.x() - itsArray[i].pos.x();
00380           const double Yin = itsArray[n].pos.y() - itsArray[i].pos.y();
00381 
00382           // If the dot product of those two vectors is less than zero,
00383           // then the background node is "outside".
00384           const double vp = Xij*Xin + Yij*Yin;
00385 
00386           if (vp < 0.0) { inside = false; break; }
00387         }
00388 
00389       if (inside)
00390         {
00391           itsArray[n].type = GaborArrayElement::INSIDE;
00392           ++insideNumber;
00393         }
00394     }
00395 
00396   printf(" FOREG_NUMBER %d    PATCH_NUMBER %d    TOTAL_NUMBER %d\n",
00397          itsForegNumber.val, insideNumber, itsTotalNumber);
00398 
00399   itsBackgSeed.save();
00400   itsSizeX.save();
00401   itsSizeY.save();
00402   itsGridSpacing.save();
00403   itsMinSpacing.save();
00404   itsFillResolution.save();
00405 
00406   itsThetaSeed.touch(); // to force a redo in updateBmap()
00407 }
00408 
00409 shared_ptr<media::bmap_data> GaborArray::generateBmap(bool doTagLast) const
00410 {
00411 GVX_TRACE("GaborArray::generateBmap");
00412 
00413   const int npix = itsSizeX*itsSizeY;
00414 
00415   rutz::fixed_block<double> win(npix);
00416 
00417   for (int i = 0; i < npix; ++i)
00418     win[i] = 0.0;
00419 
00420   rutz::urand thetas(itsThetaSeed);
00421   rutz::urand phases(itsPhaseSeed);
00422   rutz::urand contrasts(itsContrastSeed);
00423 
00424   for (int i = 0; i < itsTotalNumber; ++i)
00425     {
00426       const double phi   = 2 * M_PI * phases.fdraw();
00427 //       const double phi = 0.0;
00428 
00429       const double rand_theta = 2*M_PI * thetas.fdraw();
00430 
00431       const double theta =
00432         (itsArray[i].type == GaborArrayElement::CONTOUR)
00433         ? geom::rad_0_2pi(itsThetaJitter * (rand_theta - M_PI) +
00434                           (itsArray[i].theta + M_PI_2))
00435         : rand_theta;
00436 
00437       const int xcenter = int(itsArray[i].pos.x() + itsSizeX / 2.0 + 0.5);
00438       const int ycenter = int(itsArray[i].pos.y() + itsSizeY / 2.0 + 0.5);
00439 
00440       const GaborPatch& p =
00441         GaborPatch::lookup(itsGaborSigma, 2*M_PI/itsGaborPeriod,
00442                            theta, phi);
00443 
00444       // bottom left:
00445       const int x0 = xcenter - p.size() / 2;
00446       const int y0 = ycenter - p.size() / 2;
00447       // top right:
00448       const int x1 = x0 + p.size();
00449       const int y1 = y0 + p.size();
00450 
00451       const double contrast = exp(-itsContrastJitter * contrasts.fdraw());
00452 
00453       for (int y = y0; y < y1; ++y)
00454         for (int x = x0; x < x1; ++x)
00455           {
00456             if (x >= 0 && x < itsSizeX && y >=0 && y < itsSizeY)
00457               win[x+y*itsSizeX] += contrast * p.at(x-x0, y-y0);
00458           }
00459 
00460       if (doTagLast && i == (itsTotalNumber-1))
00461         {
00462           const double outer = 0.4 * p.size();
00463           const double inner = outer - 3;
00464 
00465           for (int y = y0; y < y1; ++y)
00466             for (int x = x0; x < x1; ++x)
00467               {
00468                 if (x >= 0 && x < itsSizeX && y >=0 && y < itsSizeY)
00469                   {
00470                     const double r = sqrt((x-xcenter)*(x-xcenter) +
00471                                           (y-ycenter)*(y-ycenter));
00472 
00473                     if (r >= inner && r <= outer)
00474                       {
00475                         win[x+y*itsSizeX] = 1.0;
00476                       }
00477                   }
00478               }
00479         }
00480     }
00481 
00482   shared_ptr<media::bmap_data> result
00483     (new media::bmap_data(vec2i(itsSizeX, itsSizeY), 8, 1));
00484 
00485   unsigned char* bytes = result->bytes_ptr();
00486 
00487   bool clip = false;
00488 
00489   for (int k = 0; k < npix; ++k)
00490     {
00491       int val = int((win[k]+1.0)/2.0*255);
00492 
00493       if      (val < 0)   { clip = true; val = 0; }
00494       else if (val > 255) { clip = true; val = 255; }
00495 
00496       GVX_ASSERT(val >= 0);
00497       GVX_ASSERT(val <= 255);
00498 
00499       *bytes++ = val;
00500     }
00501 
00502   if (clip)
00503     printf("warning: some values were clipped\n");
00504 
00505   return result;
00506 }
00507 
00508 void GaborArray::updateBmap() const
00509 {
00510 GVX_TRACE("GaborArray::updateBmap");
00511 
00512   if (itsThetaSeed.ok()
00513       && itsPhaseSeed.ok()
00514       && itsThetaJitter.ok()
00515       && itsGaborPeriod.ok()
00516       && itsGaborSigma.ok()
00517       && itsContrastSeed.ok()
00518       && itsContrastJitter.ok())
00519     return;
00520 
00521   itsBmap = generateBmap(false);
00522 
00523   itsThetaSeed.save();
00524   itsPhaseSeed.save();
00525   itsThetaJitter.save();
00526   itsGaborPeriod.save();
00527   itsGaborSigma.save();
00528   itsContrastSeed.save();
00529   itsContrastJitter.save();
00530 }
00531 
00532 void GaborArray::update() const
00533 {
00534 GVX_TRACE("GaborArray::update");
00535 
00536   updateForeg();
00537 
00538   updateBackg();
00539 
00540   updateBmap();
00541 }
00542 
00543 bool GaborArray::tryPush(const GaborArrayElement& e) const
00544 {
00545   if (tooClose(e.pos, -1)) return false;
00546 
00547   if (itsTotalNumber >= MAX_GABOR_NUMBER)
00548     {
00549       throw rutz::error(rutz::sfmt(" More than %d elements!\n",
00550                                    MAX_GABOR_NUMBER), SRC_POS);
00551     }
00552 
00553   itsArray[itsTotalNumber++] = e;
00554 
00555   // this double call is on purpose so that the added elements don't fly by
00556   // quite so quickly in the resulting movie
00557   if (itsDumpingFrames)
00558     {
00559       shared_ptr<media::bmap_data> bmap = generateBmap(true);
00560 
00561       dumpFrame(bmap);
00562       dumpFrame(bmap);
00563     }
00564 
00565   return true;
00566 }
00567 
00568 bool GaborArray::tooClose(const vec2d& v, int except) const
00569 {
00570   double minSpacingSqr = itsMinSpacing*itsMinSpacing;
00571 
00572   for (int n = 0; n < itsTotalNumber; ++n)
00573     {
00574       const double dx = itsArray[n].pos.x() - v.x();
00575       const double dy = itsArray[n].pos.y() - v.y();
00576 
00577       if (dx*dx+dy*dy <= minSpacingSqr && n != except)
00578         return true;
00579     }
00580 
00581   return false;
00582 }
00583 
00584 void GaborArray::backgHexGrid() const
00585 {
00586 GVX_TRACE("GaborArray::backgHexGrid");
00587 
00588   // lay down a hexagonal grid of elements
00589 
00590   const double dx = itsGridSpacing;
00591   const double dy = sqrt(3.0) * itsGridSpacing / 2.0;
00592 
00593   const int nx = int((itsSizeX - itsMinSpacing) / dx - 0.5);
00594   const int ny = int((itsSizeY - itsMinSpacing) / dy);
00595 
00596   double y = -0.5 * (ny-1) * dy;
00597 
00598   for (int j = 0; j < ny; ++j, y += dy)
00599     {
00600       double x = -0.5 * (nx-1) * dx - 0.25 * dx;
00601 
00602       // this is a hexagonal grid, so every other row is staggered by half
00603       // a step in the x direction
00604       if (j%2) x += 0.5*dx;
00605 
00606       for (int i = 0; i < nx; ++i, x += dx)
00607         {
00608           tryPush(GaborArrayElement(x, y, 0.0, GaborArrayElement::OUTSIDE));
00609         }
00610     }
00611 }
00612 
00613 void GaborArray::backgFill() const
00614 {
00615 GVX_TRACE("GaborArray::backgFill");
00616 
00617   const double dx = itsMinSpacing / itsFillResolution;
00618 
00619   const double halfX = 0.5 * itsSizeX;
00620   const double halfY = 0.5 * itsSizeY;
00621 
00622   for (double x = -halfX; x <= halfX; x += dx)
00623     for (double y = -halfY; y <= halfY; y += dx)
00624       {
00625         tryPush(GaborArrayElement(x, y, 0.0, GaborArrayElement::OUTSIDE));
00626       }
00627 
00628   const double spacing = sqrt(2.0*itsSizeX*itsSizeY/(sqrt(3.0)*itsTotalNumber));
00629   printf(" %d elements, ave spacing %f\n", itsTotalNumber, spacing);
00630 }
00631 
00632 void GaborArray::backgJitter(rutz::urand& urand) const
00633 {
00634 GVX_TRACE("GaborArray::backgJitter");
00635 
00636   const double jitter = (itsMinSpacing/16.0);
00637 
00638   const int backgroundIters = 1000;
00639 
00640   const double halfX = 0.5 * itsSizeX;
00641   const double halfY = 0.5 * itsSizeY;
00642 
00643   for (int niter = 0; niter < backgroundIters; ++niter)
00644     {
00645       for (int n = 0; n < itsTotalNumber; ++n)
00646         {
00647           if (itsArray[n].type == GaborArrayElement::CONTOUR)
00648             continue;
00649 
00650           vec2d v;
00651           v.x() = itsArray[n].pos.x() + jitter*(urand.fdraw_range(-1.0, 1.0));
00652           v.y() = itsArray[n].pos.y() + jitter*(urand.fdraw_range(-1.0, 1.0));
00653 
00654           if (v.x() < -halfX) v.x() += itsSizeX;
00655           if (v.x() >  halfX) v.x() -= itsSizeX;
00656           if (v.y() < -halfY) v.y() += itsSizeY;
00657           if (v.y() >  halfY) v.y() -= itsSizeY;
00658 
00659           if (!tooClose(v, n))
00660             {
00661               itsArray[n].pos = v;
00662             }
00663         }
00664 
00665       if (itsDumpingFrames &&
00666           niter % itsFrameDumpPeriod == 0)
00667         {
00668           shared_ptr<media::bmap_data> bmap = generateBmap(true);
00669           dumpFrame(bmap);
00670         }
00671     }
00672 }
00673 
00674 static const char __attribute__((used)) vcid_groovx_visx_gaborarray_cc_utc20050626084015[] = "$Id: gaborarray.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00675 #endif // !GROOVX_VISX_GABORARRAY_CC_UTC20050626084015_DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:42 2008 by Doxygen version 1.5.5.