summaryrefslogtreecommitdiffstats
path: root/rasodmg/test/test_polygon.cc
diff options
context:
space:
mode:
Diffstat (limited to 'rasodmg/test/test_polygon.cc')
-rw-r--r--rasodmg/test/test_polygon.cc951
1 files changed, 951 insertions, 0 deletions
diff --git a/rasodmg/test/test_polygon.cc b/rasodmg/test/test_polygon.cc
new file mode 100644
index 0000000..bee92bc
--- /dev/null
+++ b/rasodmg/test/test_polygon.cc
@@ -0,0 +1,951 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community 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 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community 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 rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_polygon.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+ */
+
+#include "mymalloc/mymalloc.h"
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+extern "C" {
+ #include "tiffio.h"
+}
+
+#include <iostream>
+#include <vector>
+
+using std::vector;
+using std::iterator;
+
+#include <stdio.h>
+#include <math.h>
+#include <ctype.h>
+#if defined(SOLARIS)
+#include <strings.h>
+#else
+#include <string.h>
+#endif
+
+#include "rasodmg/polygon.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/marray.hh"
+#include "rasodmg/oqlquery.hh"
+#include "rasodmg/fastscale.hh"
+#include "raslib/basetype.hh"
+#include "raslib/mitera.hh"
+#include "raslib/shhopt.h"
+#include "rasodmg/ref.hh"
+#include "conversion/tiff.hh"
+
+#include "cmlinterpreter.hh"
+#include "cmloption.hh"
+#include "cmlerror.hh"
+
+// global limits
+static const int MYSTRINGSIZE = 256;
+static const int SUCCES = 0;
+static const int FAILED = 1;
+
+// global variable used in this program
+r_Database db;
+r_Transaction ta;
+r_Float rScale;
+char* rBgr=NULL;
+r_Polygon poly;
+
+// default values & constants
+static const char* DefaultSrv = "localhost";
+static const char* DefaultPort = "7001";
+static const char* DefaultDb = "RASBASE";
+static const char* DefaultUsr = "rasguest";
+static const char* DefaultPasswd = "rasguest";
+static const r_Float DefaultScale = 1.;
+
+
+
+
+// parameters of this program
+CmlInterpreter cmlInter;
+CmlStringOption cmlSrv('s',"server", "srv-name", "name of machine running RasDaMan manager. Default: localhost");
+CmlStringOption cmlPort(0,"port", "nnnn", "port number used by RasDaMan manager. Default: 7001");
+CmlStringOption cmlDb('d',"database", "db-name", "name of database. Default: RASBASE).");
+CmlStringOption cmlUsr(0, "user", "user-name", "name of user. Default rasguest");
+CmlStringOption cmlPasswd(0,"passwd", "user-passwd", "password of user. Default rasguest");
+CmlStringOption cmlColl('c',"collname", "coll-name", "name of collection. Mandatory");
+CmlStringOption cmlDomain('r',"domain", "domain", "domain to be retrieved (e.g. \"[1000:8000,5000:10000]\"). Mandatory");
+CmlStringOption cmlScale('f',"scale", "factor", "scale factor applied to domain. Default 1");
+CmlStringOption cmlFile('t',"tiffile", "file-name", "name of TIFF file written. Mandatory");
+CmlStringOption cmlPolygon('p',"polygon", "pol-desc","polygon for clipping (e.g. \"[1010,8200] [4000,8200] [3000,9800]\").");
+CmlStringOption cmlBgr('b',"background", "bgr-desc", "background of TIFF file (e.g. 0x1f).");
+CmlBoolOption cmlHelp('h',"help","print this message.");
+
+
+
+// This is a quick first try at a class for creating TIFFs stripe by stripe. It copies
+// a lot of code from class r_Conv_TIFF in conversion/tiff.cc. Ideally this at some
+// point should make use of Andreas' conversion framework.
+
+class r_TIFFStripe
+{
+public:
+ r_TIFFStripe(const char* newFileName, const r_Minterval& tiffDom);
+ void openTiff(); //open the tiff file
+ bool addArray(const r_GMarray& myArray); //write myArray to tiff file
+ void closeTiff(); //close the tiff file
+ ~r_TIFFStripe();
+private:
+ char* fileName; //filename of the tiff image
+ TIFF* tiffFile; //handler of the tiff image
+ uint16 bpp; // bits per pixel (24 for RGB)
+ uint16 bps; // bits per sample (8 for RGB)
+ unsigned long typeSize; // size of base type, will be retrieved with r_Base_Type::size()
+ uint32 width; // image width
+ uint32 height; //image height
+ char* scanLine; // buffer for scanLine to be written to file
+ uint32 tiffRow; // row's no of tiff image
+};
+
+r_TIFFStripe::r_TIFFStripe(const char* newFileName, const r_Minterval& tiffDom)
+ : bpp(8), bps(8), typeSize(1), tiffRow(0), fileName(NULL), tiffFile(NULL), scanLine(NULL)
+{
+ fileName = strdup(newFileName);
+ width = (uint32)(tiffDom.get_extent()[0]);
+ height = (uint32)(tiffDom.get_extent()[1]);
+ // copied this formula from Andreas, do not fully get it. 31 seems to be an internal
+ // buffer for tifflib and >> 5 together with uint32 instead of char seems to be used
+ // to get the correct number of chars as oppose to bits.
+
+ //allocate the buffer
+ scanLine = (char*)mymalloc(width*typeSize);
+}
+
+void
+r_TIFFStripe::openTiff()
+{
+ uint16 cmap[256]; // Colour map (for greyscale images)
+
+ tiffFile = TIFFOpen(fileName, "w");
+
+ // These fields are written to the file by TIFFWriteDirectory, which is automatically
+ // called by TIFFClose and TIFFFlush
+
+ TIFFSetField(tiffFile, TIFFTAG_ARTIST, "RasDaMan");
+ TIFFSetField(tiffFile, TIFFTAG_DOCUMENTNAME, "Image");
+ TIFFSetField(tiffFile, TIFFTAG_SOFTWARE, "RasDaMan");
+ //TIFFSetField(tiffFile, TIFFTAG_SUBFILETYPE, (uint32)0);
+ TIFFSetField(tiffFile, TIFFTAG_IMAGEWIDTH, width);
+ TIFFSetField(tiffFile, TIFFTAG_IMAGELENGTH, height);
+ TIFFSetField(tiffFile, TIFFTAG_BITSPERSAMPLE, bps);
+ // UNIX doesn't mind which fill-order. NT only understands this one.
+ TIFFSetField(tiffFile, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
+ // problem: LZW is no longer supported in current versions of libtiff.
+ TIFFSetField(tiffFile, TIFFTAG_COMPRESSION, (uint16)COMPRESSION_NONE);
+ TIFFSetField(tiffFile, TIFFTAG_ORIENTATION, (uint16)ORIENTATION_TOPLEFT);
+
+ // Format-dependent tags, currently support only 8bit grey images
+ TIFFSetField(tiffFile, TIFFTAG_PHOTOMETRIC, (uint16)PHOTOMETRIC_PALETTE);
+ TIFFSetField(tiffFile, TIFFTAG_SAMPLESPERPIXEL, (uint16)1);
+ TIFFSetField(tiffFile, TIFFTAG_PLANARCONFIG, (uint16)PLANARCONFIG_CONTIG);
+ // TIFFSetField(tiffFile, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiffFile, (uint32)-1));
+ TIFFSetField(tiffFile, TIFFTAG_ROWSPERSTRIP, (uint32)1);
+ //TIFFSetField(tiffFile, TIFFTAG_MINSAMPLEVALUE, (uint16)0);
+ //TIFFSetField(tiffFile, TIFFTAG_MAXSAMPLEVALUE, (uint16)255);
+ TIFFSetField(tiffFile, TIFFTAG_RESOLUTIONUNIT, (uint16)RESUNIT_INCH);
+
+ // This will have to be adapted!
+ TIFFSetField(tiffFile, TIFFTAG_XRESOLUTION, (float)90.0);
+ TIFFSetField(tiffFile, TIFFTAG_YRESOLUTION, (float)90.0);
+ TIFFSetField(tiffFile, TIFFTAG_XPOSITION, (float)0.0);
+ TIFFSetField(tiffFile, TIFFTAG_YPOSITION, (float)0.0);
+
+ // build the colour-map (greyscale, i.e. all 3 components identical)
+ // TIFF needs 16 bit values for this (--> tools/tiffdither.c)
+ for (int i=0; i<256; i++) cmap[i] = (uint16)(i*((1L << 16) - 1)/255);
+ TIFFSetField(tiffFile, TIFFTAG_COLORMAP, cmap, cmap, cmap);
+}
+
+bool
+r_TIFFStripe::addArray(const r_GMarray& myArray)
+{
+ // here we write the r_GMarray we get line by line into the TIFF. We
+ // assume that the width of myArray (width = [0] r_Sinterval)
+ // corresponds to the width of the whole TIFF.
+
+ unsigned long imageHeight = myArray.spatial_domain().get_extent()[1];
+ unsigned long imageWidth = myArray.spatial_domain().get_extent()[0];
+
+ if(imageWidth != width)
+ {
+ cout << "Error Tiff file \"" << fileName << "\" initialised for "
+ << width << ", not for " << imageWidth << " !" << endl;
+ return false;
+ }
+
+ const char* linePtr = myArray.get_array(); // points to myArray's data
+ char* scanLinePtr = (char*)scanLine;
+
+
+ for (int row = 0; row < imageHeight; row++) {
+ // copy data (and transpose)
+ for (int col=0; col < imageWidth; col++) {
+ for(int i=0; i<typeSize; i++) {
+ *scanLinePtr++ = *(linePtr + col*imageHeight*typeSize + row*typeSize + i);
+ }
+ // not really fast and does not work for all types! Good enough for now.
+ }
+ if(TIFFWriteScanline(tiffFile, (tdata_t)scanLine, tiffRow++, 0) < 0)
+ {
+ // error
+ cerr << "Error writing line into file " << fileName << "." << endl;
+ return false;
+ }
+ memset(scanLine, 0, imageWidth*typeSize);
+ scanLinePtr = (char*)scanLine;
+ }
+
+ return true;
+}
+
+void
+r_TIFFStripe::closeTiff()
+{
+ TIFFClose(tiffFile);
+}
+
+r_TIFFStripe::~r_TIFFStripe()
+{
+ if(fileName)
+ free(fileName);
+ if(scanLine)
+ free(scanLine);
+}
+
+void
+printUsage(char* name)
+{
+ static const char* ExColl="lva";
+ static const char* ExDomain="[0:100,0:100]";
+ static const char* ExFile="lva.tif";
+
+ cout << name << " v1.0 - RasDaMan Export Utility for 2D marrays" << endl;
+ cout << "Description: Exports data with background, from RasDaMan database from a fastscale collection" << endl;
+ cout << " for a domain with a scale." << endl;
+ cout << " Returns " << SUCCES << " for succes, otherwise " << FAILED << endl;
+ cout << "Notes: If a polygon is specified, the result is a image which has data inside the polygon and"<< endl;
+ cout << " the rest is filled with background color." << endl;
+
+ cout << "Usage options:" << endl;
+ cmlInter.printHelp();
+
+ cout << "For example:" << endl;
+ cout << name << "\t" << cmlSrv.getLongFormTag() << " " << DefaultSrv << " ";
+ cout << cmlPort.getLongFormTag() << " " << DefaultPort << " ";
+ cout << cmlDb.getLongFormTag() << " " << DefaultDb << " ";
+ cout << cmlColl.getLongFormTag() << " " << ExColl << " ";
+ cout << endl << "\t\t" << cmlDomain.getLongFormTag() << " " << ExDomain << " ";
+ cout << cmlScale.getLongFormTag() << " " << DefaultScale << " ";
+ cout << cmlFile.getLongFormTag() << " " << ExFile << " ";
+ cout << endl << "\t\t" << cmlUsr.getLongFormTag() << " " << DefaultUsr << " ";
+ cout << cmlPasswd.getLongFormTag() << " " << DefaultPasswd << " ";
+ cout << endl;
+
+ cout << "Report bugs to <support@active­knowledge.com>" << endl;
+}
+
+void
+printStatus(char* name)
+{
+ cout << name << "'s parameters list:" << endl;
+ cmlInter.printStatus();
+}
+
+void
+defineParams()
+{
+ cmlInter.defineOption(&cmlSrv);
+ cmlInter.defineOption(&cmlPort);
+ cmlInter.defineOption(&cmlDb);
+ cmlInter.defineOption(&cmlUsr);
+ cmlInter.defineOption(&cmlPasswd);
+ cmlInter.defineOption(&cmlColl);
+ cmlInter.defineOption(&cmlDomain);
+ cmlInter.defineOption(&cmlScale);
+ cmlInter.defineOption(&cmlFile);
+ cmlInter.defineOption(&cmlPolygon);
+ cmlInter.defineOption(&cmlBgr);
+ cmlInter.defineOption(&cmlHelp);
+}
+
+void
+getParams()
+{
+ CmlOption* ptr=NULL;
+
+ ptr=cmlInter.getOption(&cmlSrv);
+ cmlSrv=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlPort);
+ cmlPort=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlDb);
+ cmlDb=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlUsr);
+ cmlUsr=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlPasswd);
+ cmlPasswd=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlColl);
+ cmlColl=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlDomain);
+ cmlDomain=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlScale);
+ cmlScale=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlFile);
+ cmlFile=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlPolygon);
+ cmlPolygon=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlBgr);
+ cmlBgr=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlHelp);
+ cmlHelp=*((CmlBoolOption*)ptr);
+
+ ptr=NULL;
+}
+
+bool
+parseParams(int argc, char** argv)
+{
+ try
+ {
+ defineParams();
+ cmlInter.interpretArguments(argc, argv);
+ getParams();
+ }
+ catch(CmlError& err)
+ {
+ cout << "Command Line Parsing Error:" << endl << err.getText() << endl;
+ return false;
+ }
+
+ //check rule
+ if(cmlColl.isPresent() &&
+ cmlDomain.isPresent() &&
+ cmlFile.isPresent()
+ )
+ return true;
+ else
+ {
+ cout << "Error some of mandatory arguments are missing!" << endl;
+ cout << "Please check your command line!" << endl;
+ return false;
+ }
+}
+
+bool
+fillPolygon(r_Polygon& myPoly)
+{
+
+ char* startPos = (char*)cmlPolygon.getString();
+ char* endPos=NULL;
+ int pointStrLen=0, pointNo=0;
+ char currPoint[MYSTRINGSIZE];
+ r_Point myPoint;
+
+
+ //cout << "start decoding polygon string"<< endl;
+
+ while(true)
+ {
+ strcpy(currPoint, "");
+ startPos = index(startPos, '[');
+ if(!startPos) {
+ // Did not find a closing [, that's it.
+ break;
+ }
+
+ endPos = index(startPos, ']');
+ if(!endPos) {
+ // Did not find a closing ], that's it.
+ break;
+ }
+
+ // try to add point
+ pointStrLen = endPos - startPos + 1;
+ strncpy(currPoint, startPos, pointStrLen);
+ currPoint[pointStrLen+1] = '\0';
+
+ try
+ {
+ myPoint=r_Point(currPoint);
+ myPoly.addPoint( myPoint );
+ pointNo++;
+ //cout << "-point " << pointNo << " : " << currPoint << endl;
+ }
+ catch(r_Error& err)
+ {
+ cout << "Error decoding point \"" << currPoint << "\" from polygon string \""
+ << cmlPolygon.getString() << " !" << endl;
+ return false;
+ }
+ startPos += pointStrLen;
+ }
+
+ if(!pointNo)
+ {
+ cout << "Error no points found, while decoding polygon string \"" << cmlPolygon.getString() << "\" !" << endl;
+ return false;
+ }
+
+ //cout << "end decoding"<< endl;
+
+ myPoly.close();
+
+ return true;
+}
+
+bool
+parseBgr()
+{
+ static char hexval[]= { 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f,
+ };
+ static char hexfig[]= { '0', '1', '2', '3',
+ '4', '5', '6', '7',
+ '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f',
+ '\0'};
+
+ static r_Bytes sizeBgrMin=2, sizeHexFig=strlen(hexfig);
+ char* pBgr=(char*)cmlBgr.getString();
+ r_Bytes sizeBgr=strlen(pBgr), sizerBgr=0, indexFigure=0, indexHexFig=0;
+
+ if(sizeBgr <= sizeBgrMin)
+ {
+ cout << "Error decoding background \"" << pBgr << "\", is not a hex string !" << endl;
+ return false;
+ }
+
+ if (pBgr[0] !='0' || (pBgr[1] != 'x' && pBgr[1]!='X'))
+ {
+ cout << "Error decoding background \"" << pBgr << "\", 0x or 0X is missing !" << endl;
+ return false;
+ }
+
+ if(sizeBgr%sizeBgrMin)
+ {
+ sizerBgr=(sizeBgr-sizeBgrMin+1)/sizeBgrMin;
+ }
+ else
+ sizerBgr=(sizeBgr-sizeBgrMin)/sizeBgrMin;
+
+ rBgr=new char [sizeBgr+1];
+ memset(rBgr,'\0', sizeBgr+1);
+
+ //skip tag 0x/0X
+ pBgr+=sizeBgrMin;
+
+ while (*pBgr)
+ {
+ //check figure
+ indexHexFig=0;
+ while(indexHexFig<sizeHexFig)
+ {
+ if (tolower(*pBgr) == hexfig[indexHexFig])
+ break;
+ indexHexFig++;
+ }
+
+ if(indexHexFig>=sizeHexFig)
+ {
+ cout << "Error decoding background \"" << pBgr << "\", \"" << *pBgr << "\" is no a hex value !" << endl;
+ delete[] rBgr;
+ return false;
+ }
+
+ //set value figure
+ if(indexFigure%sizeBgrMin)
+ {
+#if defined(LITTLE_ENDIAN)
+ rBgr[indexFigure/sizeBgrMin]=rBgr[indexFigure/sizeBgrMin] * 16 + hexval[indexHexFig];
+#else
+ rBgr[indexFigure/sizeBgrMin]=rBgr[indexFigure/sizeBgrMin]+ hexval[indexHexFig] * 16;
+#endif
+ }
+ else
+ rBgr[indexFigure/sizeBgrMin]=hexval[indexHexFig];
+
+ //advance
+ pBgr++;
+ indexFigure++;
+ }
+
+ return true;
+}
+
+
+bool
+detectParams()
+{
+ r_Long rPort=0;
+
+ // server name
+ if(!cmlSrv.isPresent())
+ cmlSrv.setValue(DefaultSrv);
+
+ // server port
+ if(!cmlPort.isPresent())
+ cmlPort.setValue(DefaultPort);
+ else
+ {
+ try
+ {
+ rPort=cmlPort.getLong();
+ }
+ catch(CmlError& err)
+ {
+ cout << "Error decoding " << cmlPort.getLongForm() << " \"" << cmlPort.getString()
+ << "\" isn't a number!" << endl;
+ return false;
+ }
+ if (rPort <= 0.)
+ {
+ cout << "Error decoding " << cmlPort.getLongForm() << " \"" << cmlPort.getString()
+ << "\" is negative or zero !" << endl;
+ return false;
+ }
+ }
+
+ // database name
+ if(!cmlDb.isPresent())
+ cmlDb.setValue(DefaultDb);
+
+ // user name
+ if(!cmlUsr.isPresent())
+ cmlUsr.setValue(DefaultUsr);
+
+ // user passord
+ if(!cmlPasswd.isPresent())
+ cmlPasswd.setValue(DefaultPasswd);
+
+ // scale factor
+ if(!cmlScale.isPresent())
+ rScale=DefaultScale;
+ else
+ {
+ try
+ {
+ rScale=cmlScale.getDouble();
+ }
+ catch(CmlError& err)
+ {
+ cout << "Error decoding " << cmlScale.getLongForm() << " \"" << cmlScale.getString()
+ << "\" isn't a number!" << endl;
+ return false;
+ }
+ if (rScale <= 0.)
+ {
+ cout << "Error decoding " << cmlScale.getLongForm() << " \"" << cmlScale.getString()
+ << "\" is negative or zero !" << endl;
+ return false;
+ }
+ }
+
+ // collection name
+ // nothing to check here
+
+ // collection domain
+ try
+ {
+ r_Minterval test(cmlDomain.getString());
+ }
+ catch(r_Error& err)
+ {
+ cout << "Error while decoding " << cmlDomain.getLongForm() << " \"" << cmlDomain.getString() << "\" !" << endl;
+ cout << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ return false;
+ }
+
+ // filename
+ //nothing to be checked here
+
+ // polygon
+ if(cmlPolygon.isPresent())
+ {
+ if(!fillPolygon(poly))
+ return false;
+
+ //FIXME
+ //is convex?
+ if(poly.detectPolygonType()!=r_Polygon::CONVEX)
+ {
+ cout << "We support only simple convex polygon now. Please check your polygon !" << endl;
+ return false;
+ }
+ }
+
+ // background
+ if(cmlBgr.isPresent())
+ return parseBgr();
+
+ return true;
+}
+
+
+
+bool
+exportData()
+{
+
+ // At the moment we do just a quick check for the TIFF writing using r_Conversion.
+ // Now we do a query and store the result as a TIFF using r_Conversion.
+
+ // Ok, the whole TIFF conversion thing is done below. Now let's get an
+ // array from RasDaMan here.
+ r_Ref<r_GMarray> mddObj;
+ r_Fast_Base_Scale *scaler=NULL;
+ r_Minterval trimDom(cmlDomain.getString());
+ r_Minterval tiffDom, currDom, insertionUnit(2), clipDom(2);
+ r_Minterval collDom;
+ r_Point trimExtent;
+ r_Polygon myPoly;
+
+ // 5 MB buffer for spooling images
+ r_ULong bufSize = 5 * 1024 * 1024;
+ //size of base type
+ r_Bytes typeSize = 1;
+ // no of scan lines in buffer
+ r_ULong numScanLineInBuf=0;
+ //tiff strip object
+ r_TIFFStripe* myTiff=NULL;
+
+ try
+ {
+ db.set_servername(cmlSrv.getString(), cmlPort.getLong());
+ db.set_useridentification(cmlUsr.getString(), cmlPasswd.getString());
+ db.open(cmlDb.getString());
+
+ try
+ {
+ ta.begin( r_Transaction::read_only );
+ scaler = new r_Fast_Scale<r_Char>(cmlColl.getString());
+ collDom = scaler->get_full_domain();
+ }
+ catch( r_Error& errorObj )
+ {
+ cout << "Error while initializing collection " << cmlColl.getString() << " !" << endl;
+ cout << "Error " << errorObj.get_errorno() << " : " << errorObj.what() << endl;
+ ta.abort();
+ db.close();
+ if(rBgr)
+ {
+ delete[] rBgr;
+ rBgr=NULL;
+ }
+ return false;
+ }
+
+ if (!collDom.covers(trimDom))
+ {
+ cout << "Error, the requested domain " << trimDom << " is not in the collection domain " << collDom << " !" << endl;
+
+ if(scaler)
+ {
+ delete scaler;
+ scaler=NULL;
+ }
+
+ ta.abort();
+ db.close();
+
+ if(rBgr)
+ {
+ delete[] rBgr;
+ rBgr=NULL;
+ }
+
+ return false;
+ }
+
+ // Ok, now here we split the domain in stripes. We take a roughly 5 MB buffer. It
+ // is calculated using the original domain of the area to be retrieved and scale^2
+ // to calculate the memory used without calculating the domains back and forth.
+
+ insertionUnit[0] = trimDom[0]; // we take the whole width of the image.
+
+ trimExtent=trimDom.get_extent();
+ numScanLineInBuf = bufSize / ( typeSize * trimExtent[0] * rScale * rScale);
+ numScanLineInBuf = numScanLineInBuf > trimExtent[1] ? trimExtent[1] : numScanLineInBuf;
+
+ if(numScanLineInBuf < 1) //if numScanLine is 0 as result of division
+ numScanLineInBuf=1;
+
+ insertionUnit[1] = r_Sinterval((r_Range)0, (r_Range)(numScanLineInBuf - 1));
+
+ try {
+ scaler->get_scaled_domain(trimDom, tiffDom, rScale);
+ }
+ catch( r_Error& errorObj ){
+ cout << "Error while getting the scaled domain !" << endl;
+ cout << "Error " << errorObj.get_errorno() << " : " << errorObj.what() << endl;
+ if(scaler)
+ {
+ delete scaler;
+ scaler=NULL;
+ }
+
+ ta.abort();
+ db.close();
+
+ if(rBgr)
+ {
+ delete[] rBgr;
+ rBgr=NULL;
+ }
+ return false;
+ }
+
+
+ if(cmlPolygon.isPresent())
+ {
+ // we scale the polygon according to the scale factor
+ cout << "Defined Polygon: " << poly << endl;
+ poly.scale(collDom.get_origin(), rScale);
+ cout << "Scaled Polygon: " << poly << endl;
+ }
+
+ myTiff = new r_TIFFStripe(cmlFile.getString(), tiffDom);
+ myTiff->openTiff();
+
+ cout << "Retrieving area " << trimDom << " of object " << cmlColl.getString()
+ << " with scale factor " << rScale << "." << endl;
+ cout << "Retrieving units of shape " << insertionUnit << "." << endl;
+ cout << "Tiff Image area " << tiffDom << endl;
+
+ r_MiterArea myIter(&insertionUnit, &trimDom);
+ while( !myIter.isDone() ) {
+ currDom = myIter.nextArea();
+ cout << " Getting " << currDom << " with scale factor " << rScale << "." << endl;
+ try {
+ mddObj = scaler->get_scaled_object(currDom, rScale, 1);
+ }
+ catch( r_Error& errorObj )
+ {
+ cout << "Error while getting the scaled domain !" << endl;
+ cout << "Error " << errorObj.get_errorno() << " : " << errorObj.what() << endl;
+ if(myTiff)
+ {
+ myTiff->closeTiff();
+ delete myTiff;
+ myTiff=NULL;
+ }
+ if(scaler)
+ {
+ delete scaler;
+ scaler=NULL;
+ }
+
+ ta.abort();
+ db.close();
+
+ if(rBgr)
+ {
+ delete[] rBgr;
+ rBgr=NULL;
+ }
+ return false;
+ }
+
+ // The polygonal cutout is currently not done. We will need a scale function with the
+ // same semantics as fastscale for it to work. Then the polygon can be specified in
+ // original pixel coordinates and will be scaled according to the scaling factor.
+
+ if(cmlPolygon.isPresent()) {
+ // we clip the polygon it according to the scaled domain retrieved by r_Fast_Scale
+
+ // original polygon is modified by clip function
+ myPoly=poly;
+
+ scaler->get_scaled_domain(currDom, clipDom, rScale);
+ cout << "Domain for clipping: " << clipDom << endl;
+
+ //FIXME
+ //quick hack for test_polygon because get_scaled_image
+ //returns the clipDom translated in currDom.get_origin()
+ mddObj->set_spatial_domain(clipDom);
+
+ myPoly.clip(clipDom);
+ cout << "Clipped polygon: " << myPoly << endl;
+
+
+ // we would have to transpose it here. This is done by the TIFF conversion.
+
+ // REALLY IMPORTANT: The TA has to be open here! Otherwise neither
+ // type info nor domain can be read.
+ try
+ {
+ myPoly.fillMArray(*mddObj, false, rBgr);
+ }
+ catch(r_Error& err)
+ {
+ cout << "Error size of background " << strlen(rBgr) << " bytes "
+ << " is different from mdd base type size " << mddObj->get_type_length()
+ << " bytes !" << endl;
+ mddObj.destroy();
+ throw err;
+ }
+ }//end if(usePolygon)
+
+ // Ok, now we use our r_TIFFStripe class here
+ if(!myTiff->addArray(*mddObj))
+ {
+ if(myTiff)
+ {
+ myTiff->closeTiff();
+ delete myTiff;
+ myTiff=NULL;
+ }
+
+ if(rBgr)
+ {
+ delete[] rBgr;
+ rBgr=NULL;
+ }
+
+ if(scaler)
+ {
+ delete scaler;
+ scaler=NULL;
+ }
+
+ mddObj.destroy();
+
+ ta.abort();
+ db.close();
+
+ return false;
+ }
+ mddObj.destroy();
+ }//end while
+
+ delete scaler;
+ scaler=NULL;
+
+ myTiff->closeTiff();
+ delete myTiff;
+ myTiff=NULL;
+
+ delete[] rBgr;
+ rBgr=NULL;
+
+ ta.commit();
+ db.close();
+ }
+ catch(r_Error & errObj)
+ {
+ cout << "Error while exporting the data !" << endl;
+ cout << "Error " << errObj.get_errorno() << " : " << errObj.what() << endl;
+ if(scaler)
+ {
+ delete scaler;
+ scaler=NULL;
+ }
+
+ ta.abort();
+ db.close();
+
+ if(rBgr)
+ {
+ delete[] rBgr;
+ rBgr = NULL;
+ }
+ if(myTiff)
+ {
+ myTiff->closeTiff();
+ delete myTiff;
+ myTiff = NULL;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool
+processRequest(char* name)
+{
+ bool result=false;
+
+ if(detectParams())
+ {
+#if defined(RMANDEBUG)
+ printStatus(name);
+#endif
+ result=exportData();
+ }
+
+ return result;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ int result=FAILED;
+
+ if(!parseParams(argc, argv))
+ printUsage(argv[0]);
+ else
+ if(cmlHelp.isPresent())
+ {
+ printUsage(argv[0]);
+ result=SUCCES;
+ }
+ else
+ if(processRequest(argv[0]))
+ result=SUCCES;
+ else
+ printUsage(argv[0]);
+ return result;
+
+}
+