summaryrefslogtreecommitdiffstats
path: root/conversion
diff options
context:
space:
mode:
authorConstantin Jucovschi <cj@ubuntu.localdomain>2009-04-24 07:20:22 -0400
committerConstantin Jucovschi <cj@ubuntu.localdomain>2009-04-24 07:20:22 -0400
commit8f27e65bddd7d4b8515ce620fb485fdd78fcdf89 (patch)
treebd328a4dd4f92d32202241b5e3a7f36177792c5f /conversion
downloadrasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.zip
rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.gz
rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.xz
Initial commitv8.0
Diffstat (limited to 'conversion')
-rw-r--r--conversion/Makefile.am37
-rw-r--r--conversion/bmp.cc990
-rw-r--r--conversion/bmp.hh91
-rw-r--r--conversion/convertor.cc405
-rw-r--r--conversion/convertor.hh252
-rw-r--r--conversion/convfactory.cc189
-rw-r--r--conversion/convfactory.hh64
-rw-r--r--conversion/csv.cc222
-rw-r--r--conversion/csv.hh93
-rw-r--r--conversion/dem.cc894
-rw-r--r--conversion/dem.hh187
-rw-r--r--conversion/des.cc118
-rw-r--r--conversion/des.h67
-rw-r--r--conversion/ecw.cc339
-rw-r--r--conversion/ecw.hh78
-rw-r--r--conversion/ecwmemfs.cc157
-rw-r--r--conversion/ecwmemfs.hh84
-rw-r--r--conversion/graphic.cc148
-rw-r--r--conversion/graphic.h90
-rw-r--r--conversion/hdf.cc386
-rw-r--r--conversion/hdf.hh104
-rw-r--r--conversion/image.cc1040
-rw-r--r--conversion/image.h226
-rw-r--r--conversion/int16.cc874
-rw-r--r--conversion/int16.hh205
-rw-r--r--conversion/jpeg.cc530
-rw-r--r--conversion/jpeg.hh84
-rw-r--r--conversion/memfs.c421
-rw-r--r--conversion/memfs.cc421
-rw-r--r--conversion/memfs.h85
-rw-r--r--conversion/memfs.hh85
-rw-r--r--conversion/nitf.cc702
-rw-r--r--conversion/nitf.h165
-rw-r--r--conversion/ntf.cc218
-rw-r--r--conversion/ntf.hh80
-rw-r--r--conversion/png.cc597
-rw-r--r--conversion/png.hh79
-rw-r--r--conversion/res.cc110
-rw-r--r--conversion/res.h64
-rw-r--r--conversion/test/Makefile142
-rw-r--r--conversion/test/test_bmp.cc83
-rw-r--r--conversion/test/test_convertor.cc276
-rw-r--r--conversion/test/test_hdf.cc309
-rw-r--r--conversion/test/test_jpeg.cc295
-rw-r--r--conversion/test/test_png.cc237
-rw-r--r--conversion/test/test_vff.cc169
-rw-r--r--conversion/text.cc138
-rw-r--r--conversion/text.h86
-rw-r--r--conversion/tiff.cc653
-rw-r--r--conversion/tiff.hh145
-rw-r--r--conversion/tor.cc230
-rw-r--r--conversion/tor.hh82
-rw-r--r--conversion/utilities.cc109
-rw-r--r--conversion/utilities.h35
-rw-r--r--conversion/vff.cc797
-rw-r--r--conversion/vff.hh138
56 files changed, 14905 insertions, 0 deletions
diff --git a/conversion/Makefile.am b/conversion/Makefile.am
new file mode 100644
index 0000000..8da362d
--- /dev/null
+++ b/conversion/Makefile.am
@@ -0,0 +1,37 @@
+# -*-Makefile-*- (for Emacs)
+#
+# 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>.
+#
+# MAKEFILE FOR:
+# module conversion
+#
+#
+# COMMENTS:
+#
+##################################################################
+
+noinst_LIBRARIES=libconversion.a
+libconversion_a_SOURCES= convertor.cc convfactory.cc tiff.cc hdf.cc png.cc jpeg.cc \
+ csv.cc bmp.cc vff.cc tor.cc dem.cc ecw.cc memfs.cc \
+ convertor.hh convfactory.hh tiff.hh hdf.hh png.hh jpeg.hh \
+ csv.hh bmp.hh vff.hh tor.hh dem.hh ecw.hh memfs.hh \
+ ntf.hh
diff --git a/conversion/bmp.cc b/conversion/bmp.cc
new file mode 100644
index 0000000..9995943
--- /dev/null
+++ b/conversion/bmp.cc
@@ -0,0 +1,990 @@
+/*
+* 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: bmp.cc
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_BMP
+ *
+ * COMMENTS:
+ * Provides functions to convert data to BMP and back.
+ *
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <string.h>
+#include <new>
+
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/parseparams.hh"
+#include "conversion/bmp.hh"
+#include "conversion/memfs.hh"
+
+
+// Some Windows-structs, redefined for platform-independent use.
+typedef struct {
+ unsigned short type;
+ r_ULong size;
+ unsigned short res0;
+ unsigned short res1;
+ r_ULong offset;
+} bitmap_file_header_t;
+
+typedef struct {
+ r_ULong size;
+ r_Long width;
+ r_Long height;
+ unsigned short planes;
+ unsigned short bitCount;
+ r_ULong compression;
+ r_ULong sizeImage;
+ r_Long xpels;
+ r_Long ypels;
+ r_ULong clrUsed;
+ r_ULong clrImportant;
+} bitmap_info_header_t;
+
+typedef struct {
+ unsigned char blue;
+ unsigned char green;
+ unsigned char red;
+ unsigned char null;
+} rgb_quad_t;
+
+// Identifier of BMP data (first two bytes)
+const unsigned short BMP_IDENTIFIER=0x4d42;
+// Compression types (correspond to BI_RGB, BI_RLE8, BI_RLE4)
+const int COMPRESS_NONE=0;
+const int COMPRESS_RLE8=1;
+const int COMPRESS_RLE4=2;
+// Size of BITMAPFILEHEADER (the Windows struct)
+const int BMPFILEHEADERSIZE=sizeof(bitmap_file_header_t) - sizeof(BMP_IDENTIFIER);
+// Size of BITMAPINFOHEADER (the Windows struct)
+const int BMPINFOHEADERSIZE=sizeof(bitmap_info_header_t);
+// Total header size
+const int BMPHEADERSIZE=(BMPFILEHEADERSIZE + BMPINFOHEADERSIZE);
+
+// Shortcuts for reading and writing short and long types from/to little endian bytestreams
+#define READ_LE_SHORT(p,s) \
+ s = p[0] | (p[1] << 8); p += 2;
+#define READ_LE_LONG(p,l) \
+ l = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); p += 4;
+#define WRITE_LE_SHORT(p,s) \
+ p[0] = s & 0xff; p[1] = (s >> 8) & 0xff; p += 2;
+#define WRITE_LE_LONG(p,l) \
+ p[0] = l & 0xff; p[1] = (l >> 8) & 0xff; p[2] = (l >> 16) & 0xff; p[3] = (l >> 24) & 0xff; p += 4;
+
+
+
+void r_Conv_BMP::initBMP( void )
+{
+ memFS = NULL;
+
+ compress = 1;
+
+ if (params == NULL)
+ params = new r_Parse_Params;
+
+ params->add("compress", &compress, r_Parse_Params::param_type_int);
+}
+
+
+r_Conv_BMP::r_Conv_BMP(const char *src, const r_Minterval &interv, int tp) throw(r_Error)
+: r_Convertor(src, interv, tp)
+{
+ initBMP();
+}
+
+
+r_Conv_BMP::r_Conv_BMP(const char *src, const r_Minterval &interv, const r_Type *tp) throw(r_Error)
+: r_Convertor(src, interv, tp)
+{
+ initBMP();
+}
+
+
+r_Conv_BMP::~r_Conv_BMP(void)
+{
+ if (memFS != NULL)
+ {
+ memfs_killfs((void*)memFS);
+ delete memFS;
+ memFS=NULL;
+ }
+}
+
+
+unsigned char *r_Conv_BMP::flushLiterals(int numLit, int pixelAdd, unsigned char *dest, const unsigned char *lastLit, const unsigned char *mapColours)
+{
+ unsigned char *destPtr = dest;
+
+ while (numLit != 0)
+ {
+ // Must code literal runs of less than 3 bytes as runs
+ if (numLit < 3)
+ {
+ while (numLit > 0)
+ {
+ *destPtr++ = 1; *destPtr++ = mapColours[*lastLit];
+ lastLit += pixelAdd; numLit--;
+ }
+ }
+ else
+ {
+ int litLength=0;
+ r_Ptr align=0;
+
+ litLength = numLit; if (litLength > 255) litLength = 255;
+ *destPtr++ = 0x00; *destPtr++ = (unsigned char)litLength;
+ numLit -= litLength;
+ while (litLength > 0)
+ {
+ *destPtr++ = mapColours[*lastLit]; lastLit += pixelAdd; litLength--;
+ }
+ align = (r_Ptr)destPtr; if ((align & 1) != 0) *destPtr++ = 0;
+ }
+ }
+ return destPtr;
+}
+
+
+r_convDesc &r_Conv_BMP::convertTo( const char *options) throw(r_Error)
+{
+ void *handle=NULL;
+ bitmap_info_header_t ihead;
+ rgb_quad_t *palette = NULL;
+ int i=0, j=0;
+ int paletteSize=0, pixelSize=0;
+ int destPitch=0, pixelAdd=0, lineAdd=0;
+ int width=0, height=0;
+ r_ULong offset=0;
+ r_ULong fileSize=0;
+ unsigned char *dest=NULL, *destPtr=NULL;
+ const unsigned char *srcLine=NULL, *srcPtr=NULL;
+ unsigned char bmpHeaders[BMPHEADERSIZE];
+ unsigned char mapColours[256];
+
+ memFS = new memFSContext; handle = (void*)memFS;
+ if ((memFS == NULL) || (memfs_initfs(handle) < 0))
+ {
+ RMInit::logOut << "r_Conv_BMP::convertTo(): couldn't initialize memfs!" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+ memfs_newfile(handle);
+
+ width = (int)(desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1);
+ height = (int)(desc.srcInterv[1].high() - desc.srcInterv[1].low() + 1);
+
+ params->process(options);
+
+ ihead.size = BMPINFOHEADERSIZE;
+ ihead.width = (r_Long)width;
+ ihead.height = (r_Long)height;
+ ihead.planes = 1;
+ ihead.compression = COMPRESS_NONE;
+ ihead.xpels = 0; ihead.ypels = 0;
+
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ ihead.bitCount = 1; destPitch = ((width + 31) & ~31) >> 3; paletteSize = 2; pixelSize = 1;
+ ihead.clrUsed = 2; ihead.clrImportant = 2;
+ palette = new rgb_quad_t[2];
+ palette[0].red = 0x00; palette[0].green = 0x00; palette[0].blue = 0x00; palette[0].null = 0x00;
+ palette[1].red = 0xff; palette[1].green = 0xff; palette[1].blue = 0xff; palette[1].null = 0x00;
+ break;
+ case ctype_char:
+ {
+ ihead.bitCount = 8; destPitch = ((width + 3) & ~3); pixelSize = 1;
+ if (compress != 0) ihead.compression = COMPRESS_RLE8;
+ // Determine which colours actually appear in the image
+ memset(mapColours, 0, 256);
+ srcLine = (const unsigned char*)desc.src;
+ for (i=0; i<width*height; i++) mapColours[*srcLine++] = 1;
+ // Count distinct colours
+ paletteSize = 0;
+ for (i=0; i<256; i++) if (mapColours[i] != 0) paletteSize++;
+ // Create palette
+ RMDBGONCE(3, RMDebug::module_conversion, "r_Conv_BMP", "convertTo(): number of distinct colours: " << paletteSize )
+ palette = new rgb_quad_t[paletteSize];
+ paletteSize = 0;
+ for (i=0; i<256; i++)
+ {
+ if (mapColours[i] != 0)
+ {
+ palette[paletteSize].red = (unsigned char)i;
+ palette[paletteSize].green = (unsigned char)i;
+ palette[paletteSize].blue = (unsigned char)i;
+ palette[paletteSize].null = 0;
+ paletteSize++;
+ }
+ }
+ // ``compress'' colourmap
+ paletteSize = 0;
+ for (i=0; i<256; i++)
+ {
+ if (mapColours[i] != 0) mapColours[i] = paletteSize++;
+ }
+ ihead.clrUsed = paletteSize; ihead.clrImportant = 0; // for simplicity's sake
+ break;
+ }
+ case ctype_rgb:
+ ihead.bitCount = 24; destPitch = ((width * 3 + 3) & ~3); paletteSize = 0; pixelSize = 3;
+ ihead.clrUsed = 0; ihead.clrImportant = 0;
+ break;
+ default:
+ RMInit::logOut << "r_Conv_BMP::convertTo(): Unknown base type!" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ lineAdd = pixelSize; pixelAdd = height * pixelSize;
+
+ // Write dummy header, to be replaced later
+ memset(bmpHeaders, 0, BMPHEADERSIZE);
+ memfs_write(handle, bmpHeaders, BMPHEADERSIZE);
+ if (paletteSize != 0)
+ {
+ memfs_write(handle, palette, paletteSize * sizeof(rgb_quad_t));
+ delete [] palette; palette = NULL;
+ }
+
+ srcLine = (const unsigned char*)(desc.src + (height-1) * pixelSize);
+
+ if (ihead.compression == COMPRESS_NONE)
+ {
+ if ((dest = new unsigned char[destPitch]) == NULL)
+ {
+ RMInit::logOut << "r_Conv_BMP::convertTo(): out of memory!" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+ for (j=0; j<height; j++, srcLine -= lineAdd)
+ {
+ srcPtr = srcLine; destPtr = dest;
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ {
+ int mask=0;
+ unsigned char val=0;
+
+ mask = 0x80; val = 0;
+ for (i=0; i<width; i++, srcPtr += pixelAdd)
+ {
+ if (*srcPtr != 0) val |= mask;
+ mask >>= 1;
+ if (mask == 0)
+ {
+ *destPtr++ = val; mask = 0x80; val = 0;
+ }
+ }
+ if (mask != 0x80) *destPtr++ = val;
+ }
+ break;
+ case ctype_char:
+ for (i=0; i<width; i++, srcPtr += pixelAdd)
+ {
+ *destPtr++ = mapColours[*srcPtr];
+ }
+ break;
+ case ctype_rgb:
+ for (i=0; i<width; i++, srcPtr += pixelAdd)
+ {
+ *destPtr++ = srcPtr[2]; *destPtr++ = srcPtr[1]; *destPtr++ = srcPtr[0];
+ }
+ break;
+ }
+ // Align to 32bit-boundary
+ for (i = (4 - (r_Ptr)destPtr) & 3; i>0; i--) *destPtr++ = 0;
+ memfs_write(handle, dest, destPitch);
+ }
+ delete [] dest; dest = NULL;
+ }
+ else // implies RLE 8
+ {
+ if ((dest = new unsigned char[2*destPitch]) == NULL)
+ {
+ RMInit::logOut << "r_Conv_BMP::convertTo(): out of memory!" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+
+ for (j=0; j<height; j++, srcLine -= lineAdd)
+ {
+ const unsigned char *lastLit=NULL, *tryRun=NULL;
+ int k=0, numLit=0;
+
+ srcPtr = srcLine; destPtr = dest;
+ lastLit = srcPtr; i = 0; numLit = 0;
+ while (i < width)
+ {
+ k = i;
+ tryRun = srcPtr;
+ while (k < width-1)
+ {
+ if (*tryRun != *(tryRun + pixelAdd)) break;
+ tryRun += pixelAdd; k++;
+ }
+ // If k < width-1 tryRun points to the first symbol not int the run,
+ // otherwise it points to the last one in the run
+ if (k == width-1) k = width - i; else k -= i;
+ // Run found ==> encode literals + run
+ // If a literal sequence has to be broken for the run we require a longer run.
+ // For the sequence <lit><run><lit> a run shorter than 5 bytes is best merged into lit.
+ // For the sequence <lit><run1><run2> the first run should be merged with lit if it's
+ // less than 3 bytes long. Therefore on average 4 bytes minimum runs are best.
+ if (((numLit == 0) && (k > 1)) || (k > 3))
+ {
+ // First output the pending literals, if any
+ destPtr = flushLiterals(numLit, pixelAdd, destPtr, lastLit, mapColours);
+ numLit = 0;
+ i += k;
+ // Now output the run
+ while (k > 0)
+ {
+ int runLength=0;
+
+ runLength = k; if (runLength > 255) runLength = 255;
+ *destPtr++ = runLength; *destPtr++ = mapColours[*srcPtr];
+ k -= runLength;
+ }
+ srcPtr = tryRun; lastLit = srcPtr;
+ }
+ else
+ {
+ numLit++; srcPtr += pixelAdd; i++;
+ }
+ }
+ // Flush remaining literals
+ destPtr = flushLiterals(numLit, pixelAdd, destPtr, lastLit, mapColours);
+ // EOL
+ *destPtr++ = 0; *destPtr++ = 0;
+ memfs_write(handle, dest, (destPtr - dest));
+ }
+ // EOB
+ dest[0] = 0; dest[1] = 1;
+ memfs_write(handle, dest, 2);
+
+ delete [] dest; dest = NULL;
+ }
+
+ fileSize = memfs_size(handle);
+ RMDBGONCE( 3, RMDebug::module_conversion, "r_Conv_BMP", "convertTo(): size: " << fileSize );
+ offset = BMPHEADERSIZE + paletteSize * sizeof(rgb_quad_t);
+ dest = bmpHeaders;
+ ihead.sizeImage = fileSize - offset;
+
+ WRITE_LE_SHORT(dest, BMP_IDENTIFIER);
+ WRITE_LE_LONG(dest, fileSize);
+ WRITE_LE_SHORT(dest, 0);
+ WRITE_LE_SHORT(dest, 0);
+ WRITE_LE_LONG(dest, offset);
+
+ WRITE_LE_LONG(dest, ihead.size);
+ WRITE_LE_LONG(dest, ihead.width);
+ WRITE_LE_LONG(dest, ihead.height);
+ WRITE_LE_SHORT(dest, ihead.planes);
+ WRITE_LE_SHORT(dest, ihead.bitCount);
+ WRITE_LE_LONG(dest, ihead.compression);
+ WRITE_LE_LONG(dest, ihead.sizeImage);
+ WRITE_LE_LONG(dest, ihead.xpels);
+ WRITE_LE_LONG(dest, ihead.ypels);
+ WRITE_LE_LONG(dest, ihead.clrUsed);
+ WRITE_LE_LONG(dest, ihead.clrImportant);
+
+ memfs_seek(handle, 0, SEEK_SET);
+ memfs_write(handle, bmpHeaders, BMPHEADERSIZE);
+
+ if ((desc.dest = (char*)mystore.storage_alloc(fileSize)) == NULL)
+ {
+ RMInit::logOut << "r_Conv_BMP::convertTo(): out of memory!" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+ memfs_seek(handle, 0, SEEK_SET);
+ memfs_read(handle, desc.dest, fileSize);
+
+ memfs_killfs(handle);
+ delete memFS; memFS = NULL;
+
+ desc.destInterv = r_Minterval(1);
+ desc.destInterv << r_Sinterval((r_Range)0, (r_Range)fileSize-1);
+
+ desc.destType = r_Type::get_any_type("char");
+
+ return desc;
+}
+
+
+// Auxiliary makro for RLE coders
+#define BMP_RLE_LINEFEED \
+ destLine -= lineAdd; destPtr = destLine; j++; i = 0;
+
+r_convDesc &r_Conv_BMP::convertFrom(const char *options) throw(r_Error)
+{
+ bitmap_file_header_t fhead;
+ bitmap_info_header_t ihead;
+ const rgb_quad_t *palette=NULL;
+ const unsigned char *bmp=NULL;
+ int i=0, j=0;
+ int srcPitch=0;
+ int pixelSize=0, destType=0;
+ int paletteIsGrey=0, paletteSize=0;
+ int width=0, height=0;
+ unsigned char emit0=0, emit1=0; // in case of bitmap -> bool: values to emit for 0 and 1
+ int lineAdd=0, pixelAdd=0;
+
+ bmp = (const unsigned char*)desc.src;
+
+ // Read file header
+ READ_LE_SHORT(bmp, fhead.type);
+ READ_LE_LONG(bmp, fhead.size);
+ READ_LE_SHORT(bmp, fhead.res0);
+ READ_LE_SHORT(bmp, fhead.res1);
+ READ_LE_LONG(bmp, fhead.offset);
+
+ if (fhead.type != BMP_IDENTIFIER)
+ {
+ RMInit::logOut << "r_Conv_BMP::convertFrom(): not a BMP file" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ // Read info header
+ READ_LE_LONG(bmp, ihead.size);
+ READ_LE_LONG(bmp, ihead.width);
+ READ_LE_LONG(bmp, ihead.height);
+ READ_LE_SHORT(bmp, ihead.planes);
+ READ_LE_SHORT(bmp, ihead.bitCount);
+ READ_LE_LONG(bmp, ihead.compression);
+ READ_LE_LONG(bmp, ihead.sizeImage);
+ READ_LE_LONG(bmp, ihead.xpels);
+ READ_LE_LONG(bmp, ihead.ypels);
+ READ_LE_LONG(bmp, ihead.clrUsed);
+ READ_LE_LONG(bmp, ihead.clrImportant);
+
+ width = (int)ihead.width; height = (int)ihead.height;
+
+ RMDBGIF(4, RMDebug::module_conversion, "r_Conv_BMP", \
+ RMInit::dbgOut << "File: type " << std::hex << fhead.type << ", size " << std::dec << fhead.size; \
+ RMInit::dbgOut << ", rsv0 " << fhead.res0 << ", rsv1 " << fhead.res1 << ", offs " << fhead.offset << endl; \
+ RMInit::dbgOut << "Info: size " << ihead.size << ", width " << ihead.width << ", height " << ihead.height; \
+ RMInit::dbgOut << ", planes " << ihead.planes << ", bits " << ihead.bitCount << ", comp " << ihead.compression; \
+ RMInit::dbgOut << ", sizeImg " << ihead.sizeImage << ", xpels " << ihead.xpels << ", ypels " << ihead.ypels; \
+ RMInit::dbgOut << ", clrUsed " << ihead.clrUsed << ", clrImp " << ihead.clrImportant << endl; )
+
+ palette = (const rgb_quad_t*)(desc.src + BMPFILEHEADERSIZE + ihead.size);
+ paletteIsGrey = 0;
+ paletteSize = ihead.clrUsed;
+ if ((paletteSize == 0) && (ihead.bitCount != 24)) paletteSize = (1 << ihead.bitCount);
+
+ switch (ihead.bitCount)
+ {
+ case 1:
+ srcPitch = ((width + 31) & ~31) >> 3;
+ // Grey?
+ if ((palette[0].red == palette[0].green) && (palette[0].green == palette[0].blue) &&
+ (palette[1].red == palette[1].green) && (palette[1].green == palette[1].blue))
+ {
+ paletteIsGrey = 1; pixelSize = 1;
+ // Yes; also black + white?
+ if (((palette[0].red == 0x00) && (palette[1].red == 0xff)) ||
+ ((palette[0].red == 0xff) && (palette[1].red == 0x00)))
+ {
+ // Yes
+ destType = ctype_bool;
+ if (palette[0].red == 0)
+ {
+ emit0 = 0; emit1 = 1;
+ }
+ else
+ {
+ emit0 = 1; emit1 = 0;
+ }
+ }
+ else
+ {
+ // No
+ destType = ctype_char;
+ }
+ }
+ else
+ {
+ // Convert to RGB
+ destType = ctype_rgb; pixelSize = 3;
+ }
+ break;
+ case 4:
+ case 8:
+ {
+ if (ihead.bitCount == 4)
+ {
+ srcPitch = ((width + 7) & ~7) >> 1;
+ }
+ else
+ {
+ srcPitch = ((width + 3) & ~3); }
+ // Check whether the palette is greyscale
+ for (i=0; i<paletteSize; i++)
+ {
+ if ((palette[i].red != palette[i].green) || (palette[i].green != palette[i].blue)) break;
+ }
+ if (i < paletteSize)
+ {
+ destType = ctype_rgb; pixelSize = 3;
+ }
+ else
+ {
+ destType = ctype_char; paletteIsGrey = 1; pixelSize = 1;
+ }
+ }
+ break;
+ case 24:
+ destType = ctype_rgb; srcPitch = (width * 3 + 3) & ~3;
+ pixelSize = 3;
+ break;
+ default:
+ {
+ RMInit::logOut << "r_Conv_BMP::convertFrom(): Bad bitmap depth" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ }
+
+ RMDBGONCE( 4, RMDebug::module_conversion, "r_Conv_BMP", "convertFrom(): type " << destType << ", srcPitch " << srcPitch << ", pixelSize " << pixelSize << ", palsize " << paletteSize );
+
+ unsigned char *dest=NULL, *destPtr=NULL, *destLine=NULL;
+ const unsigned char *imgPtr=NULL, *imgLine=NULL;
+
+ pixelAdd = pixelSize * height; lineAdd = pixelSize;
+
+ imgLine = (const unsigned char *)(palette + paletteSize);
+
+ if ((dest = (unsigned char*)mystore.storage_alloc(width * height * pixelSize)) == NULL)
+ {
+ RMInit::logOut << "r_Conv_BMP::convertFrom(): out of memory" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+
+ if (ihead.compression != COMPRESS_NONE)
+ {
+ // This is only defined for 8bpp and 4bpp data. The result can only be 8bpp or 24bpp.
+ // Init the entire picture to colour #0. Is this correct? Undocumented.
+ destPtr = dest; i = width * height;
+ if (paletteIsGrey == 0)
+ {
+ while (i > 0)
+ {
+ destPtr[0] = palette[0].red; destPtr[1] = palette[0].green; destPtr[2] = palette[0].blue;
+ destPtr += pixelSize; i--;
+ }
+ }
+ else
+ {
+ while (i > 0)
+ {
+ destPtr[0] = palette[0].red;
+ destPtr += pixelSize; i--;
+ }
+ }
+ }
+
+ destLine = dest + ((height - 1) * pixelSize);
+
+ switch (ihead.compression)
+ {
+ case COMPRESS_NONE:
+ for (j=0; j<height; j++, destLine -= lineAdd, imgLine += srcPitch)
+ {
+ destPtr = destLine; imgPtr = imgLine;
+ switch (ihead.bitCount)
+ {
+ case 1:
+ {
+ int mask=0;
+ unsigned char val=0;
+
+ mask = 0x00;
+ switch (destType)
+ {
+ case ctype_bool:
+ for (i=0; i<width; i++, destPtr += pixelAdd)
+ {
+ if (mask == 0x00)
+ {
+ mask = 0x80; val = *imgPtr++;
+ }
+ *destPtr = ((val & mask) == 0) ? emit0 : emit1;
+ mask >>= 1;
+ }
+ break;
+ case ctype_char:
+ for (i=0; i<width; i++, destPtr += pixelAdd)
+ {
+ if (mask == 0x00)
+ {
+ mask = 0x80; val = *imgPtr++;
+ }
+ *destPtr = palette[(((val & mask) == 0) ? 0 : 1)].red;
+ mask >>= 1;
+ }
+ break;
+ case ctype_rgb:
+ for (i=0; i<width; i++, destPtr += pixelAdd)
+ {
+ int idx=0;
+
+ if (mask == 0x00)
+ {
+ mask = 0x80; val = *imgPtr++;
+ }
+ idx = ((val & mask) == 0) ? 0 : 1;
+ destPtr[0] = palette[idx].red;
+ destPtr[1] = palette[idx].green;
+ destPtr[2] = palette[idx].blue;
+ mask >>= 1;
+ }
+ break;
+ }
+ }
+ break;
+ case 4:
+ {
+ switch (destType)
+ {
+ case ctype_char:
+ for (i=0; i<width; i+=2)
+ {
+ *destPtr = palette[(*imgPtr) >> 4].red;
+ destPtr += pixelAdd;
+ *destPtr = palette[(*imgPtr & 0x0f)].red;
+ destPtr += pixelAdd; imgPtr++;
+ }
+ if (i < width)
+ {
+ *destPtr = palette[(*imgPtr) >> 4].red;
+ }
+ break;
+ case ctype_rgb:
+ for (i=0; i<width; i+=2)
+ {
+ int idx;
+
+ idx = (*imgPtr) >> 4;
+ destPtr[0] = palette[idx].red;
+ destPtr[1] = palette[idx].green;
+ destPtr[2] = palette[idx].blue;
+ destPtr += pixelAdd;
+ idx = (*imgPtr) & 0x0f;
+ destPtr[0] = palette[idx].red;
+ destPtr[1] = palette[idx].green;
+ destPtr[2] = palette[idx].blue;
+ destPtr += pixelAdd; imgPtr++;
+ }
+ if (i < width)
+ {
+ int idx;
+
+ idx = (*imgPtr) >> 4;
+ destPtr[0] = palette[idx].red;
+ destPtr[1] = palette[idx].green;
+ destPtr[2] = palette[idx].blue;
+ }
+ break;
+ }
+ }
+ break;
+ case 8:
+ switch (destType)
+ {
+ case ctype_char:
+ for (i=0; i<width; i++, destPtr += pixelAdd)
+ {
+ *destPtr = palette[*imgPtr++].red;
+ }
+ break;
+ case ctype_rgb:
+ for (i=0; i<width; i++, destPtr += pixelAdd)
+ {
+ destPtr[0] = palette[*imgPtr].red;
+ destPtr[1] = palette[*imgPtr].green;
+ destPtr[2] = palette[*imgPtr].blue;
+ imgPtr++;
+ }
+ break;
+ }
+ break;
+ case 24:
+ for (i=0; i<width; i++, destPtr += pixelAdd)
+ {
+ destPtr[0] = imgPtr[2]; destPtr[1] = imgPtr[1]; destPtr[2] = imgPtr[0];
+ imgPtr += 3;
+ }
+ break;
+ }
+ }
+ break;
+ case COMPRESS_RLE8:
+ {
+ i = 0; j = 0; destPtr = destLine; imgPtr = imgLine;
+ while (j >= 0)
+ {
+ unsigned char val=0, cmd=0;
+
+ //cout << "(" << i << "," << j << ")" << endl;
+ cmd = *imgPtr++;
+ if (cmd == 0) // escape
+ {
+ cmd = *imgPtr++;
+ switch (cmd)
+ {
+ case 0: // end of line
+ //cout << "EOL" << endl;
+ BMP_RLE_LINEFEED;
+ break;
+ case 1: // end of bitmap
+ //cout << "EOB" << endl;
+ j = -1;
+ break;
+ case 2: // delta
+ //cout << "DELTA" << endl;
+ val = *imgPtr++; i += val; destPtr += val * pixelAdd;
+ val = *imgPtr++; j += val; destPtr -= val * lineAdd; destLine -= val * lineAdd;
+ break;
+ default: // absolute mode
+ //cout << "ABS" << endl;
+ while (cmd > 0)
+ {
+ val = *imgPtr++;
+ if (j < height)
+ {
+ if (i >= width)
+ {
+ BMP_RLE_LINEFEED;
+ }
+ destPtr[0] = palette[val].red;
+ if (paletteIsGrey == 0)
+ {
+ destPtr[1] = palette[val].green;
+ destPtr[2] = palette[val].blue;
+ }
+ destPtr += pixelAdd; i++;
+ }
+ cmd--;
+ }
+ // Align srcPtr to a Windows-Word position (==> aligned to short)
+ if ((((r_Ptr)imgPtr) & 1) != 0) imgPtr++;
+ break;
+ }
+ }
+ else // repeat sequence
+ {
+ //cout << "RUN" << endl;
+ val = *imgPtr++;
+ while (cmd > 0)
+ {
+ if (j < height)
+ {
+ if (i >= width)
+ {
+ BMP_RLE_LINEFEED;
+ }
+ destPtr[0] = palette[val].red;
+ if (paletteIsGrey == 0)
+ {
+ destPtr[1] = palette[val].green;
+ destPtr[2] = palette[val].blue;
+ }
+ destPtr += pixelAdd; i++;
+ }
+ cmd--;
+ }
+ }
+ }
+ }
+ break;
+ case COMPRESS_RLE4:
+ {
+ i = 0; j = 0; destPtr = destLine; imgPtr = imgLine;
+ while (j >= 0)
+ {
+ unsigned char val=0, cmd=0;
+
+ cmd = *imgPtr++;
+ if (cmd == 0) // escape
+ {
+ cmd = *imgPtr++;
+ switch (cmd)
+ {
+ case 0: // end of line
+ BMP_RLE_LINEFEED;
+ break;
+ case 1: // end of bitmap
+ j = -1;
+ break;
+ case 2: // delta
+ val = *imgPtr++; i += val; destPtr += val * pixelAdd;
+ val = *imgPtr++; j += val; destPtr -= val * lineAdd; destLine -= val * lineAdd;
+ break;
+ default: // absolute mode
+ while (cmd > 1)
+ {
+ val = *imgPtr++;
+ if (j < height)
+ {
+ if (i >= width)
+ {
+ BMP_RLE_LINEFEED;
+ }
+ destPtr[0] = palette[val >> 4].red;
+ if (paletteIsGrey == 0)
+ {
+ destPtr[1] = palette[val >> 4].green;
+ destPtr[2] = palette[val >> 4].blue;
+ }
+ destPtr += pixelAdd; i++;
+ if (i >= width)
+ {
+ BMP_RLE_LINEFEED;
+ }
+ destPtr[0] = palette[val & 0x0f].red;
+ if (paletteIsGrey == 0)
+ {
+ destPtr[1] = palette[val & 0x0f].green;
+ destPtr[2] = palette[val & 0x0f].blue;
+ }
+ destPtr += pixelAdd; i++;
+ }
+ cmd-=2;
+ }
+ if (cmd != 0)
+ {
+ val = *imgPtr++;
+ if (j < height)
+ {
+ if (i >= width)
+ {
+ BMP_RLE_LINEFEED;
+ }
+ destPtr[0] = palette[val >> 4].red;
+ if (paletteIsGrey == 0)
+ {
+ destPtr[1] = palette[val >> 4].green;
+ destPtr[2] = palette[val >> 4].blue;
+ }
+ destPtr += pixelAdd; i++;
+ }
+ }
+ // Align srcPtr to a Windows-Word position (==> aligned to short)
+ if ((((r_Ptr)imgPtr) & 1) != 0) imgPtr++;
+ break;
+ }
+ }
+ else // repeat sequence
+ {
+ val = *imgPtr++;
+ while (cmd > 1)
+ {
+ if (j < height)
+ {
+ if (i >= width)
+ {
+ BMP_RLE_LINEFEED;
+ }
+ destPtr[0] = palette[val >> 4].red;
+ if (paletteIsGrey == 0)
+ {
+ destPtr[1] = palette[val >> 4].green;
+ destPtr[2] = palette[val >> 4].blue;
+ }
+ destPtr += pixelAdd; i++;
+ if (i >= width)
+ {
+ BMP_RLE_LINEFEED;
+ }
+ destPtr[0] = palette[val & 0x0f].red;
+ if (paletteIsGrey == 0)
+ {
+ destPtr[1] = palette[val & 0x0f].green;
+ destPtr[2] = palette[val & 0x0f].blue;
+ }
+ destPtr += pixelAdd; i++;
+ }
+ cmd -= 2;
+ }
+ if (cmd != 0)
+ {
+ if (j < height)
+ {
+ if (i >= width)
+ {
+ BMP_RLE_LINEFEED;
+ }
+ destPtr[0] = palette[val >> 4].red;
+ if (paletteIsGrey == 0)
+ {
+ destPtr[1] = palette[val >> 4].green;
+ destPtr[2] = palette[val >> 4].blue;
+ }
+ destPtr += pixelAdd; i++;
+ }
+ }
+ }
+ }
+ }
+ break;
+ default:
+ {
+ RMInit::logOut << "r_Conv_BMP::convertFrom(): bad compression type" << endl;
+ mystore.storage_free(dest);
+ throw r_Error(r_Error::r_Error_General);
+ }
+ }
+
+ desc.dest = (char*)dest; desc.baseType = destType;
+
+ desc.destInterv = r_Minterval(2);
+ desc.destInterv << r_Sinterval((r_Range)0, (r_Range)width-1)
+ << r_Sinterval((r_Range)0, (r_Range)height-1);
+
+ desc.destType = get_external_type(desc.baseType);
+
+ return desc;
+}
+
+
+
+const char *r_Conv_BMP::get_name( void ) const
+{
+ return format_name_bmp;
+}
+
+
+r_Data_Format r_Conv_BMP::get_data_format( void ) const
+{
+ return r_BMP;
+}
+
+
+r_Convertor *r_Conv_BMP::clone( void ) const
+{
+ return new r_Conv_BMP(desc.src, desc.srcInterv, desc.baseType);
+}
diff --git a/conversion/bmp.hh b/conversion/bmp.hh
new file mode 100644
index 0000000..de49ddc
--- /dev/null
+++ b/conversion/bmp.hh
@@ -0,0 +1,91 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: bmp.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_BMP
+ *
+ * COMMENTS:
+ *
+ * Provides interface to convert data to other formats.
+ *
+*/
+
+#ifndef _R_CONV_BMP_HH_
+#define _R_CONV_BMP_HH_
+
+#include "conversion/convertor.hh"
+
+
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ BMP convertor class.
+ Completely native implementation, doesn't use external libs.
+ memfs is used differently here, therefore the class is derived
+ directly from r_Convertor rather than r_Convert_Memory.
+
+ Supported parameters are
+
+ \begin{tabular}{lcl}
+ compress && int && Use compression (8bpp only)
+ \end{tabular}
+*/
+
+class r_Conv_BMP : public r_Convertor
+{
+ public:
+ /// constructor using an r_Type object
+ r_Conv_BMP( const char *src, const r_Minterval &interv, const r_Type *tp ) throw(r_Error);
+ /// constructor using convert_type_e shortcut
+ r_Conv_BMP( const char *src, const r_Minterval &interv, int tp ) throw(r_Error);
+ /// destructor
+ ~r_Conv_BMP( void );
+
+ /// convert to BMP
+ virtual r_convDesc &convertTo( const char *options=NULL ) throw(r_Error);
+ /// convert from BMP
+ virtual r_convDesc &convertFrom( const char *options=NULL ) throw(r_Error);
+ /// cloning
+ virtual r_Convertor *clone( void ) const;
+ /// identification
+ virtual const char *get_name( void ) const;
+ virtual r_Data_Format get_data_format( void ) const;
+
+
+ private:
+ /// initalize BMP class
+ void initBMP( void );
+ /// Needed by the encoder in RLE mode
+ unsigned char *flushLiterals(int numLit, int pixelAdd, unsigned char *dest, const unsigned char *lastLit, const unsigned char *mapColours);
+
+ memFSContext *memFS;
+
+ /// parameters
+ int compress;
+};
+
+#endif
diff --git a/conversion/convertor.cc b/conversion/convertor.cc
new file mode 100644
index 0000000..9c6f353
--- /dev/null
+++ b/conversion/convertor.cc
@@ -0,0 +1,405 @@
+/*
+* 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: convertor.cc
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Convertor, r_Convert_Memory
+ *
+ * PURPOPSE:
+ * Provides interface to convert data to other formats.
+ *
+ * COMMENTS:
+ * - FIXME: r_Convertor::get_internal_type(): every structType is recognised as RGB!
+ *
+*/
+
+#include "conversion/convertor.hh"
+#include "conversion/memfs.hh"
+#include "raslib/error.hh"
+#include "raslib/parseparams.hh"
+#include "raslib/rminit.hh"
+#include "raslib/primitivetype.hh"
+
+
+/*
+ * r_Convertor class
+ */
+
+void r_Convertor::initShare( const char *src, const r_Minterval &interv )
+{
+ desc.src = src;
+ desc.srcInterv = interv;
+ desc.srcType = NULL;
+ desc.destType = NULL;
+ desc.dest = NULL;
+ params = NULL;
+ destroySrc = false;
+}
+
+
+r_Convertor::r_Convertor( void )
+{
+ desc.srcType = NULL;
+ desc.destType = NULL;
+ desc.dest = NULL;
+ desc.src = NULL;
+ desc.baseType = ctype_void;
+ params = NULL;
+}
+
+
+r_Convertor::r_Convertor( const char *src, const r_Minterval &interv, const r_Type *tp, bool fullTypes ) throw(r_Error)
+{
+ initShare(src, interv);
+
+ desc.srcType = tp;
+
+ if (tp == NULL)
+ {
+ RMInit::logOut << "Error: in conversion: type is null." << endl;
+ throw r_Error();
+ }
+
+ // Initialise desc.baseType from desc.srcType
+ desc.baseType=get_internal_type(tp, fullTypes);
+
+ if (!fullTypes) {
+ switch (tp->type_id()) {
+ case r_Type::FLOAT:
+ this->applyColorScheme<float>();
+ break;
+ case r_Type::DOUBLE:
+ applyColorScheme<double>();
+ break;
+ case r_Type::USHORT:
+ applyColorScheme<unsigned short>();
+ break;
+ case r_Type::SHORT:
+ applyColorScheme<short>();
+ break;
+ }
+ }
+}
+
+
+r_Convertor::r_Convertor(const char *src, const r_Minterval &interv, int type) throw(r_Error)
+{
+ initShare(src, interv);
+
+ desc.baseType = type;
+}
+
+
+r_Convertor::~r_Convertor(void)
+{
+ // Don't delete the resulting object pointer (desc->dest) !
+ // This is the job of the external application.
+ if (params!=NULL)
+ {
+ delete params;
+ params=NULL;
+ }
+ if (destroySrc)
+ {
+ delete desc.src;
+ destroySrc=false;
+ }
+}
+
+
+void r_Convertor::set_storage_handler( const r_Storage_Man &newStore )
+{
+ mystore = newStore;
+}
+
+
+const r_Storage_Man&
+r_Convertor::get_storage_handler( ) const
+{
+ return mystore;
+}
+
+
+
+r_Type *r_Convertor::get_external_type( int ctype ) throw(r_Error)
+{
+ r_Type* retval=NULL;
+ switch (ctype)
+ {
+ case ctype_bool:
+ retval=r_Type::get_any_type("boolean");
+ break;
+ case ctype_char:
+ case ctype_uint8:
+ retval=r_Type::get_any_type("char");
+ break;
+ case ctype_int8:
+ retval=r_Type::get_any_type("octet");
+ break;
+ case ctype_int16:
+ retval=r_Type::get_any_type("short");
+ break;
+ case ctype_uint16:
+ retval=r_Type::get_any_type("ushort");
+ break;
+ case ctype_int32:
+ retval=r_Type::get_any_type("long");
+ break;
+ case ctype_uint32:
+ retval=r_Type::get_any_type("ulong");
+ break;
+ case ctype_int64:
+ retval=r_Type::get_any_type("double"); // currently unsupported
+ break;
+ case ctype_uint64:
+ retval=r_Type::get_any_type("double"); // currently unsupported
+ break;
+ case ctype_float32:
+ retval=r_Type::get_any_type("float");
+ break;
+ case ctype_float64:
+ retval=r_Type::get_any_type("double");
+ break;
+ case ctype_rgb:
+ retval=r_Type::get_any_type("struct {char, char, char}");
+ break;
+ default:
+ RMInit::logOut << "Error: in conversion: unsupported type " << ctype << endl;
+ r_Error err(r_Error::r_Error_General);
+ throw(err);
+ }
+ return retval;
+}
+
+
+template <class baseType>
+void r_Convertor::applyColorScheme() {
+ baseType *data = (baseType*)desc.src;
+ baseType min=data[0], max=data[0];
+ int i, size = desc.srcInterv.cell_count();
+ unsigned char *t, *img = new unsigned char[size*3];
+ for (i=1; i<size; ++i) {
+ if (min > data[i])
+ min=data[i];
+ if (max < data[i])
+ max=data[i];
+ }
+ for (i=0, t=img; i<size; ++i) {
+ float n = (data[i]-min)/(max-min);
+ if (n<0.5) {
+ *t=(unsigned char)((0.5-n)*500); t++;
+ *t=(unsigned char)(n*500); t++;
+ *t=0; t++;
+ } else
+ {
+ *t=0;t++;
+ *t=(unsigned char)((1-n)*500); t++;
+ *t=(unsigned char)((n-0.5)*500); t++;
+ }
+ }
+ destroySrc = true;
+ desc.src = (char*)img;
+}
+
+r_Convertor::convert_type_e
+r_Convertor::get_internal_type(const r_Type* tp, bool fullTypes) throw(r_Error) {
+ r_Convertor::convert_type_e retval=ctype_void;
+
+ if (tp == NULL)
+ return retval;
+
+ //check if tp is structure type
+ if (tp->isStructType())
+ {
+ // make life easy and always interpret as RGB
+ retval = ctype_rgb;
+ }
+ else
+ {
+ //is primitive type
+ if (fullTypes == false)
+ {
+ // restricted types for ``classic'' image formats
+ switch (tp->type_id())
+ {
+ case r_Type::BOOL:
+ retval = ctype_bool; break;
+ case r_Type::CHAR:
+ case r_Type::OCTET:
+ retval = ctype_char; break;
+ // added (U)LONG -- PB 2005-apr-27
+ case r_Type::LONG:
+ retval = ctype_int32; break;
+ case r_Type::ULONG:
+ retval = ctype_uint32; break;
+ // set to defined value (FIXME: still not good) -- PB 2005-apr-27
+ default:
+ RMInit::logOut << "Error: in conversion: unknown type " << tp->type_id() << ", setting to void." << endl;
+ retval = ctype_rgb;
+ //retval = ctype_char;
+
+ break;
+ }
+ }
+ else
+ {
+ // full types for more generic convertors
+ switch (tp->type_id())
+ {
+ case r_Type::BOOL:
+ //FIXME that was in hdf.cc retval = ctype_uint8; break;
+ retval = ctype_bool; break;
+ case r_Type::CHAR:
+ retval = ctype_uint8; break;
+ case r_Type::OCTET:
+ retval = ctype_int8; break;
+ case r_Type::SHORT:
+ retval = ctype_int16; break;
+ case r_Type::USHORT:
+ retval = ctype_uint16; break;
+ case r_Type::LONG:
+ retval = ctype_int32; break;
+ case r_Type::ULONG:
+ retval = ctype_uint32; break;
+ case r_Type::FLOAT:
+ retval = ctype_float32; break;
+ case r_Type::DOUBLE:
+ retval = ctype_float64; break;
+ default:
+ break;
+ }
+ }//endif fullTypes
+ if (retval == ctype_void)
+ {
+ RMInit::logOut << "Warning: in conversion: this type overrides base type: " << tp->type_id() << "; using char." << endl;
+ retval = ctype_char;
+ }
+ }//endif structuretype
+
+ return retval;
+}
+
+std::ostream& operator<<(std::ostream& os, r_Convertor::convert_type_e& cte)
+{
+ switch(cte)
+ {
+ case r_Convertor::ctype_bool:
+ os << "bool";
+ break;
+ case r_Convertor::ctype_char:
+ os << "char";
+ break;
+ case r_Convertor::ctype_uint8:
+ os << "uint8";
+ break;
+ case r_Convertor::ctype_int8:
+ os << "int8";
+ break;
+ case r_Convertor::ctype_int16:
+ os << "int16";
+ break;
+ case r_Convertor::ctype_uint16:
+ os << "uint16";
+ break;
+ case r_Convertor::ctype_int32:
+ os << "int32";
+ break;
+ case r_Convertor::ctype_uint32:
+ os << "uint32";
+ break;
+ case r_Convertor::ctype_int64:
+ os << "int64"; // currently unsupported
+ break;
+ case r_Convertor::ctype_uint64:
+ os << "uint64"; // currently unsupported
+ break;
+ case r_Convertor::ctype_float32:
+ os << "float32";
+ break;
+ case r_Convertor::ctype_float64:
+ os << "float64";
+ break;
+ case r_Convertor::ctype_rgb:
+ os << "rgb";
+ break;
+ default:
+ os << "r_Convertor::convert_type_e unknown type: " << cte << endl;
+ break;
+ }
+
+ return os;
+}
+
+/*
+ * r_Convert_Memory class
+ */
+
+void r_Convert_Memory::initMemory( void ) throw(r_Error)
+{
+ int status = -1;
+
+ memFS=NULL;
+ handle=NULL;
+
+ memFS = new memFSContext;
+ if ( memFS != NULL)
+ {
+ handle = (void*)memFS;
+ if (memfs_initfs(handle) >= 0)
+ status = 0;
+ }
+ if (status < 0)
+ {
+ RMInit::logOut << "Error: cannot allocate memory for conversion." << endl;
+ r_Error err(MEMMORYALLOCATIONERROR);
+ throw(err);
+ }
+}
+
+
+r_Convert_Memory::r_Convert_Memory( const char *src, const r_Minterval &interv, const r_Type *tp, int fullTypes ) throw(r_Error)
+: r_Convertor(src, interv, tp, fullTypes)
+{
+ initMemory();
+}
+
+
+r_Convert_Memory::r_Convert_Memory( const char *src, const r_Minterval &interv, int type ) throw(r_Error)
+: r_Convertor(src, interv, type)
+{
+ initMemory();
+}
+
+
+r_Convert_Memory::~r_Convert_Memory( void )
+{
+ memfs_killfs(handle);
+ if(memFS!=NULL)
+ {
+ delete memFS;
+ memFS=NULL;
+ }
+ handle=NULL;
+}
diff --git a/conversion/convertor.hh b/conversion/convertor.hh
new file mode 100644
index 0000000..01931f4
--- /dev/null
+++ b/conversion/convertor.hh
@@ -0,0 +1,252 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: convertor.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Convertor, r_Convert_Memory
+ *
+ * COMMENTS:
+ *
+ * Provides interface to convert data to other formats.
+ *
+*/
+
+#ifndef _R_CONVERTOR_
+#define _R_CONVERTOR_
+
+#include <stdlib.h>
+
+#include "raslib/error.hh"
+#include "raslib/minterval.hh"
+#include "raslib/type.hh"
+#include "raslib/mddtypes.hh"
+#include "raslib/storageman.hh"
+//#include "conversion/memfs.h"
+
+
+
+// Declare to avoid including memfs.h (and with that tiffio.h)
+struct memFSContext;
+
+class r_Parse_Params;
+
+
+typedef struct r_convDesc {
+ const char *src; // pointer to source data
+ char *dest; // pointer to destination data
+ r_Minterval srcInterv; // dimensions of source data
+ r_Minterval destInterv; // dimensions of destination data
+ int baseType; // shortcut to src basetype
+ const r_Type *srcType; // basetypes of src data
+ r_Type *destType; // basetypes of dest data
+} r_convDesc;
+
+
+
+//@ManMemo: Module {\bf conversion}
+
+
+/*@Doc:
+ Conversion classes from and to data exchange formats. Can also be used for
+ tile compression of special MDD types (= images)
+
+ \begin{itemize}
+ \item
+ the member function convertTo() performs the conversion MDD -> DEF
+ \item
+ the member function convertFrom() performs the conversion DEF -> MDD
+ \item
+ the r_convDesc reference returned from this call is only valid while
+ the convertor object is.
+ \item
+ after successful execution the returned r_convDesc structure contains
+ the following information:
+ \begin{itemize}
+ \item
+ dest: pointer to converted data, allocated by the configured heap
+ storage object which will use malloc() by default (see
+ set_storage_handler()); must be deallocated by the caller.
+ \item
+ destInterv: r_Minterval describing the converted object's domain.
+ \item
+ destType: pointer to an r_Type object describing the converted
+ object's type; must be deallocated by the caller.
+ \end{itemize}
+ \item
+ on failure an exception is thrown.
+ \end{itemize}
+
+ The member function convertTo() receives a parameter string as argument
+ which is NULL for default parameters. The format of the string is such
+ that it can be parsed by r_Parse_Params. The params member variable is
+ initialized to NULL in this class. Derived classes that wish to add
+ parameters must first check whether params is NULL and create a new
+ object if so, then add their parameters. This makes it possible to
+ accumulate parameters over all class hierarchies.
+*/
+
+class r_Convertor
+{
+ public:
+ /// default constructor (should not be used)
+ r_Convertor( void );
+ /// constructor using an r_Type object
+ r_Convertor( const char *src, const r_Minterval &interv, const r_Type *tp,
+ bool fullTypes=false) throw(r_Error);
+ /// constructor using convert_type_e shortcut
+ r_Convertor( const char *src, const r_Minterval &interv, int type ) throw(r_Error);
+ /**
+ convert_type_e is an enumerator that acts as a shortcut to base types
+ relevant for DEFs. The values and what they correspond to are listed
+ below (the types below the line are for HDF):
+
+ \begin{tabular}{ll}
+ ctype_void && No type, used for errors\\
+ ctype_bool && bool\\
+ ctype_char && char\\
+ ctype_rgb && struct {char, char, char}\\
+ \hline
+ ctype_int8 && signed char\\
+ ctype_uint8 && unsigned char\\
+ ctype_int16 && short\\
+ ctype_uint16 && unsigned short\\
+ ctype_int32 && int\\
+ ctype_uint32 && unsigned int\\
+ ctype_int64 && (unsupported)\\
+ ctype_uint64 && (unsupported)\\
+ ctype_float32 && float\\
+ ctype_float64 && double\\
+ \end{tabular}
+ */
+
+ /// destructor
+ virtual ~r_Convertor( void );
+
+ //@Man: Interface
+ /// convert array to DEF
+ virtual r_convDesc &convertTo( const char *options=NULL ) throw(r_Error) = 0;
+
+ /// convert DEF to array
+ virtual r_convDesc &convertFrom( const char *options=NULL ) throw(r_Error) = 0;
+
+ /// cloning
+ virtual r_Convertor *clone( void ) const = 0;
+
+ /// identification
+ virtual const char *get_name( void ) const = 0;
+ virtual r_Data_Format get_data_format( void ) const = 0;
+
+ /// set storage handler, default is malloc/free
+ void set_storage_handler( const r_Storage_Man &newStore );
+
+ /// get storage handler, default is malloc/free
+ const r_Storage_Man& get_storage_handler( ) const;
+
+
+ /// base type shortcuts
+ enum convert_type_e {
+ // undefined type
+ ctype_void,
+ // Shortcut for the three important base types r_Boolean, r_Char and RGBPixel
+ ctype_bool,
+ ctype_char,
+ ctype_rgb,
+ // More generic types for HDF
+ ctype_int8,
+ ctype_uint8,
+ ctype_int16,
+ ctype_uint16,
+ ctype_int32,
+ ctype_uint32,
+ ctype_int64,
+ ctype_uint64,
+ ctype_float32,
+ ctype_float64
+ };
+
+ //@{ helper structure for encoding string-to-int parameters
+ typedef struct convert_string_s {
+ const char *key;
+ int id;
+ } convert_string_t;
+ //@}
+
+ /// get a r_Type from an internal type
+ static r_Type *get_external_type( int ctype ) throw(r_Error);
+
+ /// get a internal type from a r_Type
+ static convert_type_e get_internal_type( const r_Type* type, bool fullTypes=false ) throw(r_Error);
+
+ protected:
+ /// initialize internal structures
+ void initShare( const char *src, const r_Minterval &interv );
+
+ /// true if we should free the src area (in case the input was converted to rgb)
+ bool destroySrc;
+
+ /// convert unsupported type to rgb by applying the default color scheme
+ template <class baseType>
+ void applyColorScheme();
+
+ /// conversion context
+ r_convDesc desc;
+
+ /// parameter parser
+ r_Parse_Params *params;
+
+ /// storage manager
+ r_Storage_Man mystore;
+};
+
+///ostream operator for convert_type_e
+std::ostream& operator<<(std::ostream& os, r_Convertor::convert_type_e& cte);
+
+/*@Doc:
+ Abstract base class for all memory-to-memory conversion classes,
+ uses memfs for of data with unknown size at the time of creation.
+*/
+
+class r_Convert_Memory : public r_Convertor
+{
+ public:
+ /// constructor using an r_Type object
+ r_Convert_Memory( const char *src, const r_Minterval &interv, const r_Type *tp,
+ int fullTypes=0) throw(r_Error);
+ /// constructur using convert_type_e shortcut
+ r_Convert_Memory( const char *src, const r_Minterval &interv, int type ) throw(r_Error);
+ /// destructor
+ virtual ~r_Convert_Memory( void );
+
+
+ protected:
+ /// init memfs
+ void initMemory( void ) throw(r_Error);
+
+ /// variables
+ memFSContext *memFS;
+ void *handle;
+};
+
+#endif
diff --git a/conversion/convfactory.cc b/conversion/convfactory.cc
new file mode 100644
index 0000000..31f27ae
--- /dev/null
+++ b/conversion/convfactory.cc
@@ -0,0 +1,189 @@
+/*
+* 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: convertor.cc
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Convertor_Factory
+ * Create convertors out of data formats
+ *
+ * COMMENTS:
+ * - temporary, for debugging
+*/
+
+#include "raslib/rminit.hh"
+#include "debug.hh"
+
+#include "conversion/convfactory.hh"
+
+// all the conversion types, for easy creation
+#include "tiff.hh"
+#include "hdf.hh"
+#include "png.hh"
+#include "jpeg.hh"
+#include "bmp.hh"
+#include "vff.hh"
+#include "tor.hh"
+#include "dem.hh"
+#include "ecw.hh"
+#include "ntf.hh"
+#include "csv.hh"
+
+
+
+bool r_Convertor_Factory::is_supported( r_Data_Format fmt )
+{
+ ENTER( "r_Convertor_Factory::is_supported( " << fmt << " )" );
+
+ bool retval=false;
+ switch (fmt)
+ {
+ case r_TIFF:
+ case r_PNG:
+ case r_JPEG:
+ case r_BMP:
+ case r_VFF:
+ case r_TOR:
+ case r_DEM:
+ case r_ECW:
+#ifndef DISABLE_HDF
+ case r_HDF:
+#endif
+ // case r_NTF:
+ retval=true;
+ break;
+ default:
+ retval=false;
+ break;
+ }
+
+ LEAVE( "r_Convertor_Factory::is_supported() -> " << retval );
+ return retval;
+}
+
+r_Convertor *r_Convertor_Factory::create( r_Data_Format fmt, const char *src, const r_Minterval &interv, const r_Type *tp) throw(r_Error)
+{
+ ENTER( "r_Convertor_Factory::create( fmt=" << fmt << ", &src=" << ((r_Ptr) src) << ", interval=" << interv << ", &type=" << ((r_Ptr) tp) << " )" );
+ r_Convertor *result = NULL;
+
+ switch (fmt)
+ {
+ case r_TIFF:
+ result = new r_Conv_TIFF(src, interv, tp);
+ break;
+ case r_PNG:
+ result = new r_Conv_PNG(src, interv, tp);
+ break;
+ case r_CSV:
+ result = new r_Conv_CSV(src, interv, tp);
+ break;
+ case r_JPEG:
+ result = new r_Conv_JPEG(src, interv, tp);
+ break;
+ case r_BMP:
+ result = new r_Conv_BMP(src, interv, tp);
+ break;
+ case r_VFF:
+ result = new r_Conv_VFF(src, interv, tp);
+ break;
+ case r_TOR:
+ result = new r_Conv_TOR(src, interv, tp);
+ break;
+ case r_DEM:
+ result = new r_Conv_DEM(src, interv, tp);
+ break;
+ case r_ECW:
+ result = new r_Conv_ECW(src, interv, tp);
+ break;
+#ifndef DISABLE_HDF
+ case r_HDF:
+ result = new r_Conv_HDF(src, interv, tp);
+ break;
+#endif
+ // case r_NTF:
+ // TALK( "creating NTF converter..." );
+ // result = new r_Conv_NTF(src, interv, tp);
+ // break;
+ default:
+ RMInit::logOut << "Error: in conversion factory during create: unsupported format: " << fmt << endl;
+ r_Error err(CONVERSIONFORMATNOTSUPPORTED);
+ throw(err);
+ }
+
+ LEAVE( "r_Convertor_Factory::create() -> " << result );
+ return result;
+}
+
+
+r_Convertor *r_Convertor_Factory::create( r_Data_Format fmt, const char *src, const r_Minterval &interv, int type ) throw(r_Error)
+{
+ ENTER( "r_Convertor_Factory::create( fmt=" << fmt << ", &src=" << ((r_Ptr) src) << ", interval=" << interv << ", type=" << type << " )" );
+
+ r_Convertor *result = NULL;
+
+ switch (fmt)
+ {
+ case r_TIFF:
+ result = new r_Conv_TIFF(src, interv, type);
+ break;
+ case r_PNG:
+ result = new r_Conv_PNG(src, interv, type);
+ break;
+ case r_JPEG:
+ result = new r_Conv_JPEG(src, interv, type);
+ break;
+ case r_BMP:
+ result = new r_Conv_BMP(src, interv, type);
+ break;
+ case r_VFF:
+ result = new r_Conv_VFF(src, interv, type);
+ break;
+ case r_TOR:
+ result = new r_Conv_TOR(src, interv, type);
+ break;
+ case r_DEM:
+ result = new r_Conv_DEM(src, interv, type);
+ break;
+ case r_ECW:
+ result = new r_Conv_ECW(src, interv, type);
+ break;
+#ifndef DISABLE_HDF
+ case r_HDF:
+ result = new r_Conv_HDF(src, interv, type);
+ break;
+#endif
+ // case r_NTF:
+ // TALK( "creating NTF converter..." );
+ // result = new r_Conv_NTF(src, interv, type);
+ // break;
+ default:
+ RMInit::logOut << "Error: in conversion factory during create: unsupported format: " << fmt << endl;
+ r_Error err(CONVERSIONFORMATNOTSUPPORTED);
+ throw(err);
+ }
+
+ LEAVE( "r_Convertor_Factory::create() -> " << result );
+ return result;
+}
+
diff --git a/conversion/convfactory.hh b/conversion/convfactory.hh
new file mode 100644
index 0000000..e299dca
--- /dev/null
+++ b/conversion/convfactory.hh
@@ -0,0 +1,64 @@
+/*
+* 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: convertor.cc
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Convertor_Factory
+ *
+ * COMMENTS:
+ * Create convertors out of data formats
+*/
+
+#include "raslib/mddtypes.hh"
+#include "raslib/error.hh"
+
+
+class r_Convertor;
+class r_Minterval;
+class r_Type;
+
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ r_Convertor_Factory is a class encapsulating static functions to
+ create convertors out of data formats. The alternative of making
+ this functionality static members of r_Converstor would have meant
+ that all code using just one convertor would have to link the libs
+ of all convertors, rendering it unusable.
+*/
+
+class r_Convertor_Factory
+{
+ public:
+ /// check for support
+ static bool is_supported( r_Data_Format fmt );
+ /// creating from r_Type
+ static r_Convertor *create( r_Data_Format fmt, const char *src, const r_Minterval &interv,
+ const r_Type *tp ) throw(r_Error);
+ /// creating from internal type
+ static r_Convertor *create( r_Data_Format fmt, const char *src, const r_Minterval &interv,
+ int type ) throw(r_Error);
+};
diff --git a/conversion/csv.cc b/conversion/csv.cc
new file mode 100644
index 0000000..7babcbe
--- /dev/null
+++ b/conversion/csv.cc
@@ -0,0 +1,222 @@
+/*
+* 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: csv.cc
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_CSV
+ *
+ * COMMENTS:
+ *
+ * Provides functions to convert data to CSV SD and back.
+ *
+*/
+
+/* Added by Sorin Stancu-Mara. Definition clashed for type int8, define in both
+* /usr/include/csv.h and in /usr/include/tiff.h
+* This will supress the tiff.h definition.
+* Both definitions are similar
+*/
+#define HAVE_INT8
+
+#include "conversion/csv.hh"
+#include "raslib/error.hh"
+#include "raslib/rminit.hh"
+#include "raslib/parseparams.hh"
+#include "raslib/primitivetype.hh"
+#include <iostream>
+#include <fstream>
+#include <cstring>
+
+#include "csv.hh"
+
+#include <stdio.h>
+#include <iostream>
+
+
+r_Conv_CSV::r_Conv_CSV(const char *src, const r_Minterval &interv, const r_Type *tp) throw(r_Error)
+: r_Convertor(src, interv, tp, true)
+{
+ if (tp->isStructType())
+ {
+ RMInit::logOut << "r_Conv_CSV::r_Conv_CSV(): structured types not supported." << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+}
+
+
+
+r_Conv_CSV::r_Conv_CSV(const char *src, const r_Minterval &interv, int tp) throw(r_Error)
+: r_Convertor(src, interv, tp)
+{
+}
+
+
+/*
+int r_Conv_HDF::getTypeSize(int intType, char *format)
+{
+
+ switch (intType)
+ {
+ case ctype_int8: strcpy(format, "%c"); return 1; break;
+ case ctype_uint8:
+ case ctype_char:
+ case ctype_bool: return 1; break;
+ case ctype_int16: return 2; break;
+ case ctype_uint16: return 2; break;
+ case ctype_int32: return 4; break;
+ case ctype_uint32: return 4; break;
+ case ctype_int64: return 8; break;
+ case ctype_uint64: return 8; break;
+ case ctype_float32: return 4; break;
+ case ctype_float64: return 8; break;
+ default: return 1; break;
+ }
+ return 1;
+}
+*/
+
+r_Conv_CSV::~r_Conv_CSV(void)
+{
+}
+
+template <class baseType, class castType>
+void r_Conv_CSV::print(std::ofstream &f, baseType* val, int *dims, int dim) {
+ if (dim==1) {
+ for (int i=0; i<dims[0]-1; ++i, val++)
+ f << (castType)val[0] << ",";
+ f << (castType) val[dims[0]-1]; val++;
+ } else {
+ for (int i=0; i<dims[0]-1; ++i, val++) {
+ f << "{";
+ print<baseType, castType>(f, val, dims+1, dim-1);
+ f << "},";
+ }
+ f << "{";
+ print<baseType, castType>(f, val, dims+1, dim-1);
+ f << "}";
+ }
+}
+
+
+r_convDesc &r_Conv_CSV::convertTo( const char *options ) throw(r_Error)
+{
+ char name[256];
+ strncpy(name, tmpnam(NULL), 256);
+ std::ofstream ftemp(name);
+ //int size = getTypeSize(desc.baseType);
+ int rank, i;
+ int *dimsizes;
+ rank = desc.srcInterv.dimension();
+ const char *src = desc.src;
+
+ char *t;
+
+ dimsizes = new int[rank];
+
+ for (i=0; i<rank; i++)
+ {
+ dimsizes[i] = desc.srcInterv[i].high() - desc.srcInterv[i].low() + 1;
+ }
+
+ switch (desc.baseType)
+ {
+ case ctype_int8: print<const r_Octet, int>(ftemp, (const r_Octet* &)src, dimsizes, rank); break;
+ case ctype_uint8:
+ case ctype_char:
+ case ctype_bool: print<r_Char, int>(ftemp, (r_Char* &)src, dimsizes, rank); break;
+ case ctype_int16: print<r_Short, int>(ftemp, (r_Short* &)src, dimsizes, rank); break;
+ case ctype_uint16: print<r_UShort, int>(ftemp, (r_UShort* &) src, dimsizes, rank); break;
+ case ctype_int32: print<r_Long, int>(ftemp, (r_Long* &) src, dimsizes, rank); break;
+ case ctype_uint32: print<r_ULong, int>(ftemp, (r_ULong* &) src, dimsizes, rank); break;
+ case ctype_int64: print<long long, long long>(ftemp, (long long* &) src, dimsizes, rank); break;
+ case ctype_uint64: print<unsigned long long, unsigned long long>(ftemp, (unsigned long long* &) src, dimsizes, rank); break;
+ case ctype_float32: print<r_Float, float>(ftemp, (r_Float* &) src, dimsizes, rank); break;
+ case ctype_float64: print<r_Double, float>(ftemp, (r_Double* &) src, dimsizes, rank); break;
+ default: print<r_Char, int>(ftemp, (r_Char* &)src, dimsizes, rank);
+ }
+
+ delete [] dimsizes; dimsizes=NULL;
+ ftemp.close();
+
+ FILE *fp;
+ int filesize;
+
+ if ((fp = fopen(name, "rb")) == NULL)
+ {
+ RMInit::logOut << "r_Conv_CSV::convertTo(): unable to read back file." << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ fseek(fp, 0, SEEK_END);
+ filesize = ftell(fp);
+
+ desc.destInterv = r_Minterval(1);
+ desc.destInterv << r_Sinterval((r_Range)0, (r_Range)filesize - 1);
+
+ if ((desc.dest = (char*)mystore.storage_alloc(filesize)) == NULL)
+ {
+ RMInit::logOut << "r_Conv_CSV::convertTo(): out of memory error" << endl;
+ fclose(fp);
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+ fseek(fp, 0, SEEK_SET);
+ fread(desc.dest, 1, filesize, fp);
+
+ fclose(fp);
+
+ remove(name);
+
+ // Result is just a bytestream
+ desc.destType = r_Type::get_any_type("char");
+
+ return desc;
+}
+
+
+
+r_convDesc &r_Conv_CSV::convertFrom(const char *options) throw(r_Error)
+{
+ RMInit::logOut << "importing CSV data not yet implemented" << endl;
+ throw new r_Error(CONVERSIONFORMATNOTSUPPORTED);
+ return desc;
+}
+
+
+
+const char *r_Conv_CSV::get_name( void ) const
+{
+ return "csv";
+}
+
+
+r_Data_Format r_Conv_CSV::get_data_format( void ) const
+{
+ return r_CSV;
+}
+
+
+r_Convertor *r_Conv_CSV::clone( void ) const
+{
+ return new r_Conv_CSV(desc.src, desc.srcInterv, desc.baseType);
+}
diff --git a/conversion/csv.hh b/conversion/csv.hh
new file mode 100644
index 0000000..c4eed18
--- /dev/null
+++ b/conversion/csv.hh
@@ -0,0 +1,93 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: csv.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_CSV
+ *
+ * COMMENTS:
+ *
+ * Provides interface to convert data to other formats.
+ *
+*/
+
+#ifndef _R_CONV_CSV_HH_
+#define _R_CONV_CSV_HH_
+
+#include "conversion/convertor.hh"
+#include <ostream>
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ CSV convertor class.
+
+ Supported parameters are
+
+ \begin{tabular}{lcl}
+ comptype && string && the compression type to use (see below)\\
+ quality && int && quality parameter for JPEG compression\\
+ skiphuff && int && skipping parameter for Huffman coding\\
+ \end{tabular}
+
+ The compression type defaults to deflate but may be one of the
+ following
+
+ \begin{tabular}{ll}
+ none && no compression\\
+ rle && Run Length Coding\\
+ huffman && Huffman coding\\
+ deflate && ZIP deflate\\
+ \end{tabular}
+
+*/
+class r_Conv_CSV : public r_Convertor
+{
+ public:
+ /// constructor using an r_Type object. Exception if the type isn't atomic.
+ r_Conv_CSV( const char *src, const r_Minterval &interv, const r_Type *tp) throw(r_Error);
+ /// constructor using convert_type_e shortcut
+ r_Conv_CSV( const char *src, const r_Minterval &interv, int tp ) throw(r_Error);
+ /// destructor
+ ~r_Conv_CSV( void );
+
+ /// convert to CSV
+ virtual r_convDesc &convertTo( const char *options=NULL ) throw(r_Error);
+ /// convert from CSV
+ virtual r_convDesc &convertFrom( const char *options=NULL ) throw(r_Error);
+ /// cloning
+ virtual r_Convertor *clone( void ) const;
+ /// identification
+ virtual const char *get_name( void ) const;
+ virtual r_Data_Format get_data_format( void ) const;
+
+
+ private:
+ template <class baseType, class castType>
+ void print(std::ofstream &f, baseType* val, int *dims, int dim);
+
+};
+
+#endif
diff --git a/conversion/dem.cc b/conversion/dem.cc
new file mode 100644
index 0000000..09e801e
--- /dev/null
+++ b/conversion/dem.cc
@@ -0,0 +1,894 @@
+/*
+* 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: dem.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_DEM
+ *
+ * PURPOSE:
+ * Provides interface to convert data from/to Array format to/from DEM format.
+ *
+ * COMMENTS:
+ * For further support send a mail to comanl@yahoo.com
+ * - convertTo() writes a temp file; this should be omitted for performance reasons
+*/
+
+static const char rcsid[] = "@(#)conversion,r_Conv_DEM: $Id: dem.cc,v 1.10 2005/09/08 12:59:26 rasdev Exp $";
+
+#include "conversion/dem.hh"
+
+#include <float.h>
+#include <string>
+#include <cstring>
+#include <strstream>
+#include <sstream>
+#include <algorithm>
+
+using std::istringstream;
+using std::istrstream;
+using std::string;
+using namespace std;
+
+#include "raslib/rminit.hh"
+#include "raslib/parseparams.hh"
+#include "raslib/primitivetype.hh"
+
+
+const r_Dimension r_Conv_DEM::srcIntervDim=1;
+const r_Dimension r_Conv_DEM::destIntervDim=2;
+const r_ULong r_Conv_DEM::paramMin=6;
+const char* r_Conv_DEM::paramSep=",";
+const char* r_Conv_DEM::paramEq="=";
+const char* r_Conv_DEM::paramFlipX="flipx";
+const char* r_Conv_DEM::paramFlipY="flipy";
+const char* r_Conv_DEM::paramStartX="startx";
+const char* r_Conv_DEM::paramEndX="endx";
+const char* r_Conv_DEM::paramResX="resx";
+const char* r_Conv_DEM::paramStartY="starty";
+const char* r_Conv_DEM::paramEndY="endy";
+const char* r_Conv_DEM::paramResY="resy";
+
+const r_Double r_Conv_DEM::NULL_DB = 0.;
+const r_Double r_Conv_DEM::ZERO_DB = FLT_MIN;
+const r_Double r_Conv_DEM::ZERO_DEM = 0.;
+
+r_Conv_DEM::~r_Conv_DEM( void )
+{
+ //nothing to care for
+}
+
+void r_Conv_DEM::initGeoBBox( r_GeoBBox& cBBox )
+{
+ //flipy is selected by default
+ cBBox.flipy = 1;
+
+ //flipx is not selected by default
+ cBBox.flipx = 0;
+
+ //geo information are initialized by default to DBL_MAX
+ // FIXME: better defaults res=1, min=-MAX?
+ cBBox.startx = DBL_MAX;
+ cBBox.endx = DBL_MAX;
+ cBBox.resx = DBL_MAX;
+ cBBox.starty = DBL_MAX;
+ cBBox.endy = DBL_MAX;
+ cBBox.resy = DBL_MAX;
+}
+
+r_Conv_DEM::r_Conv_DEM(const char* source, const r_Minterval& lengthordomain, const r_Type* tp) throw(r_Error)
+ : r_Convertor(source, lengthordomain, tp, true)
+{
+ initGeoBBox(collBBox);
+}
+
+r_Conv_DEM::r_Conv_DEM(const char* source, const r_Minterval& lengthordomain, int tp) throw(r_Error)
+ : r_Convertor(source, lengthordomain, tp)
+{
+ initGeoBBox(collBBox);
+}
+
+bool
+r_Conv_DEM::decodeOptions(const char* options,
+ r_GeoBBox& cBBox) throw()
+{
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(" << (options?options:"NULL") << ")" << endl;
+
+ r_Parse_Params parseParams;
+
+ initGeoBBox(cBBox);
+
+ parseParams.add(paramFlipX, &cBBox.flipx, r_Parse_Params::param_type_int);
+ parseParams.add(paramFlipY, &cBBox.flipy, r_Parse_Params::param_type_int);
+ parseParams.add(paramStartX, &cBBox.startx, r_Parse_Params::param_type_double);
+ parseParams.add(paramEndX, &cBBox.endx, r_Parse_Params::param_type_double);
+ parseParams.add(paramResX, &cBBox.resx, r_Parse_Params::param_type_double);
+ parseParams.add(paramStartY, &cBBox.starty, r_Parse_Params::param_type_double);
+ parseParams.add(paramEndY, &cBBox.endy, r_Parse_Params::param_type_double);
+ parseParams.add(paramResY, &cBBox.resy, r_Parse_Params::param_type_double);
+
+ //process options
+ r_Long processRet=parseParams.process(options);
+ if(processRet < paramMin)
+ {
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(...) Error: Some required options are missing!" << endl;
+ return false;
+ }
+
+ //check if start,res,end are present
+ if(cBBox.startx == DBL_MAX)
+ {
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(...) Error: startx is not present!" << endl;
+ return false;
+ }
+
+ if(cBBox.starty == DBL_MAX)
+ {
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(...) Error: starty is not present!" << endl;
+ return false;
+ }
+
+ if(cBBox.endx == DBL_MAX)
+ {
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(...) Error: endx is not present!" << endl;
+ return false;
+ }
+
+ if(cBBox.endy == DBL_MAX)
+ {
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(...) Error: endy is not present!" << endl;
+ return false;
+ }
+
+ if(cBBox.resx == DBL_MAX)
+ {
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(...) Error: resx is not present!" << endl;
+ return false;
+ }
+
+ if(cBBox.resy == DBL_MAX)
+ {
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(...) Error: resy is not present!" << endl;
+ return false;
+ }
+
+
+ //check res
+ if(!cBBox.resx)
+ {
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(...) Error: resx is zero!" << endl;
+ return false;
+ }
+
+ if(!cBBox.resy)
+ {
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(...) Error: resy is zero!" << endl;
+ return false;
+ }
+
+ //check start >= end
+ if(cBBox.startx >= cBBox.endx )
+ {
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(...) Error: startx >= endx!" << endl;
+ return false;
+ }
+
+ if(cBBox.starty >= cBBox.endy)
+ {
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(...) Erorr: starty >= endy!" << endl;
+ return false;
+ }
+
+ //show parsed options
+ RMInit::logOut.setf(std::ios::fixed);
+ RMInit::logOut << "r_Conv_DEM::decodeOptions(...) parsed options:" << endl
+ << " " << paramFlipX << paramEq << cBBox.flipx
+ << " " << paramFlipY << paramEq << cBBox.flipy << endl
+ << " " << paramStartX << paramEq << cBBox.startx
+ << " " << paramEndX << paramEq << cBBox.endx
+ << " " << paramResX << paramEq << cBBox.resx << endl
+ << " " << paramStartY << paramEq << cBBox.starty
+ << " " << paramEndY << paramEq << cBBox.endy
+ << " " << paramResY << paramEq << cBBox.resy << endl;
+ return true;
+}
+
+string
+r_Conv_DEM::encodeOptions(const r_GeoBBox& cBBox) throw()
+{
+ std::ostringstream os;
+
+ os.str("");
+ os.setf(std::ios::fixed);
+ os << paramFlipX << paramEq << cBBox.flipx
+ << paramSep << paramFlipY << paramEq << cBBox.flipy
+ << paramSep << paramStartX << paramEq << cBBox.startx
+ << paramSep << paramEndX << paramEq << cBBox.endx
+ << paramSep << paramResX << paramEq << cBBox.resx
+ << paramSep << paramStartY << paramEq << cBBox.starty
+ << paramSep << paramEndY << paramEq << cBBox.endy
+ << paramSep << paramResY << paramEq << cBBox.resy;
+
+ RMInit::logOut << "r_Conv_DEM::encodeOptions(" << os.str() << ")" << endl;
+
+ return os.str();
+}
+
+void
+r_Conv_DEM::checkLimits() throw(r_Error)
+{
+ //show processed data
+ RMInit::logOut << "r_Conv_DEM::checkLimits() processed data:" << endl
+ << " minx=" << min.x << " miny=" << min.y << " minh=" << min.h << endl
+ << " maxx=" << max.x << " maxy=" << max.y << " maxh=" << max.h << endl;
+ // printf( "r_Conv_DEM::checkLimits() processed data: minx=%8G, miny=%8G, minh=%8G, maxx=%8G, maxy=%8G, maxh=%8G\n", min.x, min.y, min.h, max.x, max.y, max.h );
+
+ if(collBBox.startx > min.x)
+ {
+ RMInit::logOut << "r_Conv_DEM::checkLimits() startx( " << collBBox.startx << ") > min.x (" << min.x << " )!" << endl;
+ throw r_Error();
+ }
+ if(collBBox.endx < max.x)
+ {
+ RMInit::logOut << "r_Conv_DEM::checkLimits() endx( " << collBBox.endx << ") < max.x (" << max.x << " )!" << endl;
+ throw r_Error();
+ }
+
+ if(collBBox.starty > min.y)
+ {
+ RMInit::logOut << "r_Conv_DEM::checkLimits() starty( " << collBBox.starty << ") > min.y (" << min.y << " )!" << endl;
+ throw r_Error();
+ }
+
+ if(collBBox.endy < max.y)
+ {
+ RMInit::logOut << "r_Conv_DEM::checkLimits() endy( " << collBBox.endy << ") < max.y (" << max.y << " )!" << endl;
+ throw r_Error();
+ }
+}
+
+void
+r_Conv_DEM::readFromSrcStream() throw(r_Error)
+{
+ istrstream iFile(desc.src, desc.srcInterv[0].get_extent());
+ string currStrRow;
+ r_Long rowNo=0;
+ r_Double noResx, noResy;
+ DEMRow currRow, prevRow;
+
+ min.x=min.y=min.h=DBL_MAX;
+ max.x=max.y=max.h=-DBL_MAX;
+ demRows.clear();
+
+ //process the lines
+ while(!iFile.eof())
+ {
+ getline(iFile, currStrRow);
+ rowNo++;
+ if(currStrRow.empty())
+ {
+ // TALK( "r_Conv_DEM::readFromSrcStream() skipping empty line " << rowNo );
+ continue;
+ }
+ else
+ {
+ // have an input stream for analysing the current line
+ // (declaring this variable here allows to have a fresh one;
+ // had a reentrance problem with followup lines -- PB 2005-sep-08)
+ istringstream icurrRow;
+ icurrRow.str(currStrRow);
+
+ //decode x
+ icurrRow >> currRow.x;
+ if(!icurrRow)
+ {
+ RMInit::logOut << "Error in r_Conv_DEM::readFromSrcStream():: unable to decode x in line " << rowNo << ", skipping line: " << currStrRow << endl;
+ continue;
+ }
+
+ //decode y
+ icurrRow >> currRow.y;
+ if(!icurrRow)
+ {
+ RMInit::logOut << "Error in r_Conv_DEM::readFromSrcStream():: unable to decode y in line " << rowNo << ", skipping line: " << currStrRow << endl;
+ continue;
+ }
+
+ //decode h
+ icurrRow >> currRow.h;
+ if(!icurrRow)
+ {
+ RMInit::logOut << "Error in r_Conv_DEM::readFromSrcStream():: unable to decode h in line " << rowNo << ", skipping line: " << currStrRow << endl;
+ continue;
+ }
+
+ //update to support NULL value: 0. (real value) goes in FLT_MIN(db value)
+ //because 0.(db value) represent NULL(real value). When we do export we skip NULL values.
+ if(currRow.h == ZERO_DEM)
+ currRow.h=ZERO_DB;
+
+ //FIXME we ignore this check, because it may happen to have a incomplet dem
+ /*
+ //check if we have resx, resy
+ noResx=currRow.x/collBBox.resx;
+ if((currRow.x - noResx*collBBox.resx) > 0.)
+ {
+ RMInit::logOut << "r_Conv_DEM::readFromSrcStream() resolution for x on line " <<
+ rowNo << " is not " << collBBox.resx << " !" << endl;
+ throw r_Error();
+ }
+ noResy=currRow.y/collBBox.resy;
+ if((currRow.y - noResy*collBBox.resy) > 0.)
+ {
+ RMInit::logOut << "r_Conv_DEM::readFromSrcStream() resolution for y on line " <<
+ rowNo << " is not " << collBBox.resy << " !" << endl;
+ throw r_Error();
+ }
+ */
+
+ //compute min, max for x,y,z
+ min.x=std::min<r_Double>(min.x, currRow.x);
+ min.y=std::min<r_Double>(min.y, currRow.y);
+ min.h=std::min<r_Double>(min.h, currRow.h);
+ max.x=std::max<r_Double>(max.x, currRow.x);
+ max.y=std::max<r_Double>(max.y, currRow.y);
+ max.h=std::max<r_Double>(max.h, currRow.h);
+
+ //store currRow
+ demRows.push_back(currRow);
+ }//end if(currStrRow.empty())
+
+ }//end reading src stream
+
+ if(demRows.empty())
+ {
+ // TALK( "r_Conv_DEM::readFromSrcStream() desc.src stream empty." );
+ throw r_Error();
+ }
+
+ // std::cout << "r_Conv_DEM::readFromSrcStream(): x=" << min.x << ":" << max.x << ", y=" << min.y << ":" << max.y << endl;
+
+ //check limits
+ checkLimits();
+}
+
+
+void
+r_Conv_DEM::readToSrcStream() throw(r_Error)
+{
+ r_Long x=0, y=0;
+ r_Long xlow=0, ylow=0;
+ r_Long xhigh=0, yhigh=0;
+ DEMRow currRow;
+ r_Bytes typeSize=0;
+ r_Long offset=0;
+ char* buffer=NULL;
+
+ //initialize
+ xlow=desc.srcInterv[0].low();
+ ylow=desc.srcInterv[1].low();
+
+ xhigh=desc.srcInterv[0].high();
+ yhigh=desc.srcInterv[1].high();
+
+ //compute min & max
+ if (collBBox.flipx)
+ {
+ min.x=collBBox.endx - xhigh*collBBox.resx;
+ max.x=collBBox.endx - xlow*collBBox.resx;
+ }
+ else
+ {
+ min.x=collBBox.startx + xlow*collBBox.resx;
+ max.x=collBBox.startx + xhigh*collBBox.resx;
+ }
+
+ if(collBBox.flipy)
+ {
+ min.y=collBBox.endy - yhigh*collBBox.resy;
+ max.y=collBBox.endy - ylow*collBBox.resy;
+ }
+ else
+ {
+ min.y=collBBox.starty + ylow*collBBox.resy;
+ max.y=collBBox.starty + yhigh*collBBox.resy;
+ }
+
+ min.h=DBL_MAX;
+ max.h=-DBL_MAX;
+
+ //check limits
+ checkLimits();
+
+ //prepare container
+ demRows.clear();
+ typeSize=((r_Primitive_Type*)desc.srcType)->size();
+ buffer=new char[typeSize];
+ if(!buffer)
+ {
+ RMInit::logOut << "r_Conv_DEM::readToSrcStream() unable to claim memory !" << endl;
+ throw r_Ememory_allocation();
+ }
+ for(y=ylow; y<=yhigh; y++)
+ {
+ if(collBBox.flipy)
+ currRow.y=collBBox.endy - y*collBBox.resy;
+ else
+ currRow.y=collBBox.starty + y*collBBox.resy;
+
+ for(x=xlow; x<=xhigh; x++)
+ {
+ if(collBBox.flipx)
+ currRow.x=collBBox.endx - x*collBBox.resx;
+ else
+ currRow.x=collBBox.startx + x*collBBox.resx;
+ offset=desc.srcInterv.cell_offset(r_Point(x,y))*typeSize;
+ memcpy(buffer, &desc.src[offset], typeSize);
+
+ switch(desc.srcType->type_id())
+ {
+ case r_Type::BOOL:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_boolean(buffer);
+ break;
+ case r_Type::CHAR:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_char(buffer);
+ break;
+ case r_Type::OCTET:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_octet(buffer);
+ break;
+ case r_Type::SHORT:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_short(buffer);
+ break;
+ case r_Type::USHORT:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_ushort(buffer);
+ break;
+ case r_Type::LONG:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_long(buffer);
+ break;
+ case r_Type::ULONG:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_ulong(buffer);
+ break;
+ case r_Type::FLOAT:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_float(buffer);
+ break;
+ case r_Type::DOUBLE:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_double(buffer);
+ break;
+ default:
+ //write message to log
+ RMInit::logOut << "r_Conv_DEM::readToSrcStream() srcType (" << desc.srcType->type_id() << ") unsupported !" << endl;
+ //clean up
+ if(buffer)
+ {
+ delete[] buffer;
+ buffer=NULL;
+ }
+ //report error
+ throw r_Error();
+ break;
+ }
+ min.h=std::min<r_Double>(min.h, currRow.h);
+ max.h=std::max<r_Double>(max.h, currRow.h);
+ demRows.push_back(currRow);
+ }
+ }
+
+ //clean up
+ if(buffer)
+ {
+ delete[] buffer;
+ buffer=NULL;
+ }
+
+ if(demRows.empty())
+ {
+ RMInit::logOut << "r_Conv_DEM::readToSrcStream() src stream is empty !" << endl;
+ throw r_Error();
+ }
+
+ RMInit::logOut << "r_Conv_DEM::readToSrcStream() processed interval [" << xlow << ":" << xhigh << "," << ylow << ":" << yhigh << "]" << endl;
+}
+
+
+void
+r_Conv_DEM::writeFromDestStream() throw(r_Error)
+{
+ DEMRowVec::const_iterator iter, iterEnd;
+ r_Long xdim, ydim, offset;
+ r_Point currPt(destIntervDim);
+ r_Bytes typeSize=0;
+
+
+ //FIXME here we should modify for other type support
+ if(desc.destType->type_id() != r_Type::DOUBLE)
+ {
+ RMInit::logOut << "r_Conv_DEM::writeFromDestStream() destType (" << desc.destType->type_id()
+ << ") is not " << r_Type::DOUBLE << " !" << endl;
+ throw r_Error();
+ }
+
+ xdim=desc.destInterv[0].get_extent();
+ ydim=desc.destInterv[1].get_extent();
+ iter=demRows.begin();
+ iterEnd=demRows.end();
+ typeSize=((r_Primitive_Type*)desc.destType)->size();
+
+ //FIXME correction for strange effect of r_Long cast with 1e-6
+ while(iter != iterEnd)
+ {
+ if(collBBox.flipx)
+ currPt[0]=(collBBox.endx - iter->x)/collBBox.resx + 1e-6;
+ else
+ currPt[0]=(iter->x - collBBox.startx)/collBBox.resx + 1e-6;
+ if(collBBox.flipy)
+ currPt[1]=(collBBox.endy - iter->y)/collBBox.resy + 1e-6;
+ else
+ currPt[1]=(iter->y - collBBox.starty)/collBBox.resy + 1e-6;
+ ((r_Primitive_Type*)desc.destType)->set_double(&desc.dest[desc.destInterv.cell_offset(currPt)*typeSize], iter->h);
+ ++iter;
+ }
+
+ RMInit::logOut << "r_Conv_DEM::writeFromDestStream() processed " << xdim << " x " << ydim << " elements." << endl;
+}
+
+void
+r_Conv_DEM::writeToDestStream(ofstream& oFile) throw(r_Error)
+{
+ DEMRowVec::const_iterator iter, iterEnd;
+ r_Double currH;
+
+ if(!oFile.is_open())
+ {
+ RMInit::logOut << "r_Conv_DEM::writeToDestStream() oFile is not opened !" << endl;
+ throw r_Error();
+ }
+ oFile.setf(std::ios::fixed);
+
+ iter=demRows.begin();
+ iterEnd=demRows.end();
+ while(iter != iterEnd)
+ {
+ //update to support NULL value: 0. (real value) goes in FLT_MIN(db value)
+ //because 0.(db value) represent NULL(real value). When we do export we skip NULL values.
+ currH = iter->h;
+ if(currH != NULL_DB)
+ {
+ //FIXME we have to implement different here when we change server scale algorithm
+ if(currH == ZERO_DB)
+ currH = ZERO_DEM;
+ oFile << iter->x << "\t" << iter->y << "\t" << currH << endl;
+ }
+ ++iter;
+ }
+}
+
+r_convDesc&
+r_Conv_DEM::convertFrom(const char* options) throw (r_Error)
+{
+ bool hasSrcType=true;
+
+ RMInit::logOut << "r_Conv_DEM::convertFrom(" << (options?options:"NULL") << ")" << endl;
+
+ if(!desc.srcType)
+ {
+ desc.srcType=get_external_type(desc.baseType);
+ hasSrcType=false;
+ }
+
+ try
+ {
+ RMInit::logOut << "r_Conv_DEM::convertFrom(...) src interval=" << desc.srcInterv << endl;
+ RMInit::logOut << "r_Conv_DEM::convertFrom(...) src type=" << desc.srcType->type_id() << endl;
+
+ //check options
+ if(!decodeOptions(options, collBBox))
+ {
+ RMInit::logOut << "Error in r_Conv_DEM::convertFrom(): illegal option string: " << (options?options:"(null)") << endl;
+ throw r_Error();
+ }
+
+ //check desc.srcInterv.dimension
+ if(desc.srcInterv.dimension() != srcIntervDim)
+ {
+ RMInit::logOut << "r_Conv_DEM::convertFrom(" << (options?options:"NULL")
+ << ") desc.srcInterv dimension (" << desc.srcInterv.dimension()
+ << " != " << srcIntervDim << " !" << endl;
+ throw r_Error();
+ }
+
+ //check srcType
+ if(!desc.srcType->isPrimitiveType())
+ {
+ RMInit::logOut << "r_Conv_DEM::convertFrom(" << (options?options:"NULL")
+ << ") desc.srcType (" << desc.srcType->type_id()
+ << ") not supported, only primitive types !" << endl;
+ throw r_Error();
+ }
+
+ if(desc.srcType->isComplexType())
+ {
+ RMInit::logOut << "r_Conv_DEM::convertFrom(" << (options?options:"NULL")
+ << ") desc.srcType (" << desc.srcType->type_id()
+ << ") not supported !" << endl;
+ throw r_Error();
+ }
+
+ //read src stream
+ readFromSrcStream();
+
+ //convert from DEM to marray
+ //--computing the marray domain
+ desc.destInterv = r_Minterval(destIntervDim);
+
+ //FIXME correction for strange efect of r_Long cast with 1e-6
+ if(collBBox.flipx)
+ desc.destInterv << r_Sinterval((r_Long)((collBBox.endx - max.x)/collBBox.resx + 1e-6),
+ (r_Long)((collBBox.endx - min.x)/collBBox.resx + 1e-6));
+ else
+ desc.destInterv << r_Sinterval((r_Long)((min.x - collBBox.startx)/collBBox.resx + 1e-6),
+ (r_Long)((max.x - collBBox.startx)/collBBox.resx + 1e-6));
+ if(collBBox.flipy)
+ desc.destInterv << r_Sinterval((r_Long)((collBBox.endy - max.y)/collBBox.resy + 1e-6),
+ (r_Long)((collBBox.endy - min.y)/collBBox.resy + 1e-6));
+ else
+ desc.destInterv << r_Sinterval((r_Long)((min.y - collBBox.starty)/collBBox.resy + 1e-6),
+ (r_Long)((max.y - collBBox.starty)/collBBox.resy + 1e-6));
+
+ RMInit::logOut << "r_Conv_DEM::convertFrom(...) dest interval=" << desc.destInterv << endl;
+
+ //--creating the resulting type
+ desc.destType = new r_Primitive_Type("Double", r_Type::DOUBLE);
+ RMInit::logOut << "r_Conv_DEM::convertFrom(...) dest type=" << desc.destType->type_id() << endl;
+
+ //--claim memory for result
+ desc.dest = (char*)mystore.storage_alloc(desc.destInterv.cell_count() * ((r_Primitive_Type*)desc.destType)->size());
+ if(desc.dest==NULL)
+ {
+ RMInit::logOut << "r_Conv_DEM::convertFrom(" << (options?options:"NULL")
+ << ") unable to claim memory !" << endl;
+ throw r_Ememory_allocation();
+ }
+ memset(desc.dest, 0, desc.destInterv.cell_count() * ((r_Primitive_Type*)desc.destType)->size());
+
+ //--write parsed data in desc.dest
+ writeFromDestStream();
+ }
+ catch(r_Error& err)
+ {
+ //cleanup
+ if(!hasSrcType)
+ {
+ delete desc.srcType;
+ desc.srcType=NULL;
+ }
+
+ //desc.destType
+ if(desc.destType)
+ {
+ delete desc.destType;
+ desc.destType=NULL;
+ }
+
+ //desc.dest
+ if(desc.dest)
+ {
+ mystore.storage_free(desc.dest);
+ desc.dest=NULL;
+ }
+
+ //report error
+ throw;
+ }
+
+ //cleanup
+ if(!hasSrcType)
+ {
+ delete desc.srcType;
+ desc.srcType=NULL;
+ }
+
+ //return result
+ return desc;
+}
+
+
+r_convDesc&
+r_Conv_DEM::convertTo(const char* options) throw (r_Error)
+{
+ bool hasSrcType=true;
+
+ char* pTempFileName=NULL; // name of temp file
+ string tempFileName; // duplicate of temp file name -- heaven knows why
+ ofstream oFile; // for writing out file
+ FILE* pFile=NULL; // for reading back file
+ size_t lenFile=0; // size of file as read
+
+ RMInit::logOut << "r_Conv_DEM::convertTo(" << (options?options:"NULL") << ")" << endl;
+
+ try
+ {
+ if(!desc.srcType)
+ {
+ desc.srcType=get_external_type(desc.baseType);
+ hasSrcType=false;
+ }
+
+ RMInit::logOut << "r_Conv_DEM::convertTo(...) src interval=" << desc.srcInterv << endl;
+ RMInit::logOut << "r_Conv_DEM::convertTo(...) src type=" << desc.srcType->type_id() << endl;
+
+ //check options
+ if(!decodeOptions(options, collBBox))
+ throw r_Error();
+
+ if(!desc.srcType->isPrimitiveType())
+ {
+ RMInit::logOut << "r_Conv_DEM::convertTo(" << (options?options:"NULL")
+ << ") desc.srcType (" << desc.srcType->type_id()
+ << ") not supported, only primitive types !" << endl;
+ throw r_Error();
+ }
+ if(desc.srcType->isComplexType())
+ {
+ RMInit::logOut << "r_Conv_DEM::convertTo(" << (options?options:"NULL")
+ << ") desc.srcType (" << desc.srcType->type_id()
+ << ") not supported !" << endl;
+ throw r_Error();
+ }
+
+ //read src data
+ readToSrcStream();
+
+ //convert from marray to DEM;
+ //--create the temp file
+ //FIXME for multithread application
+ pTempFileName=tmpnam(NULL);
+ if(pTempFileName==NULL)
+ {
+ RMInit::logOut << "r_Conv_DEM::convertTo(" << (options?options:"NULL")
+ << ") desc.srcType (" << desc.srcType->type_id()
+ << ") unable to generate a tempory file !" << endl;
+ throw r_Error();
+ }
+
+ tempFileName=pTempFileName;
+ oFile.open(tempFileName.c_str());
+ if(!oFile.is_open())
+ {
+ RMInit::logOut << "r_Conv_DEM::convertTo(" << (options?options:"NULL")
+ << ") desc.srcType (" << desc.srcType->type_id()
+ << ") unable to open the tempory file !" << endl;
+ throw r_Error();
+ }
+
+ RMInit::logOut << "r_Conv_DEM::convertTo(...) temp file=" << tempFileName << endl;
+
+ //--get DEM format
+ writeToDestStream(oFile);
+ oFile.close();
+
+ //--accessing the temp file
+ if ((pFile = fopen(tempFileName.c_str(), "rb")) == NULL)
+ {
+ RMInit::logOut << "r_Conv_DEM::convertTo(): unable to read back file." << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ fseek(pFile, 0, SEEK_END);
+ lenFile = ftell(pFile);
+ RMInit::logOut << "r_Conv_DEM::convertTo(...) dest len=" << lenFile << endl;
+
+ if (!lenFile)
+ {
+ RMInit::logOut << "r_Conv_DEM::convertTo(): source contains only NULL values." << endl;
+ throw r_Error( E_DEM_EMPTY );
+ }
+
+ //--creating the resulting type
+ desc.destType = new r_Primitive_Type("Char", r_Type::CHAR);
+
+ //--computing the marray domain
+ desc.destInterv = r_Minterval(srcIntervDim);
+ desc.destInterv << r_Sinterval((r_Long)0, (r_Long)lenFile - 1);
+
+ RMInit::logOut << "r_Conv_DEM::convertTo(...) dest interval=" << desc.destInterv << endl;
+ RMInit::logOut << "r_Conv_DEM::convertTo(...) dest type=" << desc.destType->type_id() << endl;
+
+ //--claim memory for desc.dest
+ desc.dest = (char*)mystore.storage_alloc(lenFile);
+ if(desc.dest==NULL)
+ {
+ RMInit::logOut << "r_Conv_DEM::convertTo(" << (options?options:"NULL")
+ << ") unable to claim memory !" << endl;
+ throw r_Ememory_allocation();
+ }
+ memset(desc.dest, 0, lenFile);
+
+ //--store data in desc.dest
+ fseek(pFile, 0, SEEK_SET);
+ fread(desc.dest, 1, lenFile, pFile);
+
+ //clean up
+ fclose(pFile);
+ pFile=NULL;
+ remove(pTempFileName);
+ }
+ catch(r_Error& err)
+ {
+ //cleanup
+ if(!hasSrcType)
+ {
+ delete desc.srcType;
+ desc.srcType=NULL;
+ }
+
+ //desc.destType
+ if(desc.destType)
+ {
+ delete desc.destType;
+ desc.destType=NULL;
+ }
+
+ //desc.dest
+ if(desc.dest)
+ {
+ mystore.storage_free(desc.dest);
+ desc.dest=NULL;
+ }
+
+ // close & remove file, if not done previously
+ fclose(pFile);
+ pFile=NULL;
+ remove(pTempFileName);
+
+ //rethrow error
+ throw;
+ }
+
+ //clean up
+ if(!hasSrcType)
+ {
+ delete desc.srcType;
+ desc.srcType=NULL;
+ }
+
+ //return result
+ return desc;
+}
+
+const char*
+r_Conv_DEM::get_name() const throw()
+{
+ return get_name_from_data_format(r_DEM);
+}
+
+r_Data_Format
+r_Conv_DEM::get_data_format() const throw()
+{
+ return r_DEM;
+}
+
+r_Convertor*
+r_Conv_DEM::clone() const throw(r_Error)
+{
+ return new r_Conv_DEM(desc.src, desc.srcInterv, desc.srcType);
+}
diff --git a/conversion/dem.hh b/conversion/dem.hh
new file mode 100644
index 0000000..ccfdbef
--- /dev/null
+++ b/conversion/dem.hh
@@ -0,0 +1,187 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: dem.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_DEM
+ *
+ * PURPOSE:
+ * Provides interface to convert data to other formats.
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_CONV_DEM_HH_
+#define _R_CONV_DEM_HH_
+
+#include <sstream>
+#include <vector>
+#include <string>
+#include <cstdio>
+using std::vector;
+using std::ofstream;
+using std::string;
+
+#include "conversion/convertor.hh"
+#include "raslib/odmgtypes.hh"
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ DEM convertor class.
+
+ Supported parameters are
+
+ \begin{tabular}{lcl}
+ {\tt flipx} && int && flip image flag on x axis, default 0\\
+ {\tt flipy} && int && flip image flag on y axis, default 1\\
+ {\tt startx} && double && start value on x axis \\
+ {\tt endx} && double && end value on x axis \\
+ {\tt resx} && double && resolution on x axis \\
+ {\tt starty} && double && start value on y axis \\
+ {\tt endy} && double && end value on y axis \\
+ {\tt resy} && double && resolution on y axis \\
+ \end{tabular}
+
+ The "flipx" parameter is a flag for mirroring the image on x axis.
+ The "flipy" parameter is a flag for mirroring the image on y axis.
+ [startx:endx, starty:endy] represents the geographical bounding box
+ of the whole image. The corresponding pixel bounding box is calculated
+ as follows:
+ if flipy is disabled:
+ [(minx-startx)/resx:(maxx-startx)/resx, (miny-starty)/resy:(maxy-starty)/resy]
+ else
+ [(minx-startx)/resx:(maxx-startx)/resx, (endy-maxy)/resy:(endy-miny)/resy]
+
+ if flipx is disabled:
+ [(minx-startx)/resx:(maxx-startx)/resx, (miny-starty)/resy:(maxy-starty)/resy]
+ else
+ [(endx-maxx)/resx:(endx-minx)/resx, (miny-starty)/resy:(maxy-starty)/resy]
+
+ The pairs (startx, endx, resx), (starty, endy, resy) are for the whole image(e.g image bounding)
+ and the pairs (minx,maxx, resx), (miny, maxy, resy) are for the current part of image.
+ They are used to compute the position of current image in RasDaMan coordinates.
+*/
+
+// r_Error code for "empty DEM result generated"; this def should go into a central list
+// -- PB 2003-dec-03
+#define E_DEM_EMPTY 3000
+
+class r_Conv_DEM : public r_Convertor
+{
+ public:
+ // constants to handle NULL
+ static const r_Double NULL_DB;
+ static const r_Double ZERO_DB;
+ static const r_Double ZERO_DEM;
+
+ //inner class for convertor parameters
+ class r_GeoBBox
+ {
+ public:
+ r_Double startx, endx, resx;
+ r_Double starty, endy, resy;
+ r_ULong flipy, flipx;
+ };
+
+ r_Conv_DEM(const char* source, const r_Minterval& lengthordomain, const r_Type* tp) throw(r_Error);
+
+ r_Conv_DEM(const char* source, const r_Minterval& lengthordomain, int tp) throw(r_Error);
+
+ r_convDesc& convertFrom(const char* options = NULL) throw (r_Error);
+
+ r_convDesc& convertTo(const char* options = NULL) throw (r_Error);
+
+ const char* get_name() const throw();
+
+ r_Data_Format get_data_format() const throw();
+
+ r_Convertor* clone() const throw(r_Error);
+
+ /// dimension of src domain accepted as input in convertFrom
+ static const r_Dimension srcIntervDim;
+
+ /// dimension of dest domain accepted as input in convertTo
+ static const r_Dimension destIntervDim;
+
+ /// decode convertor options
+ static bool decodeOptions( const char* options,
+ r_GeoBBox& collBBox) throw();
+
+ /// encode convertor options
+ static string encodeOptions(const r_GeoBBox& collBBox) throw();
+
+ /// destructor
+ virtual ~r_Conv_DEM( void );
+
+ /// init convertor parameters to default value
+ static void initGeoBBox( r_GeoBBox& cBBox );
+
+ private:
+
+
+ /// check limits before converting
+ void checkLimits() throw(r_Error);
+
+ ///i/o src/dest stream
+ void readFromSrcStream() throw(r_Error);
+ void readToSrcStream() throw(r_Error);
+ void writeFromDestStream() throw(r_Error);
+ void writeToDestStream(ofstream& oFile) throw(r_Error);
+
+ /// parameters
+ r_GeoBBox collBBox;
+
+ /// class constants
+ static const r_ULong paramMin;
+ static const char* paramSep;
+ static const char* paramEq;
+ static const char* paramFlipX;
+ static const char* paramFlipY;
+ static const char* paramStartX;
+ static const char* paramEndX;
+ static const char* paramResX;
+ static const char* paramStartY;
+ static const char* paramEndY;
+ static const char* paramResY;
+
+
+ /// internal data
+ class DEMRow
+ {
+ public:
+ r_Double x,y,h;
+ };
+
+ typedef vector<DEMRow> DEMRowVec;
+
+ DEMRow min, max;
+ DEMRowVec demRows;
+
+ };
+
+#endif
+
diff --git a/conversion/des.cc b/conversion/des.cc
new file mode 100644
index 0000000..a6d9843
--- /dev/null
+++ b/conversion/des.cc
@@ -0,0 +1,118 @@
+/*
+* 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>.
+*/
+
+#include <iostream>
+#include <fstream>
+
+#include "des.h"
+#include "nitf.h"
+#include "utilities.h"
+
+using namespace std;
+using namespace RasNITF;
+
+des::des(){
+
+ m_desshf = NULL;
+ m_desdata = NULL;
+ data_length = 0;
+ header_length = 0;
+}
+
+des::~des(){
+
+ if(m_desshf != NULL){
+ delete m_desshf;
+ m_desshf = NULL;
+ }
+
+ if(m_desdata != NULL){
+ delete m_desdata;
+ m_desdata = NULL;
+ }
+
+}
+
+int des::read_file(istream &hNITF, long desh_length, long des_length){
+
+ int charsread = 0;
+
+ header_length=desh_length;
+
+ charsread += read_verify2(hNITF, m_de, 2 + 25 + 2 + 167);
+
+ //if TRE_OF read teh next two
+ if(strncmp(m_destag,"TRE_OVERFLOW",12)==0) {
+ charsread += read_verify2(hNITF, m_desoflw, 6+3);
+ }
+
+ charsread += read_verify2(hNITF, m_desshl, 4);
+ n_desshl = charptrtolong(m_desshl,4);
+
+ if (n_desshl > 0) {
+ m_desshf = new char[n_desshl];
+ if(m_desshf == NULL) cerr<<"ERROR: could not allocate memory";
+ charsread += read_verify2(hNITF, m_desshf, n_desshl);
+ }
+
+ m_desdata = new char[des_length];
+ charsread += read_verify2(hNITF, m_desdata, des_length);
+ data_length = des_length;
+
+ return charsread;
+}
+
+int des::write_file(ofstream &fNITF){
+
+ fNITF.write(m_de, 2);
+ fNITF.write(m_destag, 25);
+ fNITF.write(m_desver, 2);
+ fNITF.write(m_dessg, 167);
+
+ if(strncmp(m_destag,"TRE_OVERFLOW",12)==0) {
+ fNITF.write(m_desoflw, 6);
+ fNITF.write(m_desitem, 3);
+ }
+
+ fNITF.write( m_desshl, 4);
+
+ if (n_desshl > 0) {
+ fNITF.write(m_desshf, n_desshl);
+ }
+
+ if( m_desdata != NULL) {
+ fNITF.write( m_desdata, data_length);
+ }
+
+ //TODO
+ return 0;
+
+}
+
+string des::get_ld() const {
+ return des_dl;
+}
+
+string des::get_ldsh() const {
+ return des_hl;
+}
diff --git a/conversion/des.h b/conversion/des.h
new file mode 100644
index 0000000..358ad5e
--- /dev/null
+++ b/conversion/des.h
@@ -0,0 +1,67 @@
+/*
+* 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>.
+*/
+
+
+#ifndef __RASNITF_DES_H
+#define __RASNITF_DES_H
+
+#include <vector>
+#include <iostream>
+#include <fstream>
+
+namespace RasNITF
+{
+
+class des {
+
+ char m_de[2];
+ char m_destag[25];
+ char m_desver[2];
+ char m_dessg[167];
+ char m_desoflw[6];
+ char m_desitem[3];
+ char m_desshl[4];
+ char *m_desshf;
+ char *m_desdata;
+
+ int header_length;
+ long n_desshl;
+ int data_length;
+ int des_header_length;
+
+ std::string des_hl ;
+ std::string des_dl ;
+
+ public:
+
+ des();
+ ~des();
+ int read_file(std::istream &,long,long);
+ int write_file(std::ofstream &);
+ std::string get_ld() const;
+ std::string get_ldsh() const;
+
+};
+
+}
+#endif
diff --git a/conversion/ecw.cc b/conversion/ecw.cc
new file mode 100644
index 0000000..3035e28
--- /dev/null
+++ b/conversion/ecw.cc
@@ -0,0 +1,339 @@
+/*
+* 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>.
+*/
+
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/parseparams.hh"
+#include "raslib/mitera.hh"
+#include "raslib/minterval.hh"
+#include "raslib/primitivetype.hh"
+#include "ecw.hh"
+#include "convertor.hh"
+#include "convfactory.hh"
+
+#ifdef ECW
+#include "ecwmemfs.hh"
+#include "NCSECWClient.h"
+#include "NCSErrors.h"
+
+NCSError memOpen(char *szFileName, void **ppClientData)
+ {
+ RMDBGENTER(5, RMDebug::module_conversion, "ECWMem", "memOpen(" << szFileName << ", fd)");
+ MemoryFileSystem* myMem = new MemoryFileSystem();
+ *ppClientData = (void*)myMem;
+ MemoryFileSystem::m_Error err = MemoryFileSystem::No_Error;
+ err = myMem->open(szFileName);
+ RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memOpen(" << szFileName << ", fd) " << err);
+ if (err == MemoryFileSystem::No_Error)
+ return NCS_SUCCESS;
+ else
+ return NCS_FILE_OPEN_FAILED;
+ }
+
+NCSError memClose(void *pClientData)
+ {
+ RMDBGENTER(5, RMDebug::module_conversion, "ECWMem", "memClose(fd)");
+ MemoryFileSystem::m_Error err = MemoryFileSystem::No_Error;
+ err = ((MemoryFileSystem*)pClientData)->close();
+ if (err == MemoryFileSystem::No_Error)
+ {
+ delete pClientData;
+ RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memClose(fd) OK");
+ return NCS_SUCCESS;
+ }
+ else {
+ RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memClose(fd) Already closed");
+ return NCS_FILE_CLOSE_ERROR;
+ }
+ }
+
+NCSError memRead(void *pClientData, void *pBuffer, UINT32 nLength)
+ {
+ RMDBGENTER(5, RMDebug::module_conversion, "ECWMem", "memRead(fd, buffer, " << nLength << ")");
+ MemoryFileSystem::m_Error err = ((MemoryFileSystem*)pClientData)->read(pBuffer, nLength);
+ if (err == MemoryFileSystem::No_Error)
+ {
+ RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memRead(fd, buffer, " << nLength << ") OK");
+ return NCS_SUCCESS;
+ }
+ else {
+ RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memRead(fd, buffer, " << nLength << ") ERROR");
+ return NCS_FILE_SEEK_ERROR;
+ }
+ }
+
+NCSError memSeek(void *pClientData, UINT64 nOffset)
+ {
+ RMDBGENTER(5, RMDebug::module_conversion, "ECWMem", "memSeek(fd, " << nOffset << ")");
+ MemoryFileSystem::m_Error err = ((MemoryFileSystem*)pClientData)->seek(nOffset);
+ if (err == MemoryFileSystem::No_Error)
+ {
+ RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memSeek(fd, " << nOffset << ") OK");
+ return NCS_SUCCESS;
+ }
+ else {
+ RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memSeek(fd, " << nOffset << ") ERROR");
+ return NCS_FILE_SEEK_ERROR;
+ }
+ }
+
+NCSError memTell(void *pClientData, UINT64 *pOffset)
+ {
+ RMDBGENTER(5, RMDebug::module_conversion, "ECWMem", "memTell(fd, " << *pOffset << ")");
+ *pOffset = ((MemoryFileSystem*)pClientData)->tell();
+ RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memTell(fd, " << *pOffset << ")");
+ return NCS_SUCCESS;
+ }
+#endif
+
+void
+r_Conv_ECW::initECW()
+ {
+ RMDBGONCE(5, RMDebug::module_conversion, "r_Conv_ECW", "initECW()");
+ if(params ==NULL)
+ {
+ params = new r_Parse_Params(2);
+ }
+ }
+
+r_Conv_ECW::r_Conv_ECW(const char* source, const r_Minterval& lengthordomain, const r_Type* tp) throw(r_Error)
+ : r_Convertor(source, lengthordomain, tp, true)
+ {
+ RMDBGONCE(5, RMDebug::module_conversion, "r_Conv_ECW", "r_Conv_ECW(source, " << lengthordomain << ", " << tp->name() << ")");
+ initECW();
+ }
+
+r_Conv_ECW::r_Conv_ECW(const char* source, const r_Minterval& lengthordomain, int tp) throw(r_Error)
+ : r_Convertor(source, lengthordomain, tp)
+ {
+ RMDBGONCE(5, RMDebug::module_conversion, "r_Conv_ECW", "r_Conv_ECW(source, " << lengthordomain << ", " << tp << ")");
+ initECW();
+ }
+
+r_convDesc&
+r_Conv_ECW::convertFrom(const char* options) throw (r_Error)
+ {
+#ifdef ECW
+ RMDBGENTER(5, RMDebug::module_conversion, "r_Conv_ECW", "convertFrom(" << ((options)? options : "NULL") << ")");
+ int windowx = 1000;
+ int windowy = 1000;
+ params->add("windowx", &windowx, r_Parse_Params::param_type_int);
+ params->add("windowy", &windowy, r_Parse_Params::param_type_int);
+ params->process(options);
+ RMDBGMIDDLE(5, RMDebug::module_conversion, "r_Conv_ECW", "window x " << windowx);
+ RMDBGMIDDLE(5, RMDebug::module_conversion, "r_Conv_ECW", "window y " << windowy);
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ case ctype_char:
+ case ctype_uint8:
+ break;
+ case ctype_rgb:
+ break;
+ default:
+ RMInit::logOut << "r_Conv_ECW unknown base type!" << std::endl;
+ throw r_Error(COMPRESSIONFAILED);
+ }
+ NCSFileView *pNCSFileView = NULL;
+ NCSFileViewFileInfo *pNCSFileInfo = NULL;
+
+ NCSError eError = NCS_SUCCESS;
+ eError = NCSecwSetIOCallbacks(memOpen, memClose, memRead, memSeek, memTell);
+ if (eError != NCS_SUCCESS)
+ {
+ RMInit::logOut << "Error = " << NCSGetErrorText(eError) << std::endl;
+ throw r_Error(COMPRESSIONFAILED);
+ }
+ UINT8 **p_p_output_line = NULL;
+ UINT8 *p_output_buffer = NULL;
+ UINT32 x_size = 0;
+ UINT32 y_size = 0;
+ UINT32 number_x = 0;
+ UINT32 number_y = 0;
+ UINT32 start_x = 0;
+ UINT32 start_y = 0;
+ UINT32 end_x = 0;
+ UINT32 end_y = 0;
+ UINT32 band = 0;
+ UINT32 nBands = 0;
+ MemoryFileSystem::memorySrc = desc.src;
+ MemoryFileSystem::memorySrcLength = desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1;
+ eError = NCScbmOpenFileView((char*)MemoryFileSystem::memorySrcName, &pNCSFileView, NULL);
+
+ if (eError != NCS_SUCCESS)
+ {
+ RMInit::logOut << "Error = " << NCSGetErrorText(eError) << std::endl;
+ throw r_Error(COMPRESSIONFAILED);
+ }
+
+ NCScbmGetViewFileInfo(pNCSFileView, &pNCSFileInfo);
+ x_size = pNCSFileInfo->nSizeX;
+ y_size = pNCSFileInfo->nSizeY;
+ nBands = pNCSFileInfo->nBands;
+ RMDBGMIDDLE(5, RMDebug::module_conversion, "r_Conv_ECW", "image : " << x_size << " x " << y_size << ", " << nBands << " bands");
+
+ /* Have to set up the band list. Compatible with ER Mapper's method.*/
+ /* In this example we always request all bands.*/
+ UINT32* band_list = new UINT32[nBands];
+ for( band = 0; band < nBands; band++ )
+ band_list[band] = band;
+ size_t typeLength = nBands;
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ case ctype_char:
+ case ctype_uint8:
+ if (nBands != 1)
+ {
+ RMInit::logOut << "r_Conv_ECW conversion of base types bot supported" << std::endl;
+ throw r_Error(COMPRESSIONFAILED);
+ }
+ break;
+ case ctype_rgb:
+ if (nBands != 3)
+ {
+ RMInit::logOut << "r_Conv_ECW conversion of base types bot supported" << std::endl;
+ throw r_Error(COMPRESSIONFAILED);
+ }
+ break;
+ default:
+ RMInit::logOut << "r_Conv_ECW there is a really bad error in your compiler" << std::endl;
+ throw r_Error(10000);
+ break;
+ }
+ start_x = 0;
+ start_y = 0;
+ end_x = x_size - 1;
+ end_y = y_size - 1;
+ number_x = x_size;
+ number_y = y_size;
+
+ windowx = number_x;
+ windowy = number_y;
+
+ r_Minterval imageDomain(2);
+ imageDomain << r_Sinterval((r_Range)0, (r_Range)number_x - 1);
+ imageDomain << r_Sinterval((r_Range)0, (r_Range)number_y - 1);
+ RMDBGMIDDLE(5, RMDebug::module_conversion, "r_Conv_ECW", "image domain " << imageDomain << ", type length " << typeLength << " bands");
+ char* image = (char*)mystore.storage_alloc(number_x * number_y * typeLength);
+ //char* image = new char[number_x * number_y * typeLength];
+ memset(image, 0, number_x * number_y * typeLength);
+ r_Minterval maxDom(2);
+ maxDom << r_Sinterval((r_Range)0, (r_Range)1000 - 1);
+ maxDom << r_Sinterval((r_Range)0, (r_Range)1000 - 1);
+ r_MiterArea dom_iter(&maxDom, &imageDomain);
+ r_Minterval iterArea(2);
+ while (!dom_iter.isDone())
+ {
+ iterArea = dom_iter.nextArea();
+ start_x = iterArea[0].low();
+ start_y = iterArea[1].low();
+ end_x = iterArea[0].high();
+ end_y = iterArea[1].high();
+ number_x = iterArea[0].get_extent();
+ number_y = iterArea[1].get_extent();
+ RMDBGMIDDLE(5, RMDebug::module_conversion, "r_Conv_ECW", "current " << start_x << ":" << end_x << "," << start_y << ":" << end_y << " window " << number_x << " x " << number_y);
+ eError = NCScbmSetFileView(pNCSFileView, nBands, band_list, start_x, start_y, end_x, end_y, number_x, number_y);
+ if( eError != NCS_SUCCESS)
+ {
+ RMInit::logOut << "Error while setting file view to " << nBands << " bands, [" << start_x << ":" << end_x << "," << start_y << ":" << end_y << "], window size " << number_x << " x " << number_y << " pixel" << std::endl;
+ RMInit::logOut << "Error = " << NCSGetErrorText(eError) << std::endl;
+ NCScbmCloseFileViewEx(pNCSFileView, TRUE);
+ delete [] band_list;
+ mystore.storage_free(image);
+ throw r_Error(COMPRESSIONFAILED);
+ }
+
+ p_output_buffer = new UINT8[number_x * nBands];
+ p_p_output_line = new UINT8*[nBands];
+
+ for(band = 0; band < nBands; band++ )
+ p_p_output_line[band] = p_output_buffer + (band * number_x);
+
+ /*
+ ** Read each line of the compressed file
+ */
+ for( UINT32 line = 0; line < number_y; line++ )
+ {
+ NCSEcwReadStatus eReadStatus = NCScbmReadViewLineBIL( pNCSFileView, p_p_output_line);
+ if (eReadStatus != NCSECW_READ_OK)
+ {
+ RMInit::logOut << "Read line error at line " << line << std::endl;
+ RMInit::logOut << "Status code " << eReadStatus << std::endl;
+ NCScbmCloseFileViewEx(pNCSFileView, TRUE);
+ delete [] band_list;
+ delete [] p_p_output_line;
+ delete [] p_output_buffer;
+ mystore.storage_free(image);
+ throw r_Error(COMPRESSIONFAILED);
+ }
+ for (int b = 0; b < nBands; b++)
+ {
+ for (int l = 0; l < number_x; l++)
+ {
+ image[(l + iterArea[0].low()) * windowy * typeLength + (line + iterArea[1].low()) * typeLength + b] = p_p_output_line[b][l];
+ }
+ }
+ }
+ delete [] p_p_output_line;
+ delete [] p_output_buffer;
+ RMDBGMIDDLE(5, RMDebug::module_conversion, "r_Conv_ECW", "read done");
+ }
+ NCScbmCloseFileViewEx(pNCSFileView, TRUE);
+ delete [] band_list;
+ desc.dest = (char*)image;
+ desc.destInterv = imageDomain;
+ desc.destType = get_external_type(desc.baseType);
+ return desc;
+#else
+ RMDBGENTER(5, RMDebug::module_conversion, "r_Conv_ECW", "convertFrom(" << options << ") NOT COMPILED");
+ RMInit::logOut << "r_Conv_ECW::convertFrom(" << options << ") ecw support not compiled in" << std::endl;
+ throw r_Error(COMPRESSIONFAILED);
+#endif
+ }
+
+r_convDesc&
+r_Conv_ECW::convertTo(const char* options) throw (r_Error)
+ {
+ RMInit::logOut << "r_Conv_ECW::convertTo(" << options << ") compression not supported" << std::endl;
+ throw r_Error(COMPRESSIONFAILED);
+ }
+
+const char*
+r_Conv_ECW::get_name() const
+ {
+ return get_name_from_data_format(r_ECW);
+ }
+
+r_Data_Format
+r_Conv_ECW::get_data_format() const
+ {
+ return r_ECW;
+ }
+
+r_Convertor*
+r_Conv_ECW::clone() const
+ {
+ return new r_Conv_ECW(desc.src, desc.srcInterv, desc.srcType);
+ }
+
diff --git a/conversion/ecw.hh b/conversion/ecw.hh
new file mode 100644
index 0000000..d418809
--- /dev/null
+++ b/conversion/ecw.hh
@@ -0,0 +1,78 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: ecw.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_ECW
+ *
+ * COMMENTS:
+ * Provides interface to convert data from ECW to r_Array
+ *
+*/
+
+#ifndef _R_CONV_ECW_HH_
+#define _R_CONV_ECW_HH_
+#include "conversion/convertor.hh"
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ ECW convertor class.
+
+ Supported parameters are
+
+ \begin{tabular}{lcl}
+ {\tt windowx} && uint && maximum number of colums to convert in one ecw call, default 1000\\
+ {\tt windowy} && uint && maximum number of lines to convert in one ecw call, default 1000\\
+ \end{tabular}
+*/
+
+
+class r_Conv_ECW : public r_Convertor
+ {
+ public:
+ r_Conv_ECW(const char* source, const r_Minterval& lengthordomain, const r_Type* tp) throw(r_Error);
+
+ r_Conv_ECW(const char* source, const r_Minterval& lengthordomain, int tp) throw(r_Error);
+
+ r_convDesc& convertFrom(const char* options = NULL) throw (r_Error);
+
+ r_convDesc& convertTo(const char* options = NULL) throw (r_Error);
+
+ const char* get_name() const;
+
+ r_Data_Format get_data_format() const;
+
+ r_Convertor* clone() const;
+
+
+ private:
+ void initECW();
+
+ };
+
+#endif
+
+
diff --git a/conversion/ecwmemfs.cc b/conversion/ecwmemfs.cc
new file mode 100644
index 0000000..07357d6
--- /dev/null
+++ b/conversion/ecwmemfs.cc
@@ -0,0 +1,157 @@
+/*
+* 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>.
+*/
+
+#include "ecwmemfs.hh"
+#include <fstream>
+#include <algorithm>
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+
+const char*
+MemoryFileSystem::memorySrc = NULL;
+
+r_Bytes
+MemoryFileSystem::memorySrcLength = 0;
+
+const char*
+MemoryFileSystem::memorySrcName = "memory.src";
+
+MemoryFileSystem::MemoryFileSystem()
+ : current(NULL),
+ source(NULL),
+ length(0),
+ closed(false),
+ owner(true)
+ {
+ RMDBGONCE(5, RMDebug::module_conversion, "MemoryFileSystem", "MemoryFileSystem()");
+ }
+
+MemoryFileSystem::m_Error
+MemoryFileSystem::open(const char* memorySource, r_Bytes mSize)
+ {
+ RMDBGONCE(5, RMDebug::module_conversion, "MemoryFileSystem", "open(source, " << mSize << ")");
+ owner = false;
+ length = mSize;
+ source = (char*)memorySource;
+ current = source;
+ return No_Error;
+ }
+
+MemoryFileSystem::m_Error
+MemoryFileSystem::open(const char* fileName)
+ {
+ owner = true;
+ RMDBGENTER(5, RMDebug::module_conversion, "MemoryFileSystem", "open(" << fileName << ")");
+ if (fileName == memorySrcName)
+ {
+ MemoryFileSystem::m_Error err = open(memorySrc, memorySrcLength);
+ RMDBGEXIT(5, RMDebug::module_conversion, "MemoryFileSystem", "open(" << fileName << ") " << err);
+ return err;
+ }
+ else {
+ std::ifstream f;
+ f.open(fileName);
+ if (!f.is_open())
+ {
+ RMInit::logOut << "MemoryFileSystem::open(" << fileName << ") could not open file" << std::endl;
+ RMDBGEXIT(5, RMDebug::module_conversion, "MemoryFileSystem", "open(" << fileName << ") " << Error);
+ return Error;
+ }
+ f.seekg(0, std::ios::end);
+ std::ios::pos_type end = f.tellg();
+ RMDBGMIDDLE(5, RMDebug::module_conversion, "MemoryFileSystem", "size " << end);
+ length = end;
+ source = new char[end];
+ current = source;
+ memset(source, 0, end);
+ f.seekg(0, std::ios::beg);
+ f.read(source, end);
+ f.close();
+ RMDBGEXIT(5, RMDebug::module_conversion, "MemoryFileSystem", "open(" << fileName << ") " << No_Error);
+ return No_Error;
+ }
+ }
+
+MemoryFileSystem::m_Error
+MemoryFileSystem::close()
+ {
+ RMDBGENTER(5, RMDebug::module_conversion, "MemoryFileSystem", "close()");
+ if (!closed)
+ {
+ if (owner)
+ {
+ delete [] source;
+ }
+ source = NULL;
+ current = NULL;
+ length = 0;
+ RMDBGEXIT(5, RMDebug::module_conversion, "MemoryFileSystem", "close() " << No_Error);
+ return No_Error;
+ }
+ else {
+ RMDBGEXIT(5, RMDebug::module_conversion, "MemoryFileSystem", "close() " << Error);
+ return Error;
+ }
+ }
+
+MemoryFileSystem::~MemoryFileSystem()
+ {
+ RMDBGONCE(5, RMDebug::module_conversion, "MemoryFileSystem", "~MemoryFileSystem()");
+ close();
+ }
+
+MemoryFileSystem::m_Error
+MemoryFileSystem::read(void* buffer, r_Bytes bSize)
+ {
+ RMDBGENTER(5, RMDebug::module_conversion, "MemoryFileSystem", "read(buffer, " << bSize << ")");
+ bSize = std::min(bSize, length - (current - source));
+ RMDBGMIDDLE(5, RMDebug::module_conversion, "MemoryFileSystem", "reading " << bSize);
+ memcpy(buffer, current, bSize);
+ current += bSize;
+ RMDBGEXIT(5, RMDebug::module_conversion, "MemoryFileSystem", "read(buffer, " << bSize << ") " << No_Error);
+ return No_Error;
+ }
+
+unsigned long long
+MemoryFileSystem::tell()
+ {
+ RMDBGONCE(5, RMDebug::module_conversion, "MemoryFileSystem", "tell() " << (current - source));
+ return current - source;
+ }
+
+MemoryFileSystem::m_Error
+MemoryFileSystem::seek(unsigned long long offset)
+ {
+ RMDBGENTER(5, RMDebug::module_conversion, "MemoryFileSystem", "seek(" << offset << ")");
+ if (offset > length)
+ {
+ RMDBGEXIT(5, RMDebug::module_conversion, "MemoryFileSystem", "seek(" << offset << ") (length " << length << ") " << Error);
+ return Error;
+ }
+ else {
+ current = offset + source;
+ RMDBGEXIT(5, RMDebug::module_conversion, "MemoryFileSystem", "seek(" << offset << ") " << No_Error);
+ return No_Error;
+ }
+ }
+
diff --git a/conversion/ecwmemfs.hh b/conversion/ecwmemfs.hh
new file mode 100644
index 0000000..f61ed10
--- /dev/null
+++ b/conversion/ecwmemfs.hh
@@ -0,0 +1,84 @@
+/*
+* 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>.
+*/
+
+#ifndef _ECWMEMFS_HH_
+#define _ECWMEMFS_HH_
+
+#include "raslib/mddtypes.hh"
+
+class MemoryFileSystem
+ {
+ public:
+ enum m_Error
+ {
+ No_Error = 0,
+ Error = 1
+ };
+
+ MemoryFileSystem();
+
+ ///open file an read into memory - completely
+ m_Error open(const char* fileName);
+
+ ///use this memory chunk with mSize bytes length
+ m_Error open(const char* memorySource, r_Bytes mSize);
+
+ ///close and deinitialise (delete only my own data)
+ m_Error close();
+
+ ///call close
+ ~MemoryFileSystem();
+
+ ///read bSize bytes into buffer, only if bSize bytes are available
+ m_Error read(void* buffer, r_Bytes bSize);
+
+ ///get current position
+ unsigned long long tell();
+
+ ///go to offset bytes from begining of memory
+ m_Error seek(unsigned long long offset);
+
+ ///if you use open(const* char) and the pointer is memorySrcName then no file will be read but this pointer
+ static const char* memorySrc;
+
+ ///file names which point to this will not read from file system but from memorySrc
+ static const char* memorySrcName;
+
+ ///the length of the memorySrc chunk must be specified in memoryLength
+ static r_Bytes memorySrcLength;
+
+ private:
+
+ ///my memory block
+ char* source;
+ ///my current position
+ char* current;
+ ///am i closed
+ bool closed;
+ ///do i own my memory data
+ bool owner;
+ ///how long is my memory data
+ r_Bytes length;
+ };
+
+#endif
diff --git a/conversion/graphic.cc b/conversion/graphic.cc
new file mode 100644
index 0000000..1ba5bda
--- /dev/null
+++ b/conversion/graphic.cc
@@ -0,0 +1,148 @@
+/*
+* 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>.
+*/
+
+#include <iostream>
+#include <fstream>
+#include <cstring>
+
+#include "graphic.h"
+#include "nitf.h"
+#include "utilities.h"
+
+using namespace std;
+using namespace RasNITF;
+
+graphic::graphic()
+{
+ m_graphic_data = NULL;
+ m_sxshd = NULL;
+}
+
+graphic::~graphic()
+{
+ if(m_graphic_data != NULL)
+ delete m_graphic_data;
+ m_graphic_data = NULL;
+
+ if(m_sxshd != NULL)
+ delete m_sxshd;
+ m_sxshd = NULL;
+
+}
+
+int graphic::read_file(istream &hNITF, long gh_length, long graph_length)
+{
+ int charsread = 0;
+ long start_position = 0;
+
+ header_length = gh_length;
+
+ // here find where are we relative to the begining
+ start_position = hNITF.tellg();
+
+ // here read the header data
+ charsread += read_verify2(hNITF,m_sy, 2+10+20+1+2+11+2+20+2+8+4+1+8+43+1+40+1+8+15+1+1+13+3+3+10+10+1+10+2);
+
+ charsread += read_verify2(hNITF, m_sxshdl, 5);
+
+ n_sxshdl = charptrtolong(m_sxshdl, 5);
+
+ if (n_sxshdl > 0) {
+ n_sxshdl -= 3;
+ read_verify2(hNITF, m_sxsofl, 3);
+ m_sxshd = new char[n_sxshdl - 3];
+ if(m_sxshd == NULL) cerr<<"ERROR: could not allocate memory";
+ read_verify2(hNITF, m_sxshd, n_sxshdl);
+ n_sxshdl += 3;
+
+ }
+
+ // check if we are where we should be
+
+ if( ((long)hNITF.tellg()) != (start_position + gh_length)) {
+ cerr << "Error in graph.cpp";
+ exit(2);
+ }
+
+ // store the text data
+
+ m_graphic_data = new char[graph_length];
+ if(m_graphic_data == NULL) cerr<<"ERROR: could not allocate memory";
+ data_length = read_verify2(hNITF, m_graphic_data, graph_length);
+ return charsread;
+}
+
+int graphic::write_file(ofstream &fNITF){
+
+ fNITF.write( m_sy, 2);
+ fNITF.write( m_sid, 10);
+ fNITF.write( m_sname, 20);
+ fNITF.write( m_ssclas, 1);
+ fNITF.write( m_ssclsy, 2);
+ fNITF.write( m_sscode, 11);
+ fNITF.write( m_ssctlh, 2);
+ fNITF.write( m_ssrel, 20);
+ fNITF.write( m_ssdctp, 2);
+ fNITF.write( m_ssdcdt, 8);
+ fNITF.write( m_ssdcxm, 4);
+ fNITF.write( m_ssdg, 1);
+ fNITF.write( m_ssdgdt, 8);
+ fNITF.write( m_sscltx, 43);
+ fNITF.write( m_sscatp, 1);
+ fNITF.write( m_sscaut, 40);
+ fNITF.write( m_sscrsn, 1);
+ fNITF.write( m_sssrdt, 8);
+ fNITF.write( m_ssctln, 15);
+ fNITF.write( m_encryp, 1);
+ fNITF.write( m_stype, 1);
+ fNITF.write( m_sres1, 13);
+ fNITF.write( m_sdlvl, 3);
+ fNITF.write( m_salvl, 3);
+ fNITF.write( m_sloc, 10);
+ fNITF.write( m_sbnd1, 10);
+ fNITF.write( m_scolor, 1);
+ fNITF.write( m_sbnd2, 10);
+ fNITF.write( m_sres2, 2);
+ fNITF.write(m_sxshdl, 5);
+
+ if (n_sxshdl > 0) {
+ fNITF.write(m_sxsofl, 3);
+ fNITF.write(m_sxshd, n_sxshdl - 3);
+ }
+
+ if( m_graphic_data != NULL) {
+ fNITF.write( m_graphic_data, data_length);
+ }
+
+ //TODO change to charswritten
+ return 0;
+
+}
+
+string graphic::get_ls() {
+ return graphic_dl;
+}
+
+string graphic::get_lssh() {
+ return graphic_hl;
+}
diff --git a/conversion/graphic.h b/conversion/graphic.h
new file mode 100644
index 0000000..e1662e2
--- /dev/null
+++ b/conversion/graphic.h
@@ -0,0 +1,90 @@
+/*
+* 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>.
+*/
+
+
+#ifndef __GRAPHIC_H_INCLUDED
+#define __GRAPHIC_H_INCLUDED
+
+#include<vector>
+#include<iostream>
+#include<fstream>
+
+namespace RasNITF
+{
+
+class graphic{
+ private:
+ char m_sy[2];
+ char m_sid[10];
+ char m_sname[20];
+ char m_ssclas[1];
+ char m_ssclsy[2];
+ char m_sscode[11];
+ char m_ssctlh[2];
+ char m_ssrel[20];
+ char m_ssdctp[2];
+ char m_ssdcdt[8];
+ char m_ssdcxm[4];
+ char m_ssdg[1];
+ char m_ssdgdt[8];
+ char m_sscltx[43];
+ char m_sscatp[1];
+ char m_sscaut[40];
+ char m_sscrsn[1];
+ char m_sssrdt[8];
+ char m_ssctln[15];
+ char m_encryp[1];
+ char m_stype[1];
+ char m_sres1[13];
+ char m_sdlvl[3];
+ char m_salvl[3];
+ char m_sloc[10];
+ char m_sbnd1[10];
+ char m_scolor[1];
+ char m_sbnd2[10];
+ char m_sres2[2];
+ char m_sxshdl[5];
+ char m_sxsofl[3];
+ char* m_sxshd;
+ char *m_graphic_data;
+
+ int header_length;
+ int data_length;
+ int n_sxshdl;
+ int n_sxsofl;
+
+ std::string graphic_hl ;
+ std::string graphic_dl ;
+
+ public:
+ graphic();
+ ~graphic();
+ int read_file(std::istream&, long, long);
+ int write_file(std::ofstream &);
+ std::string get_ls();
+ std::string get_lssh();
+};
+
+}
+
+#endif
diff --git a/conversion/hdf.cc b/conversion/hdf.cc
new file mode 100644
index 0000000..5effb10
--- /dev/null
+++ b/conversion/hdf.cc
@@ -0,0 +1,386 @@
+/*
+* 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: hdf.cc
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_HDF
+ *
+ * COMMENTS:
+ *
+ * Provides functions to convert data to HDF SD and back.
+ *
+*/
+
+/* Added by Sorin Stancu-Mara. Definition clashed for type int8, define in both
+* /usr/include/hdf.h and in /usr/include/tiff.h
+* This will supress the tiff.h definition.
+* Both definitions are similar
+*/
+#define HAVE_INT8
+
+#include "conversion/hdf.hh"
+#include "raslib/error.hh"
+#include "raslib/rminit.hh"
+#include "raslib/parseparams.hh"
+#include "raslib/primitivetype.hh"
+
+
+#ifdef HAVE_HDF_H
+ #include "hdf.h"
+#elif HAVE_HDF_HDF_H
+ #include "hdf/hdf.h"
+#else
+ #error "No hdf.h header available."
+#endif
+
+#ifdef HAVE_MFHDF_H
+ #include "mfhdf.h"
+#elif HAVE_HDF_MFHDF_H
+ #include "hdf/mfhdf.h"
+#else
+ #error "No mfhdf.h header available."
+#endif
+
+#include <stdio.h>
+#include <iostream>
+
+
+
+const r_Convertor::convert_string_t r_Conv_HDF::compNames[] = {
+ {"none", COMP_CODE_NONE},
+ {"rle", COMP_CODE_RLE},
+ {"huffman", COMP_CODE_SKPHUFF},
+ {"deflate", COMP_CODE_DEFLATE},
+ {NULL, COMP_CODE_NONE}
+};
+
+// Buffer used for switching the majorness (column <--> row) of the array data
+const int r_Conv_HDF::MaxSwapBufferSize = 0x10000;
+
+
+
+
+void r_Conv_HDF::initHDF( void )
+{
+ compType = NULL;
+ quality = 80;
+ skiphuff = 0;
+
+ if (params == NULL)
+ params = new r_Parse_Params;
+
+ params->add("comptype", &compType, r_Parse_Params::param_type_string);
+ params->add("quality", &quality, r_Parse_Params::param_type_int);
+ params->add("skiphuff", &skiphuff, r_Parse_Params::param_type_int);
+}
+
+
+int r_Conv_HDF::getHDFtype(int intType, int &size)
+{
+ int result=0;
+
+ switch (intType)
+ {
+ case ctype_int8: result = DFNT_CHAR8; size = 1; break;
+ case ctype_uint8:
+ case ctype_char:
+ case ctype_bool: result = DFNT_UCHAR8; size = 1; break;
+ case ctype_int16: result = DFNT_INT16; size = 2; break;
+ case ctype_uint16: result = DFNT_UINT16; size = 2; break;
+ case ctype_int32: result = DFNT_INT32; size = 4; break;
+ case ctype_uint32: result = DFNT_UINT32; size = 4; break;
+ case ctype_int64: result = DFNT_INT64; size = 8; break;
+ case ctype_uint64: result = DFNT_UINT64; size = 8; break;
+ case ctype_float32: result = DFNT_FLOAT32; size = 4; break;
+ case ctype_float64: result = DFNT_FLOAT64; size = 8; break;
+ default: result = 0; size = 1; break;
+ }
+ return result;
+}
+
+
+int r_Conv_HDF::getIntType( int hdfType, int &size )
+{
+ int result=0;
+
+ switch (hdfType)
+ {
+ case DFNT_CHAR8: result = ctype_int8; size = 1; break;
+ case DFNT_UCHAR8: result = ctype_uint8; size = 1; break;
+ case DFNT_INT16: result = ctype_int16; size = 2; break;
+ case DFNT_UINT16: result = ctype_uint16; size = 2; break;
+ case DFNT_INT32: result = ctype_int32; size = 4; break;
+ case DFNT_UINT32: result = ctype_uint32; size = 4; break;
+ case DFNT_INT64: result = ctype_int64; size = 8; break;
+ case DFNT_UINT64: result = ctype_uint64; size = 8; break;
+ case DFNT_FLOAT32: result = ctype_float32; size = 4; break;
+ case DFNT_FLOAT64: result = ctype_float64; size = 8; break;
+ default: result = ctype_void; size = 1; break;
+ }
+ return result;
+}
+
+
+
+r_Conv_HDF::r_Conv_HDF(const char *src, const r_Minterval &interv, const r_Type *tp) throw(r_Error)
+: r_Convertor(src, interv, tp, true)
+{
+ initHDF();
+
+ if (tp->isStructType())
+ {
+ RMInit::logOut << "r_Conv_HDF::r_Conv_HDF(): structured types not supported." << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+}
+
+
+
+r_Conv_HDF::r_Conv_HDF(const char *src, const r_Minterval &interv, int tp) throw(r_Error)
+: r_Convertor(src, interv, tp)
+{
+ initHDF();
+}
+
+
+
+r_Conv_HDF::~r_Conv_HDF(void)
+{
+ if (compType != NULL)
+ {
+ delete [] compType;
+ compType = NULL;
+ }
+}
+
+
+
+r_convDesc &r_Conv_HDF::convertTo( const char *options ) throw(r_Error)
+{
+ char name[256];
+ int32 handle=0, sds_id=0, rank=0;
+ comp_coder_t comp_type=COMP_CODE_NONE;
+ int32 *dimsizes=NULL, *start=NULL;
+ size_t filesize=0;
+ int i=0, j=0;
+ FILE *fp=NULL;
+ comp_info c_info;
+
+ strncpy(name, tmpnam(NULL), 256);
+ //name = "testfile.hdf";
+
+ if ((handle = SDstart(name, DFACC_CREATE)) == FAIL)
+ {
+ RMInit::logOut << "r_Conv_HDF::convertTo(): unable to open output file." << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ rank = desc.srcInterv.dimension();
+
+ dimsizes = new int32[rank]; start = new int32[rank];
+ datatype = getHDFtype(desc.baseType, datasize);
+
+ for (i=0; i<rank; i++)
+ {
+ dimsizes[i] = desc.srcInterv[i].high() - desc.srcInterv[i].low() + 1;
+ start[i] = 0;
+ }
+
+ if ((sds_id = SDcreate(handle, "RasDaMan object", datatype, rank, dimsizes)) == FAIL)
+ {
+ RMInit::logOut << "r_Conv_HDF::convertTo(): unable to create object." << endl;
+ SDend(handle); remove(name);
+ throw r_Error(r_Error::r_Error_General);
+ }
+ SDsetfillmode(sds_id, SD_NOFILL);
+
+ params->process(options);
+
+ comp_type = COMP_CODE_DEFLATE;
+ if (compType != NULL)
+ {
+ for (i=0; compNames[i].key != NULL; i++)
+ {
+ if (strcasecmp(compNames[i].key, compType) == 0)
+ {
+ comp_type = (comp_coder_t)compNames[i].id;
+ break;
+ }
+ }
+ if (compNames[i].key == NULL)
+ {
+ RMInit::logOut << "r_Conv_HDF::convertTo(): unsupported compression type " << compType << endl;
+ }
+ }
+ c_info.skphuff.skp_size = skiphuff;
+ c_info.deflate.level = quality;
+
+ SDsetcompress(sds_id, comp_type, &c_info);
+
+ SDwritedata(sds_id, start, NULL, dimsizes, (VOIDP)(desc.src));
+
+ delete [] dimsizes; dimsizes=NULL;
+ delete [] start; start=NULL;
+
+ SDendaccess(sds_id);
+
+ SDend(handle);
+
+ if ((fp = fopen(name, "rb")) == NULL)
+ {
+ RMInit::logOut << "r_Conv_HDF::convertTo(): unable to read back file." << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ fseek(fp, 0, SEEK_END);
+ filesize = ftell(fp);
+
+ desc.destInterv = r_Minterval(1);
+ desc.destInterv << r_Sinterval((r_Range)0, (r_Range)filesize - 1);
+
+ if ((desc.dest = (char*)mystore.storage_alloc(filesize)) == NULL)
+ {
+ RMInit::logOut << "r_Conv_HDF::convertTo(): out of memory error" << endl;
+ fclose(fp);
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+ fseek(fp, 0, SEEK_SET);
+ fread(desc.dest, 1, filesize, fp);
+
+ fclose(fp);
+
+ remove(name);
+
+ // Result is just a bytestream
+ desc.destType = r_Type::get_any_type("char");
+
+ return desc;
+}
+
+
+
+r_convDesc &r_Conv_HDF::convertFrom(const char *options) throw(r_Error)
+{
+ char name[256];
+ int32 handle=0, sds_id=0, rank=0, dtype=0, numattr=0, array_size=0;
+ int32 dimsizes[MAX_VAR_DIMS];
+ int32 *start=NULL;
+ int dsize=0;
+ size_t filesize=0;
+ FILE *fp=NULL;
+ int i=0;
+
+ if (desc.srcInterv.dimension() != 1)
+ {
+ RMInit::logOut << "r_Conv_HDF::convertFrom(): source data must be a bytestream!" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ strncpy(name, tmpnam(NULL), 256);
+ if ((fp = fopen(name, "wb")) == NULL)
+ {
+ RMInit::logOut << "r_Conv_HDF::convertFrom(): unable to write temporary file!" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ filesize = desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1;
+ if ((i = fwrite(desc.src, 1, filesize, fp)) != filesize)
+ {
+ RMInit::logOut << "r_Conv_HDF::convertFrom(): error writing to temporary file ("
+ << i << " / " << filesize << ')' << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ fclose(fp);
+
+ if ((handle = SDstart(name, DFACC_READ)) == FAIL)
+ {
+ RMInit::logOut << "r_Conv_HDF::convertFrom(): can't read temporary file!" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ // Only read the first object in the file
+ if ((sds_id = SDselect(handle, 0)) == FAIL)
+ {
+ RMInit::logOut << "r_Conv_HDF::convertFrom(): unable to open first object" << endl;
+ SDend(handle); remove(name);
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ SDgetinfo(sds_id, NULL, &rank, dimsizes, &dtype, &numattr);
+
+ // Ignore native datatype flag
+ dtype &= ~DFNT_NATIVE;
+
+ desc.destType = get_external_type(getIntType(dtype, dsize));
+
+ start = new int32[rank];
+ desc.destInterv = r_Minterval(rank);
+ array_size = (int32)dsize;
+ for (i=0; i<rank; i++)
+ {
+ desc.destInterv << r_Sinterval(r_Range(0), r_Range(dimsizes[i]-1));
+ array_size *= dimsizes[i];
+ start[i] = 0;
+ }
+
+ if ((desc.dest = (char*)mystore.storage_alloc(array_size)) == NULL)
+ {
+ RMInit::logOut << "r_Conv_HDF::convertFrom(): out of memory error!" << endl;
+ SDend(handle); remove(name);
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+
+ if (SDreaddata(sds_id, start, NULL, dimsizes, (VOIDP)desc.dest) == FAIL)
+ {
+ RMInit::logOut << "r_Conv_HDF::convertFrom(): error reading data" << endl;
+ SDend(handle); remove(name);
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ delete [] start; start=NULL;
+
+ SDendaccess(sds_id);
+
+ SDend(handle);
+
+ remove(name);
+
+ return desc;
+}
+
+
+
+const char *r_Conv_HDF::get_name( void ) const
+{
+ return format_name_hdf;
+}
+
+
+r_Data_Format r_Conv_HDF::get_data_format( void ) const
+{
+ return r_HDF;
+}
+
+
+r_Convertor *r_Conv_HDF::clone( void ) const
+{
+ return new r_Conv_HDF(desc.src, desc.srcInterv, desc.baseType);
+}
diff --git a/conversion/hdf.hh b/conversion/hdf.hh
new file mode 100644
index 0000000..0546811
--- /dev/null
+++ b/conversion/hdf.hh
@@ -0,0 +1,104 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: hdf.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_HDF
+ *
+ * COMMENTS:
+ *
+ * Provides interface to convert data to other formats.
+ *
+*/
+
+#ifndef _R_CONV_HDF_HH_
+#define _R_CONV_HDF_HH_
+
+#include "conversion/convertor.hh"
+
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ HDF convertor class.
+
+ Supported parameters are
+
+ \begin{tabular}{lcl}
+ comptype && string && the compression type to use (see below)\\
+ quality && int && quality parameter for JPEG compression\\
+ skiphuff && int && skipping parameter for Huffman coding\\
+ \end{tabular}
+
+ The compression type defaults to deflate but may be one of the
+ following
+
+ \begin{tabular}{ll}
+ none && no compression\\
+ rle && Run Length Coding\\
+ huffman && Huffman coding\\
+ deflate && ZIP deflate\\
+ \end{tabular}
+
+*/
+class r_Conv_HDF : public r_Convertor
+{
+ public:
+ /// constructor using an r_Type object. Exception if the type isn't atomic.
+ r_Conv_HDF( const char *src, const r_Minterval &interv, const r_Type *tp) throw(r_Error);
+ /// constructor using convert_type_e shortcut
+ r_Conv_HDF( const char *src, const r_Minterval &interv, int tp ) throw(r_Error);
+ /// destructor
+ ~r_Conv_HDF( void );
+
+ /// convert to HDF
+ virtual r_convDesc &convertTo( const char *options=NULL ) throw(r_Error);
+ /// convert from HDF
+ virtual r_convDesc &convertFrom( const char *options=NULL ) throw(r_Error);
+ /// cloning
+ virtual r_Convertor *clone( void ) const;
+ /// identification
+ virtual const char *get_name( void ) const;
+ virtual r_Data_Format get_data_format( void ) const;
+
+
+ private:
+ /// init HDF module
+ void initHDF( void );
+ /// translate an internal type into an HDF type and return the size.
+ static int getHDFtype(int intType, int &size);
+ /// translate an HDF type into an internal type and return the size
+ static int getIntType(int hdfType, int &size);
+ /// variables
+ int datatype, datasize;
+ /// parameters
+ int skiphuff;
+ int quality;
+ char *compType;
+ static const convert_string_t compNames[];
+ static const int MaxSwapBufferSize;
+};
+
+#endif
diff --git a/conversion/image.cc b/conversion/image.cc
new file mode 100644
index 0000000..95018d6
--- /dev/null
+++ b/conversion/image.cc
@@ -0,0 +1,1040 @@
+/*
+* 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>.
+*/
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#ifdef __GNUG__
+#include "raslib/template_inst.hh"
+#endif
+#endif
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+/*
+#include <strstream>
+
+#include "raslib/rminit.hh"
+#include "rasodmg/marray.hh"
+#include "rasodmg/ref.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/partinsert.hh"
+#include "raslib/type.hh"
+#include "raslib/odmgtypes.hh"
+*/
+#include <cstring>
+#include <cstdlib>
+#include <sys/types.h>
+#include <unistd.h>
+#include <cstdio>
+#include <iostream>
+#include <fstream>
+
+#include "image.h"
+#include "utilities.h"
+
+using namespace std;
+using namespace RasNITF;
+
+
+typedef struct {
+ unsigned char red, green, blue;
+} RGBPixel;
+
+image_band::image_band(){
+ lutdnnm = NULL;
+}
+
+image_band::~image_band(){
+
+ if (lutdnnm != NULL){
+ delete lutdnnm;
+ lutdnnm = NULL;
+ }
+}
+
+image::image(){
+
+ m_icom = NULL;
+ m_bands = NULL;
+ m_udid = NULL;
+ m_ixshd = NULL;
+ m_data = NULL;
+
+}
+
+image::~image(){
+
+ if (m_icom != NULL) {
+ delete m_icom;
+ m_icom = NULL;
+ }
+
+ if (m_bands != NULL){
+ delete[] m_bands;
+ m_bands = NULL;
+ }
+
+ if (m_udid != NULL) {
+ delete m_udid;
+ m_udid = NULL;
+ }
+
+ if (m_ixshd != NULL) {
+ delete m_ixshd;
+ m_ixshd = NULL;
+ }
+
+ if (m_data != NULL) {
+ delete m_data;
+ m_data = NULL;
+ }
+}
+
+
+/**********************************************************************
+ * NAME: image::read_file
+ * PURPOSE: read an image from an ntf file into an image object
+ *********************************************************************/
+
+int image::read_file(istream &hNITF, long lish, long li, bool read_image_data){
+
+ int charsread=0;
+
+ // read IM through ICORDS
+
+ charsread += read_verify2(hNITF, m_im, (2+10+14+17+80+1+2+11+2+20+2+8+4+1+8+43+1+40+1+8+15+1+42+8+8+3+8+8+2+1+1));
+
+ // read IGEOLO field if used
+
+ if (m_icords[0] != ' ') {
+ charsread += read_verify2(hNITF, m_igeolo, 60);
+ } else {
+ memset(m_igeolo, ' ', 60);
+ charsread += 60;
+ }
+
+ // read NICOM and ICOM
+
+ charsread += read_verify2(hNITF, m_nicom, 1);
+ n_nicom = charptrtoint(m_nicom, 1);
+
+ if (n_nicom > 0) {
+ m_icom = new char[n_nicom * 80];
+ charsread += read_verify2(hNITF, m_icom, n_nicom * 80);
+ } else {
+ m_icom = NULL;
+ }
+
+ // read IC
+
+ charsread += read_verify2(hNITF, m_ic, 2);
+
+ // read COMRAT if necessary
+
+ if ((strncmp(m_ic, "NC", 2) != 0) && (strncmp(m_ic, "NM", 2) != 0)) {
+ charsread += read_verify2(hNITF, m_comrat, 4);
+ }
+
+ charsread += read_verify2(hNITF, m_nbands, 1);
+ n_nbands = charptrtoint(m_nbands, 1);
+
+ if (n_nbands == 0) {
+ charsread += read_verify2(hNITF, m_xbands, 5);
+ n_xbands = charptrtoint(m_xbands, 5);
+ numbands = n_xbands;
+ } else {
+ n_xbands = 0;
+ numbands = n_nbands;
+ }
+
+ if (numbands > 0){
+
+ m_bands = new image_band[numbands];
+
+ for (int i = 0; i < numbands; i++) {
+
+ // read IREPBANDnn..NLUTSnn
+ charsread += read_verify2(hNITF, m_bands[i].irepbandnn, (2+6+1+3+1));
+
+ // get # of LUTS for this band
+ m_bands[i].numluts = charptrtoint( m_bands[i].nlutsnn, 1);
+
+ // read LUTs entries per LUT
+ if (m_bands[i].numluts > 0) {
+
+ // read # of LUT entries
+ charsread += read_verify2(hNITF, m_bands[i].nelutnn, 5);
+ m_bands[i].numlutentries = charptrtoint(m_bands[i].nelutnn, 5);
+
+ // allocate space for the LUT entries
+ m_bands[i].lutdnnm = new char[m_bands[i].numluts * m_bands[i].numlutentries];
+
+ // read LUT entries
+ charsread += read_verify2(hNITF, m_bands[i].lutdnnm, m_bands[i].numluts * m_bands[i].numlutentries);
+
+ } else {
+
+ m_bands[i].lutdnnm = NULL;
+ }
+
+ } /* end for (band_num = 0... */
+
+ } else {
+
+ m_bands = NULL;
+
+ }
+
+ // read m_isync..udidl
+
+ charsread += read_verify2(hNITF, m_isync, (1+1+4+4+4+4+2+3+3+10+4+5));
+ n_udidl = charptrtolong(m_udidl, 5);
+
+ if (n_udidl > 0) {
+ charsread += read_verify2(hNITF, m_udofl, 3);
+ m_udid = new char[n_udidl];
+ charsread += read_verify2(hNITF, m_udid, n_udidl - 3);
+ }
+
+ // read ixshdl
+
+ charsread += read_verify2(hNITF, m_ixshdl, 5);
+ n_ixshdl = charptrtolong(m_ixshdl, 5);
+
+ if (n_ixshdl > 0) {
+ charsread += read_verify2(hNITF, m_ixsofl, 3);
+ m_ixshd = new char[n_ixshdl];
+ charsread += read_verify2(hNITF, m_ixshd, n_ixshdl - 3);
+ }
+
+ /***********************************************************************
+ * MASKED IMAGES ARE IGNORED FOR NOW !!!
+ ***********************************************************************
+
+ strncpy(temp_buffer, m_ic, 2);
+ temp_buffer[2] = '\0';
+
+ if (strcmp(temp_buffer, "NM") == 0 || strcmp(temp_buffer, "M1") == 0
+ || strcmp(temp_buffer, "M3") == 0
+ || strcmp(temp_buffer, "M4") == 0
+ || strcmp(temp_buffer, "M5") == 0) {
+
+ // ERROR not implemented yet masked images
+ }
+
+ ************************************************************************/
+
+ // copy image data
+
+ header_length = lish;
+ data_length = li;
+
+ if(read_image_data == true) {
+ m_data = new char[li];
+ charsread += read_verify2(hNITF, m_data, li);
+ } else {
+ charsread += li;
+ }
+ n_nbpr = 0; // number of blocks per row
+ n_nbpc = 0; // number of blocks per column
+ n_nppbh = 0; // number of of pixels per block horizontally
+ n_nppbv = 0; // number of of pixels per block vertically
+
+ n_nppbh = charptrtoint( m_nppbh, 4);
+ n_nppbv = charptrtoint( m_nppbv, 4);
+ n_nbpr = charptrtoint( m_nbpr, 4);
+ n_nbpc = charptrtoint( m_nbpc, 4);
+
+ cout<<"IC: ";
+ cout.write(m_ic, 2);
+
+ cout<<"\nNBANDS: ";
+ cout.write(m_nbands, 1);
+
+ cout<<"\nnumber of blocks per row: ";
+ cout.write(m_nbpr, 4);
+
+ cout<<"\nNumber of blocks per column: ";
+ cout.write(m_nbpc, 4);
+
+ cout<<"\nImode: ";
+ cout.write(m_imode, 1);
+
+ return charsread;
+
+}
+
+/**********************************************************************
+ * NAME: image::write_file
+ * PURPOSE: write an image object into an ntf file on hard drive
+ *********************************************************************/
+
+int image::write_file(ofstream &fs){
+
+ int charswritten=0;
+
+ fs.write(m_im, 2);
+ fs.write(m_iid1, 10);
+ fs.write(m_idatim, 14);
+ fs.write(m_tgtid, 17);
+ fs.write(m_iid2, 80);
+ fs.write(m_isclas, 1);
+ fs.write(m_isclsy, 2);
+ fs.write(m_iscode, 11);
+ fs.write(m_isctlh, 2);
+ fs.write(m_isrel, 20);
+ fs.write(m_isdctp, 2);
+ fs.write(m_isdcdt, 8);
+ fs.write(m_isdcxm, 4);
+ fs.write(m_isdg, 1);
+ fs.write(m_isdgdt, 8);
+ fs.write(m_iscltx, 43);
+ fs.write(m_iscatp, 1);
+ fs.write(m_iscaut, 40);
+ fs.write(m_iscrsn, 1);
+ fs.write(m_issrdt, 8);
+ fs.write(m_isctln, 15);
+ fs.write(m_encryp, 1);
+ fs.write(m_isorce, 42);
+ fs.write(m_nrows, 8);
+ fs.write(m_ncols, 8);
+ fs.write(m_pvtype, 3);
+ fs.write(m_irep, 8);
+ fs.write(m_icat, 8);
+ fs.write(m_abpp, 2);
+ fs.write(m_pjust, 1);
+ fs.write(m_icords, 1);
+
+ if (m_icords[0] != ' '){
+ fs.write(m_igeolo, 60);
+ charswritten += 60;
+ }
+ fs.write(m_nicom, 1);
+
+ charswritten += 2 + 10 + 14 + 17 + 80 + 1 + 2 + 11 + 2 + 20 + 2 + 8 + 4 +1 + 8 + 43 + 1 + 40 + 1 + 8 + 15 + 1 + 42 + 8 + 8 + 3 + 8 + 8 + 2 + 1 + 1 + 1;
+
+ if (m_icom!=NULL) {
+ fs.write(m_icom, n_nicom * 80);
+ charswritten += n_nicom * 80;
+ }
+
+ fs.write(m_ic, 2);
+ charswritten += 2;
+
+ if ((strncmp(m_ic, "NC", 2) != 0) && (strncmp(m_ic, "NM", 2) != 0)) {
+ fs.write(m_comrat, 4);
+ charswritten += 4;
+ }
+ fs.write(m_nbands, 1);
+ charswritten += 1;
+
+ if (n_nbands == 0) {
+ fs.write(m_xbands, 5);
+ charswritten += 5;
+ }
+
+ if (m_bands != NULL){
+ for (int i=0; i<numbands; i++){
+ fs.write(m_bands[i].irepbandnn, 2);
+ fs.write(m_bands[i].isubcatnn, 6);
+ fs.write(m_bands[i].ifcnn, 1);
+ fs.write(m_bands[i].imfltnn, 3);
+ fs.write(m_bands[i].nlutsnn, 1);
+
+ charswritten += 2 + 6 + 1 + 3 + 1;
+
+ if (m_bands[i].numluts > 0){
+ fs.write(m_bands[i].nelutnn, 5);
+ fs.write(m_bands[i].lutdnnm, m_bands[i].numluts * m_bands[i].numlutentries);
+
+ charswritten += 5 + m_bands[i].numluts * m_bands[i].numlutentries;
+ }
+ }
+ }
+
+ fs.write(m_isync, 1);
+ fs.write(m_imode, 1);
+ fs.write(m_nbpr, 4);
+ fs.write(m_nbpc, 4);
+ fs.write(m_nppbh, 4);
+ fs.write(m_nppbv, 4);
+ fs.write(m_nbpp, 2);
+ fs.write(m_idlvl, 3);
+ fs.write(m_ialvl, 3);
+ fs.write(m_iloc, 10);
+ fs.write(m_imag, 4);
+ fs.write(m_udidl, 5);
+
+ charswritten += 1 + 1 + 4 + 4 + 4 +4 + 2 + 3 + 3 + 10 + 4 + 5;
+
+ if (n_udidl > 0) {
+ fs.write(m_udofl, 3);
+ fs.write(m_udid, n_udidl - 3);
+ charswritten += n_udidl;
+ }
+
+ fs.write(m_ixshdl, 5);
+ charswritten += 5;
+
+ if (n_ixshdl > 0) {
+ fs.write(m_ixsofl, 3);
+ fs.write(m_ixshd, n_ixshdl - 3);
+ charswritten += n_ixshdl;
+ }
+
+
+cout<<" wrote image header length: " << charswritten <<endl;
+if(m_data){
+fs.write(m_data, data_length);
+cout<< "image data length is : "<<data_length<<endl ;
+charswritten += data_length;
+}
+cout<<"IMAGE WRITE_FILE wrote "<< charswritten<<endl;
+
+ return charswritten;
+}
+
+
+/**********************************************************************
+ * NAME:image::get_li
+ * -------------------------------------------------------------------
+ * PURPOSE: image size
+ *********************************************************************/
+
+string image::get_li() const {
+ string temp(textdl);
+ return temp;
+}
+
+/**********************************************************************
+ * NAME:image::get_lish
+ * -------------------------------------------------------------------
+ * PURPOSE: returns the image header size
+ *********************************************************************/
+
+string image::get_lish() const {
+ string temp(texthl);
+ return temp;
+}
+
+
+/**********************************************************************
+ * NAME: image::compute_data_reordering_variables
+ *---------------------------------------------------------------------
+ * PURPOSE: computes some variable necessary for converting data from
+ * the ntf internal data storage to pixel sequential storage and vice
+ * versa
+ *********************************************************************/
+
+void image::compute_data_reordering_variables(){
+
+ int px_comp_size_bits = charptrtoint(m_nbpp, 2);
+
+ if ((px_comp_size_bits % 8) == 0) {
+ px_comp_size = px_comp_size_bits / 8;
+ } else {
+ cout << "unsupported pixel component size "<<endl;
+ exit(101);
+ }
+
+ px_size = px_comp_size * numbands;
+ numblocks = n_nbpc * n_nbpr;
+ block_size_bytes = data_length / numblocks;
+ block_size_pixels = n_nppbv * n_nppbh;
+ block_row_size = block_size_bytes / n_nppbv;
+ block_band_size = block_size_bytes /numbands;
+ block_band_size_px = block_size_pixels / numbands;
+ image_band_size = data_length / numbands;
+
+ n_nrows = charptrtolong(m_nrows, 8);
+ n_ncols = charptrtolong(m_ncols, 8);
+
+}
+
+/**********************************************************************
+ * NAME: image::blpxseq2pxseq
+ * -------------------------------------------------------------------
+ * PURPOSE: coverts memory data from block pixel sequential to pixel
+ * sequential storage
+ *********************************************************************/
+
+int image::blpxseq2pxseq(char* src, char* dest){
+
+ char *rowblockstart = NULL;
+ char *writefrom = NULL;
+
+
+ cout<< "n_nbpc: "<<n_nbpc <<endl;
+ cout<< "n_nbpr: " <<n_nbpr<<endl;
+ cout<< "block_size_bytes: " << block_size_bytes <<endl;
+ cout<< "block_row_size: " << block_row_size <<endl;
+
+ for (int vbindex=0; vbindex < n_nbpc; vbindex++){
+
+ rowblockstart = (char*)(src + vbindex * n_nbpr * block_size_bytes);
+
+ for (int hbindex = 0; hbindex < n_nbpr; hbindex++){
+
+ for(int i = 0; i < n_nppbv; i++){
+
+ writefrom = (char*) (rowblockstart + i * n_nbpr * block_row_size + hbindex * block_row_size );
+ strncpy(dest, writefrom , block_row_size);
+ dest += block_row_size;
+
+ cout<< "writing row: "<< i <<" of BLOCK: " << hbindex << "IN BLOCK ROW "<< vbindex<<endl;
+
+ cout << "writefrom "<< int(writefrom) <<"dest" << int(dest) <<" block row size " << block_row_size <<endl;
+ }
+ }
+ }
+
+ return 0;
+
+}
+
+/**********************************************************************
+ * NAME: image::pxseq2blpxseq
+ * -------------------------------------------------------------------
+ * PURPOSE: coverts memory data from pixel sequential to block pixel
+ * sequential storage
+ *********************************************************************/
+
+int image::pxseq2blpxseq(char* src, char* dest){
+
+ char *rowblockstart = NULL;
+ char *copyfrom = NULL;
+
+ for (int vbindex=0; vbindex < n_nbpc; vbindex++){
+
+ rowblockstart = (char*)(src + vbindex * n_nbpr * block_size_bytes);
+
+ for (int hbindex = 0; hbindex < n_nbpr; hbindex++){
+ for(int i = 0; i < n_nppbv; i++){
+ copyfrom = (char*) (rowblockstart + i * n_nbpr * block_row_size + hbindex * block_row_size );
+ strncpy(dest, copyfrom, block_row_size);
+ dest += block_row_size;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**********************************************************************
+ * NAME: image::to_pixel_sequential
+ * --------------------------------------------------------------------
+ * PURPOSE: determines internal ntf image storage and chooses which
+ * convertion function to call in oreder to make the data pixel
+ * sequential
+ *********************************************************************/
+
+int image::to_pixel_sequential(){
+
+ string ic(m_ic,2);
+
+ if(ic=="NC"){
+
+ compute_data_reordering_variables();
+
+ if (numbands == 1) {
+
+ imode_1band2ps();
+
+ } else if (numbands == 3) {
+
+ switch(*m_imode) {
+ case 'B':
+ return imode_b2ps();
+ case 'P':
+ return imode_p2ps();
+ case 'S':
+ return imode_s2ps();
+ case 'R':
+ return imode_r2ps();
+ default:
+ exit(102);
+ }
+ }
+
+ return 0;
+
+ } else {
+ exit(103);
+ }
+
+}
+
+/**********************************************************************
+ * NAME: image::to_block_pixel_sequential
+ * --------------------------------------------------------------------
+ * PURPOSE: determines internal ntf image storage and chooses which
+ * convertion function to call in oreder to make the data block pixel
+ * sequential
+ *********************************************************************/
+
+int image::to_block_pixel_sequential(char* src){
+
+ string ic(m_ic,2);
+
+ if(ic=="NC"){
+
+ compute_data_reordering_variables();
+
+ if (numbands == 1) {
+
+ imode_ps21band(src);
+
+ } else if (numbands == 3) {
+
+ switch(*m_imode) {
+ case 'B':
+ return imode_ps2b(src);
+ case 'P':
+ return imode_ps2p(src);
+ case 'S':
+ return imode_ps2s(src);
+ case 'R':
+ return imode_ps2r(src);
+ default:
+ exit(104);
+ }
+ }
+
+ return 0;
+
+ } else {
+ exit(105);
+ }
+
+}
+
+/**********************************************************************
+ * NAME: image::imode_1band2ps
+ * --------------------------------------------------------------------
+ * PURPOSE: data convertion fucntion for the data of an image with 1
+ * band only (for details see NITF spec imode field)
+ *********************************************************************/
+
+int image::imode_1band2ps() {
+
+ char* temp_data = new char [data_length];
+ strncpy(temp_data, m_data, data_length);
+ blpxseq2pxseq(temp_data, m_data);
+ delete temp_data;
+
+ return 0;
+}
+
+/**********************************************************************
+ * NAME: image::imode_ps21band
+ * --------------------------------------------------------------------
+ * PURPOSE: data convertion fucntion for the data of an image with 1
+ * band only (for details see NITF spec imode field)
+ *********************************************************************/
+
+int image::imode_ps21band(char* src) {
+
+ pxseq2blpxseq(src, m_data);
+
+ return 0;
+}
+
+
+/**********************************************************************
+ * NAME: image::imode_b2ps
+ * -------------------------------------------------------------------
+ * PURPOSE: data convertion fucntion for the data of an image stored
+ * in band interleaved by block internal storage (for details see NITF
+ * spec imode field)
+ *********************************************************************/
+
+int image::imode_b2ps() {
+/*
+ char* kurets = new char[24];
+ strncpy(kurets, "ADMPBENQCFORGJSVHKTXILUY", 24);
+ char* temp_data = new char[24];
+ char* beginning = temp_data;
+ char* read_sofar = kurets;
+ char* RED_offset = NULL;
+ char* GREEN_offset = NULL;
+ char* BLUE_offset = NULL;
+
+ for(int block_index = 0; block_index < 2; block_index++) {
+
+ RED_offset = read_sofar;
+ GREEN_offset = (char*)(read_sofar + 4);
+ BLUE_offset = (char*)(read_sofar + 8);
+
+ for (int i=0; i < 4; i++) {
+ for (int j = 0; j < 1; j++){
+ cout<<RED_offset[0]<<endl;
+ *temp_data++ = *RED_offset++;
+ read_sofar++;
+ }
+ for (int j = 0; j < 1; j++){
+ cout<<GREEN_offset[0]<<endl;
+ *temp_data++ = *GREEN_offset++;
+ read_sofar++;
+ }
+ for (int j = 0; j < 1; j++){
+ cout<<BLUE_offset[0]<<endl;
+ *temp_data++ = *BLUE_offset++;
+ read_sofar++;
+ }
+ }
+ }
+ temp_data=beginning;
+ cout.write(temp_data, 24);
+ cout<<endl;
+ blpxseq2pxseq(temp_data, kurets);
+ cout.write(kurets, 24);
+ exit(1234);
+ delete temp_data;
+ return 0;
+*/
+
+ char* temp_data = new char[data_length];
+ char* read_sofar = m_data;
+ char* RED_offset = NULL;
+ char* GREEN_offset = NULL;
+ char* BLUE_offset = NULL;
+
+ for(int block_index = 0; block_index < numblocks; block_index++) {
+
+ RED_offset = read_sofar;
+ GREEN_offset = (char*)(read_sofar + block_band_size);
+ BLUE_offset = (char*)(read_sofar + 2 * block_band_size);
+
+ for (int i=0; i < block_band_size_px; i++) {
+ for (int j = 0; j < px_comp_size; j++){
+ *temp_data++ = *RED_offset++;
+ read_sofar++;
+ }
+ for (int j = 0; j < px_comp_size; j++){
+ *temp_data++ = *GREEN_offset++;
+ read_sofar++;
+ }
+ for (int j = 0; j < px_comp_size; j++){
+ *temp_data++ = *BLUE_offset++;
+ read_sofar++;
+ }
+ }
+ }
+
+ blpxseq2pxseq(temp_data, m_data);
+
+ delete temp_data;
+ return 0;
+
+}
+
+/**********************************************************************
+ * NAME: image::imode_ps2b
+ * -------------------------------------------------------------------
+ * PURPOSE: data convertion fucntion for the data of an image stored
+ * in band interleaved by block internal storage (for details see NITF
+ * spec imode field)
+ *********************************************************************/
+
+int image::imode_ps2b(char* src) {
+
+ char* temp_data = new char[data_length];
+ pxseq2blpxseq(src, temp_data);
+
+ char* written_sofar = m_data;
+ char* RED_offset = NULL;
+ char* GREEN_offset = NULL;
+ char* BLUE_offset = NULL;
+
+ for(int block_index = 0; block_index < numblocks; block_index++) {
+
+ RED_offset = m_data;
+ GREEN_offset = (char*)(written_sofar + block_band_size);
+ BLUE_offset = (char*)(written_sofar + 2 * block_band_size);
+
+ for (int i=0; i < block_band_size_px; i++) {
+ for (int j = 0; j < px_comp_size; j++){
+ *RED_offset++ = *temp_data++;
+ written_sofar++;
+ }
+ for (int j = 0; j < px_comp_size; j++){
+ *GREEN_offset++ = *temp_data++;
+ written_sofar++;
+ }
+ for (int j = 0; j < px_comp_size; j++){
+ *BLUE_offset++ = *temp_data++;
+ written_sofar++;
+ }
+ }
+ }
+
+ delete temp_data;
+
+ return 0;
+}
+
+/**********************************************************************
+ * NAME:image::imode_p2ps
+ * --------------------------------------------------------------------
+ * PURPOSE: data convertion fucntion for the data of an image stored
+ * in band interleaved by pixel by block internal storage (for details
+ * see NITF spec imode field)
+ *********************************************************************/
+
+int image::imode_p2ps() {
+
+ char* temp_data = new char [data_length];
+ strncpy(temp_data, m_data, data_length);
+ blpxseq2pxseq(temp_data, m_data);
+ delete temp_data;
+
+ return 0;
+}
+
+/**********************************************************************
+ * NAME:image::imode_ps2p
+ * --------------------------------------------------------------------
+ * PURPOSE: data convertion fucntion for the data of an image stored
+ * in band interleaved by pixel by block internal storage (for details
+ * see NITF spec imode field)
+ *********************************************************************/
+
+int image::imode_ps2p(char* src){
+
+ pxseq2blpxseq(src, m_data);
+ return 0;
+}
+
+
+/**********************************************************************
+ * NAME:image::imode_r2ps
+ * --------------------------------------------------------------------
+ * PURPOSE: data convertion fucntion for the data of an image stored
+ * in band interleaved by row by block internal storage ( for details
+ * see NITF spec imode field)
+ *********************************************************************/
+
+int image::imode_r2ps() {
+
+ char* temp_data = new char [data_length];
+
+ char* read_sofar = m_data;
+ char* RED_offset = NULL;
+ char* GREEN_offset = NULL;
+ char* BLUE_offset = NULL;
+
+ int block_row_band_size = block_row_size/numbands;
+
+ for(int block_index = 0; block_index < numblocks ; block_index++) {
+ for (int rowinblock = 0; rowinblock < n_nppbv; rowinblock++){
+
+ RED_offset = read_sofar;
+ GREEN_offset =(char*) (read_sofar + block_row_band_size);
+ BLUE_offset = (char*) (read_sofar+ 2 * block_row_band_size);
+
+ for (int i = 0; i < n_nppbh; i++){
+
+ for (int j = 0; j < px_comp_size; j++){
+ *temp_data++ = *RED_offset++;
+ read_sofar++;
+ }
+
+ for (int j = 0; j < px_comp_size; j++){
+ *temp_data++ = *GREEN_offset++;
+ read_sofar++;
+ }
+
+ for (int j = 0; j < px_comp_size; j++){
+
+ *temp_data++ = *BLUE_offset++;
+ read_sofar++;
+ }
+ }
+ }
+ }
+
+ blpxseq2pxseq(temp_data, m_data);
+ delete temp_data;
+ return 0;
+}
+
+/**********************************************************************
+ * NAME:image::imode_ps2r
+ * --------------------------------------------------------------------
+ * PURPOSE: data convertion fucntion for the data of an image stored
+ * in band interleaved by row by block internal storage ( for details
+ * see NITF spec imode field)
+ *********************************************************************/
+
+int image::imode_ps2r(char* src) {
+
+ char* temp_data = new char [data_length];
+ pxseq2blpxseq(src, temp_data);
+
+ char* written_sofar = m_data;
+ char* RED_offset = NULL;
+ char* GREEN_offset = NULL;
+ char* BLUE_offset = NULL;
+
+ int block_row_band_size = block_row_size/numbands;
+
+ for(int block_index = 0; block_index < numblocks ; block_index++) {
+ for (int rowinblock = 0; rowinblock < n_nppbv; rowinblock++){
+
+ RED_offset = written_sofar;
+ GREEN_offset =(char*) (written_sofar + block_row_band_size);
+ BLUE_offset = (char*) (written_sofar+ 2 * block_row_band_size);
+
+ for (int i = 0; i < n_nppbh; i++){
+
+ for (int j = 0; j < px_comp_size; j++){
+ *RED_offset++ = *temp_data++;
+ written_sofar++;
+ }
+
+ for (int j = 0; j < px_comp_size; j++){
+ *GREEN_offset++ = *temp_data++;
+ written_sofar++;
+ }
+
+ for (int j = 0; j < px_comp_size; j++){
+ *BLUE_offset++ = *temp_data++;
+ written_sofar++;
+ }
+ }
+ }
+ }
+
+ delete temp_data;
+ return 0;
+}
+
+
+/**********************************************************************
+ * NAME:image::imode_s2ps
+ * -------------------------------------------------------------------
+ * PURPOSE: data convertion fucntion for the data of an image stored
+ * in band sequential internal storage (for details see NITF spec
+ * imode field)
+ *********************************************************************/
+
+int image::imode_s2ps() {
+
+ int numpix = n_nrows * n_ncols;
+
+ char* temp_data = new char [data_length];
+
+ char* RED_offset = m_data;
+ char* GREEN_offset = (char*)(m_data + image_band_size);
+ char* BLUE_offset = (char*)(m_data + 2 * image_band_size);
+
+ for (int i=0; i < numpix; i++) {
+
+ for (int j = 0; j < px_comp_size; j++){
+ *temp_data++ = *RED_offset++;
+ }
+
+ for (int j = 0; j < px_comp_size; j++){
+ *temp_data++ = *GREEN_offset++;
+ }
+
+ for (int j = 0; j < px_comp_size; j++){
+
+ *temp_data++ = *BLUE_offset++;
+ }
+ }
+
+ blpxseq2pxseq(temp_data, m_data);
+ delete temp_data;
+
+ return 0;
+}
+
+/**********************************************************************
+ * NAME:image::imode_ps2s
+ * -------------------------------------------------------------------
+ * PURPOSE: data convertion fucntion for the data of an image stored
+ * in band sequential internal storage (for details see NITF spec
+ * imode field)
+ *********************************************************************/
+
+int image::imode_ps2s(char* src) {
+
+ char* temp_data = new char[data_length];
+ pxseq2blpxseq(src, temp_data);
+
+ int numpix = n_nrows * n_ncols;
+
+ char* RED_offset = m_data;
+ char* GREEN_offset = (char*)(m_data + image_band_size);
+ char* BLUE_offset = (char*)(m_data + 2 * image_band_size);
+
+ for (int i=0; i < numpix; i++) {
+
+ for (int j = 0; j < px_comp_size; j++){
+ *RED_offset++ = *temp_data++;
+ }
+
+ for (int j = 0; j < px_comp_size; j++){
+ *GREEN_offset++ = *temp_data++;
+ }
+
+ for (int j = 0; j < px_comp_size; j++){
+ *BLUE_offset++ = *temp_data++;
+ }
+ }
+
+ delete temp_data;
+
+ return 0;
+}
+
+long image::get_size() const
+{
+ return data_length;
+}
+
+int image::get_width() const
+{
+ return n_nrows;
+}
+
+int image::get_height() const
+{
+ return n_ncols;
+}
+
+string image::get_irep() const {
+ return string(m_irep, 8);
+}
+
+string image::get_pvtype() const {
+ return string(m_pvtype, 3);
+}
+
+int image::get_nbpp_bytes() const {
+
+ return charptrtoint(m_nbpp, 2);
+}
diff --git a/conversion/image.h b/conversion/image.h
new file mode 100644
index 0000000..91213ed
--- /dev/null
+++ b/conversion/image.h
@@ -0,0 +1,226 @@
+/*
+* 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>.
+*/
+
+#ifndef __RASNITF_IMAGE_H
+#define __RASNITF_IMAGE_H
+
+#include <fstream>
+#include <iostream>
+
+namespace RasNITF{
+
+class image_band{
+
+ public:
+
+ char irepbandnn[2];
+ char isubcatnn[6];
+ char ifcnn[1];
+ char imfltnn[3];
+ char nlutsnn[1];
+ char nelutnn[5];
+ int numluts;
+ int numlutentries;
+ char* lutdnnm;
+
+ image_band();
+ ~image_band();
+
+};
+
+class image {
+
+ /*********************************
+ * image header fields
+ ********************************/
+
+ char m_im[2];
+ char m_iid1[10];
+ char m_idatim[14];
+ char m_tgtid[17];
+ char m_iid2[80];
+ char m_isclas[1];
+ char m_isclsy[2];
+ char m_iscode[11];
+ char m_isctlh[2];
+ char m_isrel[20];
+ char m_isdctp[2];
+ char m_isdcdt[8];
+ char m_isdcxm[4];
+ char m_isdg[1];
+ char m_isdgdt[8];
+ char m_iscltx[43];
+ char m_iscatp[1];
+ char m_iscaut[40];
+ char m_iscrsn[1];
+ char m_issrdt[8];
+ char m_isctln[15];
+ char m_encryp[1];
+ char m_isorce[42];
+ char m_nrows[8];
+ char m_ncols[8];
+ char m_pvtype[3];
+ char m_irep[8];
+ char m_icat[8];
+ char m_abpp[2];
+ char m_pjust[1];
+ char m_icords[1];
+ char m_igeolo[60];
+ char m_nicom[1];
+ char* m_icom;
+ char m_ic[2];
+ char m_comrat[4];
+ char m_nbands[1];
+ char m_xbands[5];
+ image_band* m_bands;
+ char m_isync[1];
+ char m_imode[1];
+ char m_nbpr[4];
+ char m_nbpc[4];
+ char m_nppbh[4];
+ char m_nppbv[4];
+ char m_nbpp[2];
+ char m_idlvl[3];
+ char m_ialvl[3];
+ char m_iloc[10];
+ char m_imag[4];
+ char m_udidl[5];
+ char m_udofl[3];
+ char* m_udid;
+ char m_ixshdl[5];
+ char m_ixsofl[3];
+ char* m_ixshd;
+
+ /*****************************
+ * image data mask table
+ ****************************/
+
+ /*
+ long imdataoff;
+ unsigned short bmrlnth;
+ unsigned short tmrlnth;
+ unsigned short tpxcdlnth;
+ long tpxcd;
+ char* BMRnBNDm;
+ char* TMRnBNDm;
+ */
+
+ /*****************************
+ * raw image data
+ *****************************/
+
+ char* m_data;
+
+ /*****************************
+ * additional variables
+ *****************************/
+
+// bool compressed;
+ int n_nicom;
+ int n_nbands;
+ int n_xbands;
+ int numbands;
+ int n_udidl;
+ int n_ixshdl;
+ long header_length;
+ long data_length;
+ char texthl[6];
+ char textdl[10];
+ int n_nbpr;
+ int n_nbpc;
+ int n_nppbh;
+ int n_nppbv;
+
+ /*****************************
+ * variables for data reordering
+ * populated by compute_data_reordering_variables()
+ *****************************/
+
+ int n_nrows;
+ int n_ncols;
+ int px_comp_size;
+ int px_size;
+ int numblocks;
+
+ long block_size_bytes;
+ long block_size_pixels;
+ long block_row_size; //bytes
+ long block_band_size; //bytes
+ long block_band_size_px;
+ long image_band_size;
+
+
+ int copy_block_data(char* writeto, int hor_block_index, int ver_block_index );
+
+ // functions for data reordering
+
+ void compute_data_reordering_variables();
+
+ int blpxseq2pxseq(char* src, char* dest);
+ int pxseq2blpxseq(char*, char*);
+
+ int imode_1band2ps();
+ int imode_b2ps();
+ int imode_r2ps();
+ int imode_p2ps();
+ int imode_s2ps();
+
+ int imode_ps21band(char*);
+ int imode_ps2b(char*);
+ int imode_ps2r(char*);
+ int imode_ps2p(char*);
+ int imode_ps2s(char*);
+
+
+ public:
+
+ image();
+ ~image();
+
+ int read_file(std::istream&, long, long, bool read_image_data);
+ int write_file(std::ofstream& fs);
+
+ std::string get_li() const;
+ std::string get_lish() const;
+ long get_size() const;
+ int get_width() const;
+ int get_height() const;
+
+ int to_pixel_sequential();
+ int to_block_pixel_sequential(char* src);
+
+ std::string get_irep() const;
+ std::string get_pvtype() const;
+
+ int get_nbpp_bytes() const;
+
+// char* get_data_ptr();
+
+
+};
+
+}
+
+#endif
+
+
diff --git a/conversion/int16.cc b/conversion/int16.cc
new file mode 100644
index 0000000..abd8a2f
--- /dev/null
+++ b/conversion/int16.cc
@@ -0,0 +1,874 @@
+/*
+* 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: int16.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_int16
+ *
+ * COMMENTS:
+ * Provides interface to convert data from/to Array format to/from int16 format.
+ *
+*/
+
+static const char rcsid[] = "@(#)conversion,r_Conv_int16: $Id: int16.cc,v 1.8 2002/10/01 09:16:38 coman Exp $";
+
+#include "conversion/int16.hh"
+
+#include <float.h>
+#include <string>
+#include <cstring>
+#include <strstream>
+#include <sstream>
+#include <algorithm>
+
+using std::istringstream;
+using std::istrstream;
+using std::string;
+
+#include "raslib/rminit.hh"
+#include "raslib/parseparams.hh"
+#include "raslib/primitivetype.hh"
+
+
+const r_Dimension r_Conv_int16::srcIntervDim=1;
+const r_Dimension r_Conv_int16::destIntervDim=2;
+const r_ULong r_Conv_int16::paramMin=6;
+const char* r_Conv_int16::paramSep=",";
+const char* r_Conv_int16::paramEq="=";
+const char* r_Conv_int16::paramFlipX="flipx";
+const char* r_Conv_int16::paramFlipY="flipy";
+const char* r_Conv_int16::paramStartX="startx";
+const char* r_Conv_int16::paramEndX="endx";
+const char* r_Conv_int16::paramResX="resx";
+const char* r_Conv_int16::paramStartY="starty";
+const char* r_Conv_int16::paramEndY="endy";
+const char* r_Conv_int16::paramResY="resy";
+
+const r_Double r_Conv_int16::NULL_DB = 0.;
+const r_Double r_Conv_int16::ZERO_DB = FLT_MIN;
+const r_Double r_Conv_int16::ZERO_int16 = 0.;
+
+r_Conv_int16::~r_Conv_int16( void )
+{
+ //nothing to care for
+}
+
+void r_Conv_int16::initGeoBBox( r_GeoBBox& cBBox )
+{
+ //flipy is selected by default
+ cBBox.flipy = 1;
+
+ //flipx is not selected by default
+ cBBox.flipx = 0;
+
+ //geo information are initialized by default to DBL_MAX
+ // FIXME: better defaults res=1, min=-MAX?
+ cBBox.startx = DBL_MAX;
+ cBBox.endx = DBL_MAX;
+ cBBox.resx = DBL_MAX;
+ cBBox.starty = DBL_MAX;
+ cBBox.endy = DBL_MAX;
+ cBBox.resy = DBL_MAX;
+}
+
+r_Conv_int16::r_Conv_int16(const char* source, const r_Minterval& lengthordomain, const r_Type* tp) throw(r_Error)
+ : r_Convertor(source, lengthordomain, tp, true)
+{
+ initGeoBBox(collBBox);
+}
+
+r_Conv_int16::r_Conv_int16(const char* source, const r_Minterval& lengthordomain, int tp) throw(r_Error)
+ : r_Convertor(source, lengthordomain, tp)
+{
+ initGeoBBox(collBBox);
+}
+
+bool
+r_Conv_int16::decodeOptions(const char* options,
+ r_GeoBBox& cBBox) throw()
+{
+ RMInit::logOut << "r_Conv_int16::decodeOptions(" << (options?options:"NULL") << ")" << endl;
+
+ r_Parse_Params parseParams;
+
+ initGeoBBox(cBBox);
+
+ parseParams.add(paramFlipX, &cBBox.flipx, r_Parse_Params::param_type_int);
+ parseParams.add(paramFlipY, &cBBox.flipy, r_Parse_Params::param_type_int);
+ parseParams.add(paramStartX, &cBBox.startx, r_Parse_Params::param_type_double);
+ parseParams.add(paramEndX, &cBBox.endx, r_Parse_Params::param_type_double);
+ parseParams.add(paramResX, &cBBox.resx, r_Parse_Params::param_type_double);
+ parseParams.add(paramStartY, &cBBox.starty, r_Parse_Params::param_type_double);
+ parseParams.add(paramEndY, &cBBox.endy, r_Parse_Params::param_type_double);
+ parseParams.add(paramResY, &cBBox.resy, r_Parse_Params::param_type_double);
+
+ //process options
+ r_Long processRet=parseParams.process(options);
+ if(processRet < paramMin)
+ {
+ RMInit::logOut << "r_Conv_int16::decodeOptions(...) Error: Some required options are missing!" << endl;
+ return false;
+ }
+
+ //check if start,res,end are present
+ if(cBBox.startx == DBL_MAX)
+ {
+ RMInit::logOut << "r_Conv_int16::decodeOptions(...) Error: startx is not present!" << endl;
+ return false;
+ }
+
+ if(cBBox.starty == DBL_MAX)
+ {
+ RMInit::logOut << "r_Conv_int16::decodeOptions(...) Error: starty is not present!" << endl;
+ return false;
+ }
+
+ if(cBBox.endx == DBL_MAX)
+ {
+ RMInit::logOut << "r_Conv_int16::decodeOptions(...) Error: endx is not present!" << endl;
+ return false;
+ }
+
+ if(cBBox.endy == DBL_MAX)
+ {
+ RMInit::logOut << "r_Conv_int16::decodeOptions(...) Error: endy is not present!" << endl;
+ return false;
+ }
+
+ if(cBBox.resx == DBL_MAX)
+ {
+ RMInit::logOut << "r_Conv_int16::decodeOptions(...) Error: resx is not present!" << endl;
+ return false;
+ }
+
+ if(cBBox.resy == DBL_MAX)
+ {
+ RMInit::logOut << "r_Conv_int16::decodeOptions(...) Error: resy is not present!" << endl;
+ return false;
+ }
+
+
+ //check res
+ if(!cBBox.resx)
+ {
+ RMInit::logOut << "r_Conv_int16::decodeOptions(...) Error: resx is zero!" << endl;
+ return false;
+ }
+
+ if(!cBBox.resy)
+ {
+ RMInit::logOut << "r_Conv_int16::decodeOptions(...) Error: resy is zero!" << endl;
+ return false;
+ }
+
+ //check start >= end
+ if(cBBox.startx >= cBBox.endx )
+ {
+ RMInit::logOut << "r_Conv_int16::decodeOptions(...) Error: startx >= endx!" << endl;
+ return false;
+ }
+
+ if(cBBox.starty >= cBBox.endy)
+ {
+ RMInit::logOut << "r_Conv_int16::decodeOptions(...) Erorr: starty >= endy!" << endl;
+ return false;
+ }
+
+ //show parsed options
+ RMInit::logOut.setf(std::ios::fixed);
+ RMInit::logOut << "r_Conv_int16::decodeOptions(...) parsed options:" << endl
+ << " " << paramFlipX << paramEq << cBBox.flipx
+ << " " << paramFlipY << paramEq << cBBox.flipy << endl
+ << " " << paramStartX << paramEq << cBBox.startx
+ << " " << paramEndX << paramEq << cBBox.endx
+ << " " << paramResX << paramEq << cBBox.resx << endl
+ << " " << paramStartY << paramEq << cBBox.starty
+ << " " << paramEndY << paramEq << cBBox.endy
+ << " " << paramResY << paramEq << cBBox.resy << endl;
+ return true;
+}
+
+string
+r_Conv_int16::encodeOptions(const r_GeoBBox& cBBox) throw()
+{
+ std::ostringstream os;
+
+ os.str("");
+ os.setf(std::ios::fixed);
+ os << paramFlipX << paramEq << cBBox.flipx
+ << paramSep << paramFlipY << paramEq << cBBox.flipy
+ << paramSep << paramStartX << paramEq << cBBox.startx
+ << paramSep << paramEndX << paramEq << cBBox.endx
+ << paramSep << paramResX << paramEq << cBBox.resx
+ << paramSep << paramStartY << paramEq << cBBox.starty
+ << paramSep << paramEndY << paramEq << cBBox.endy
+ << paramSep << paramResY << paramEq << cBBox.resy;
+
+ RMInit::logOut << "r_Conv_int16::encodeOptions(" << os.str() << ")" << endl;
+
+ return os.str();
+}
+
+void
+r_Conv_int16::checkLimits() throw(r_Error)
+{
+ //show processed data
+ RMInit::logOut << "r_Conv_int16::checkLimits() processed data:" << endl
+ << " minx=" << min.x << " miny=" << min.y << " minh=" << min.h << endl
+ << " maxx=" << max.x << " maxy=" << max.y << " maxh=" << max.h << endl;
+ // printf( "r_Conv_int16::checkLimits() processed data: minx=%8G, miny=%8G, minh=%8G, maxx=%8G, maxy=%8G, maxh=%8G\n", min.x, min.y, min.h, max.x, max.y, max.h );
+
+ if(collBBox.startx > min.x)
+ {
+ RMInit::logOut << "r_Conv_int16::checkLimits() startx( " << collBBox.startx << ") > min.x (" << min.x << " )!" << endl;
+ throw r_Error();
+ }
+ if(collBBox.endx < max.x)
+ {
+ RMInit::logOut << "r_Conv_int16::checkLimits() endx( " << collBBox.endx << ") < max.x (" << max.x << " )!" << endl;
+ throw r_Error();
+ }
+
+ if(collBBox.starty > min.y)
+ {
+ RMInit::logOut << "r_Conv_int16::checkLimits() starty( " << collBBox.starty << ") > min.y (" << min.y << " )!" << endl;
+ throw r_Error();
+ }
+
+ if(collBBox.endy < max.y)
+ {
+ RMInit::logOut << "r_Conv_int16::checkLimits() endy( " << collBBox.endy << ") < max.y (" << max.y << " )!" << endl;
+ throw r_Error();
+ }
+}
+
+void
+r_Conv_int16::readFromSrcStream() throw(r_Error)
+{
+ istrstream iFile(desc.src, desc.srcInterv[0].get_extent());
+ string currStrRow;
+ istringstream icurrRow;
+ r_Long rowNo=0;
+ r_Double noResx, noResy;
+ int16Row currRow, prevRow;
+
+ min.x=min.y=min.h=DBL_MAX;
+ max.x=max.y=max.h=-DBL_MAX;
+ demRows.clear();
+
+ //process the lines
+ while(!iFile.eof())
+ {
+ getline(iFile, currStrRow);
+ rowNo++;
+ if(currStrRow.empty())
+ {
+ RMInit::logOut << "r_Conv_int16::readFromSrcStream() skipping empty line " << rowNo << endl;
+ continue;
+ }
+ else
+ {
+ icurrRow.str(currStrRow);
+
+ //decode x
+ icurrRow >> currRow.x;
+ if(!icurrRow)
+ {
+ RMInit::logOut << "r_Conv_int16::readFromSrcStream() skiping line " << rowNo
+ << "(unable to decode x) !" << endl;
+ continue;
+ }
+
+ //decode y
+ icurrRow >> currRow.y;
+ if(!icurrRow)
+ {
+ RMInit::logOut << "r_Conv_int16::readFromSrcStream() skiping line " << rowNo
+ << "(unable to decode y) !" << endl;
+ continue;
+ }
+
+ //decode h
+ icurrRow >> currRow.h;
+ if(!icurrRow)
+ {
+ RMInit::logOut << "r_Conv_int16::readFromSrcStream() skiping line " << rowNo
+ << "(unable to decode h) !" << endl;
+ continue;
+ }
+
+ //update to support NULL value: 0. (real value) goes in FLT_MIN(db value)
+ //because 0.(db value) represent NULL(real value). When we do export we skip NULL values.
+ if(currRow.h == ZERO_int16) currRow.h=ZERO_DB;
+
+ //FIXME we ignore this check, because it may happen to have a incomplet dem
+ /*
+ //check if we have resx, resy
+ noResx=currRow.x/collBBox.resx;
+ if((currRow.x - noResx*collBBox.resx) > 0.)
+ {
+ RMInit::logOut << "r_Conv_int16::readFromSrcStream() resolution for x on line " <<
+ rowNo << " is not " << collBBox.resx << " !" << endl;
+ throw r_Error();
+ }
+ noResy=currRow.y/collBBox.resy;
+ if((currRow.y - noResy*collBBox.resy) > 0.)
+ {
+ RMInit::logOut << "r_Conv_int16::readFromSrcStream() resolution for y on line " <<
+ rowNo << " is not " << collBBox.resy << " !" << endl;
+ throw r_Error();
+ }
+ */
+
+ //compute min, max for x,y,z
+ min.x=std::min<r_Double>(min.x, currRow.x);
+ min.y=std::min<r_Double>(min.y, currRow.y);
+ min.h=std::min<r_Double>(min.h, currRow.h);
+ max.x=std::max<r_Double>(max.x, currRow.x);
+ max.y=std::max<r_Double>(max.y, currRow.y);
+ max.h=std::max<r_Double>(max.h, currRow.h);
+
+ //store currRow
+ demRows.push_back(currRow);
+ }//end if(currStrRow.empty())
+ }//end reading src stream
+
+ if(demRows.empty())
+ {
+ RMInit::logOut << "r_Conv_int16::readFromSrcStream() desc.src stream is empty !" << endl;
+ throw r_Error();
+ }
+
+ //check limits
+ checkLimits();
+}
+
+
+void
+r_Conv_int16::readToSrcStream() throw(r_Error)
+{
+ r_Long x=0, y=0;
+ r_Long xlow=0, ylow=0;
+ r_Long xhigh=0, yhigh=0;
+ int16Row currRow;
+ r_Bytes typeSize=0;
+ r_Long offset=0;
+ char* buffer=NULL;
+
+ //initialize
+ xlow=desc.srcInterv[0].low();
+ ylow=desc.srcInterv[1].low();
+
+ xhigh=desc.srcInterv[0].high();
+ yhigh=desc.srcInterv[1].high();
+
+ //compute min & max
+ if (collBBox.flipx)
+ {
+ min.x=collBBox.endx - xhigh*collBBox.resx;
+ max.x=collBBox.endx - xlow*collBBox.resx;
+ }
+ else
+ {
+ min.x=collBBox.startx + xlow*collBBox.resx;
+ max.x=collBBox.startx + xhigh*collBBox.resx;
+ }
+
+ if(collBBox.flipy)
+ {
+ min.y=collBBox.endy - yhigh*collBBox.resy;
+ max.y=collBBox.endy - ylow*collBBox.resy;
+ }
+ else
+ {
+ min.y=collBBox.starty + ylow*collBBox.resy;
+ max.y=collBBox.starty + yhigh*collBBox.resy;
+ }
+
+ min.h=DBL_MAX;
+ max.h=-DBL_MAX;
+
+ //check limits
+ checkLimits();
+
+ //prepare container
+ demRows.clear();
+ typeSize=((r_Primitive_Type*)desc.srcType)->size();
+ buffer=new char[typeSize];
+ if(!buffer)
+ {
+ RMInit::logOut << "r_Conv_int16::readToSrcStream() unable to claim memory !" << endl;
+ throw r_Ememory_allocation();
+ }
+
+ for(y=ylow; y<=yhigh; y++)
+ {
+ if(collBBox.flipy)
+ currRow.y=collBBox.endy - y*collBBox.resy;
+ else
+ currRow.y=collBBox.starty + y*collBBox.resy;
+
+ for(x=xlow; x<=xhigh; x++)
+ {
+ if(collBBox.flipx)
+ currRow.x=collBBox.endx - x*collBBox.resx;
+ else
+ currRow.x=collBBox.startx + x*collBBox.resx;
+ offset=desc.srcInterv.cell_offset(r_Point(x,y))*typeSize;
+ memcpy(buffer, &desc.src[offset], typeSize);
+ switch(desc.srcType->type_id())
+ {
+ case r_Type::BOOL:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_boolean(buffer);
+ break;
+ case r_Type::CHAR:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_char(buffer);
+ break;
+ case r_Type::OCTET:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_octet(buffer);
+ break;
+ case r_Type::SHORT:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_short(buffer);
+ break;
+ case r_Type::USHORT:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_ushort(buffer);
+ break;
+ case r_Type::LONG:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_long(buffer);
+ break;
+ case r_Type::ULONG:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_ulong(buffer);
+ break;
+ case r_Type::FLOAT:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_float(buffer);
+ break;
+ case r_Type::DOUBLE:
+ currRow.h=((r_Primitive_Type*)desc.srcType)->get_double(buffer);
+ break;
+ default:
+ //write message to log
+ RMInit::logOut << "r_Conv_int16::readToSrcStream() srcType (" << desc.srcType->type_id() << ") unsupported !" << endl;
+ //clean up
+ if(buffer)
+ {
+ delete[] buffer;
+ buffer=NULL;
+ }
+ //report error
+ throw r_Error();
+ break;
+ }
+ min.h=std::min<r_Double>(min.h, currRow.h);
+ max.h=std::max<r_Double>(max.h, currRow.h);
+ demRows.push_back(currRow);
+ }
+ }
+
+ //clean up
+ if(buffer)
+ {
+ delete[] buffer;
+ buffer=NULL;
+ }
+
+ if(demRows.empty())
+ {
+ RMInit::logOut << "r_Conv_int16::readToSrcStream() src stream is empty !" << endl;
+ throw r_Error();
+ }
+}
+
+
+void
+r_Conv_int16::writeFromDestStream() throw(r_Error)
+{
+ int16RowVec::const_iterator iter, iterEnd;
+ r_Long xdim, ydim, offset;
+ r_Point currPt(destIntervDim);
+ r_Bytes typeSize=0;
+
+
+ //FIXME here we should modify for other type support
+ if(desc.destType->type_id() != r_Type::DOUBLE)
+ {
+ RMInit::logOut << "r_Conv_int16::writeFromDestStream() destType (" << desc.destType->type_id()
+ << ") is not " << r_Type::DOUBLE << " !" << endl;
+ throw r_Error();
+ }
+
+ xdim=desc.destInterv[0].get_extent();
+ ydim=desc.destInterv[1].get_extent();
+ iter=demRows.begin();
+ iterEnd=demRows.end();
+ typeSize=((r_Primitive_Type*)desc.destType)->size();
+
+ //FIXME correction for strange efect of r_Long cast with 1e-6
+ while(iter != iterEnd)
+ {
+ if(collBBox.flipx)
+ currPt[0]=(collBBox.endx - iter->x)/collBBox.resx + 1e-6;
+ else
+ currPt[0]=(iter->x - collBBox.startx)/collBBox.resx + 1e-6;
+ if(collBBox.flipy)
+ currPt[1]=(collBBox.endy - iter->y)/collBBox.resy + 1e-6;
+ else
+ currPt[1]=(iter->y - collBBox.starty)/collBBox.resy + 1e-6;
+ ((r_Primitive_Type*)desc.destType)->set_double(&desc.dest[desc.destInterv.cell_offset(currPt)*typeSize], iter->h);
+ ++iter;
+ }
+}
+
+void
+r_Conv_int16::writeToDestStream(ofstream& oFile) throw(r_Error)
+{
+ int16RowVec::const_iterator iter, iterEnd;
+ r_Double currH;
+
+ if(!oFile.is_open())
+ {
+ RMInit::logOut << "r_Conv_int16::writeToDestStream() oFile is not opened !" << endl;
+ throw r_Error();
+ }
+ oFile.setf(std::ios::fixed);
+
+ iter=demRows.begin();
+ iterEnd=demRows.end();
+ while(iter != iterEnd)
+ {
+ //update to support NULL value: 0. (real value) goes in FLT_MIN(db value)
+ //because 0.(db value) represent NULL(real value). When we do export we skip NULL values.
+ currH = iter->h;
+ if(currH != NULL_DB)
+ {
+ //FIXME we have to implement different here when we change server scale algorithm
+ if(currH == ZERO_DB)
+ currH = ZERO_int16;
+ oFile << iter->x << "\t" << iter->y << "\t" << currH << endl;
+ }
+ ++iter;
+ }
+}
+
+r_convDesc&
+r_Conv_int16::convertFrom(const char* options) throw (r_Error)
+{
+ bool hasSrcType=true;
+
+ RMInit::logOut << "r_Conv_int16::convertFrom(" << (options?options:"NULL") << ")" << endl;
+
+ if(!desc.srcType)
+ {
+ desc.srcType=get_external_type(desc.baseType);
+ hasSrcType=false;
+ }
+
+ try
+ {
+ RMInit::logOut << "r_Conv_int16::convertFrom(...) src interval=" << desc.srcInterv << endl;
+ RMInit::logOut << "r_Conv_int16::convertFrom(...) src type=" << desc.srcType->type_id() << endl;
+
+ //check options
+ if(!decodeOptions(options, collBBox))
+ throw r_Error();
+
+ //check desc.srcInterv.dimension
+ if(desc.srcInterv.dimension() != srcIntervDim)
+ {
+ RMInit::logOut << "r_Conv_int16::convertFrom(" << (options?options:"NULL")
+ << ") desc.srcInterv dimension (" << desc.srcInterv.dimension()
+ << " != " << srcIntervDim << " !" << endl;
+ throw r_Error();
+ }
+
+ //check srcType
+ if(!desc.srcType->isPrimitiveType())
+ {
+ RMInit::logOut << "r_Conv_int16::convertFrom(" << (options?options:"NULL")
+ << ") desc.srcType (" << desc.srcType->type_id()
+ << ") not supported, only primitive types !" << endl;
+ throw r_Error();
+ }
+
+ if(desc.srcType->isComplexType())
+ {
+ RMInit::logOut << "r_Conv_int16::convertFrom(" << (options?options:"NULL")
+ << ") desc.srcType (" << desc.srcType->type_id()
+ << ") not supported !" << endl;
+ throw r_Error();
+ }
+
+ //read src stream
+ readFromSrcStream();
+
+ //convert from int16 to marray
+ //--computing the marray domain
+ desc.destInterv = r_Minterval(destIntervDim);
+
+ //FIXME correction for strange efect of r_Long cast with 1e-6
+ if(collBBox.flipx)
+ desc.destInterv << r_Sinterval((r_Long)((collBBox.endx - max.x)/collBBox.resx + 1e-6),
+ (r_Long)((collBBox.endx - min.x)/collBBox.resx + 1e-6));
+ else
+ desc.destInterv << r_Sinterval((r_Long)((min.x - collBBox.startx)/collBBox.resx + 1e-6),
+ (r_Long)((max.x - collBBox.startx)/collBBox.resx + 1e-6));
+ if(collBBox.flipy)
+ desc.destInterv << r_Sinterval((r_Long)((collBBox.endy - max.y)/collBBox.resy + 1e-6),
+ (r_Long)((collBBox.endy - min.y)/collBBox.resy + 1e-6));
+ else
+ desc.destInterv << r_Sinterval((r_Long)((min.y - collBBox.starty)/collBBox.resy + 1e-6),
+ (r_Long)((max.y - collBBox.starty)/collBBox.resy + 1e-6));
+
+ RMInit::logOut << "r_Conv_int16::convertFrom(...) dest interval=" << desc.destInterv << endl;
+
+ //--creating the resulting type
+ desc.destType = new r_Primitive_Type("Double", r_Type::DOUBLE);
+ RMInit::logOut << "r_Conv_int16::convertFrom(...) dest type=" << desc.destType->type_id() << endl;
+
+ //--claim memory for result
+ desc.dest = (char*)mystore.storage_alloc(desc.destInterv.cell_count() * ((r_Primitive_Type*)desc.destType)->size());
+ if(desc.dest==NULL)
+ {
+ RMInit::logOut << "r_Conv_int16::convertFrom(" << (options?options:"NULL")
+ << ") unable to claim memory !" << endl;
+ throw r_Ememory_allocation();
+ }
+ memset(desc.dest, 0, desc.destInterv.cell_count() * ((r_Primitive_Type*)desc.destType)->size());
+
+ //--write parsed data in desc.dest
+ writeFromDestStream();
+ }
+ catch(r_Error& err)
+ {
+ //cleanup
+ if(!hasSrcType)
+ {
+ delete desc.srcType;
+ desc.srcType=NULL;
+ }
+
+ //desc.destType
+ if(desc.destType)
+ {
+ delete desc.destType;
+ desc.destType=NULL;
+ }
+
+ //desc.dest
+ if(desc.dest)
+ {
+ mystore.storage_free(desc.dest);
+ desc.dest=NULL;
+ }
+
+ //report error
+ throw;
+ }
+
+ //cleanup
+ if(!hasSrcType)
+ {
+ delete desc.srcType;
+ desc.srcType=NULL;
+ }
+
+ //return result
+ return desc;
+}
+
+
+r_convDesc&
+r_Conv_int16::convertTo(const char* options) throw (r_Error)
+{
+ bool hasSrcType=true;
+
+ RMInit::logOut << "r_Conv_int16::convertTo(" << (options?options:"NULL") << ")" << endl;
+
+ try
+ {
+ if(!desc.srcType)
+ {
+ desc.srcType=get_external_type(desc.baseType);
+ hasSrcType=false;
+ }
+
+ RMInit::logOut << "r_Conv_int16::convertTo(...) src interval=" << desc.srcInterv << endl;
+ RMInit::logOut << "r_Conv_int16::convertTo(...) src type=" << desc.srcType->type_id() << endl;
+
+ //check options
+ if(!decodeOptions(options, collBBox))
+ throw r_Error();
+
+ if(!desc.srcType->isPrimitiveType())
+ {
+ RMInit::logOut << "r_Conv_int16::convertTo(" << (options?options:"NULL")
+ << ") desc.srcType (" << desc.srcType->type_id()
+ << ") not supported, only primitive types !" << endl;
+ throw r_Error();
+ }
+ if(desc.srcType->isComplexType())
+ {
+ RMInit::logOut << "r_Conv_int16::convertTo(" << (options?options:"NULL")
+ << ") desc.srcType (" << desc.srcType->type_id()
+ << ") not supported !" << endl;
+ throw r_Error();
+ }
+
+ //read src data
+ readToSrcStream();
+
+ //convert from marray to int16;
+ char* pTempFileName=NULL;
+ string tempFileName;
+ ofstream oFile;
+ FILE* pFile=NULL;
+ size_t lenFile=0;
+
+ //--create the temp file
+ //FIXME for multithread application
+ pTempFileName=tmpnam(NULL);
+ if(pTempFileName==NULL)
+ {
+ RMInit::logOut << "r_Conv_int16::convertTo(" << (options?options:"NULL")
+ << ") desc.srcType (" << desc.srcType->type_id()
+ << ") unable to generate a tempory file !" << endl;
+ throw r_Error();
+ }
+
+ tempFileName=pTempFileName;
+ oFile.open(tempFileName.c_str());
+ if(!oFile.is_open())
+ {
+ RMInit::logOut << "r_Conv_int16::convertTo(" << (options?options:"NULL")
+ << ") desc.srcType (" << desc.srcType->type_id()
+ << ") unable to open the tempory file !" << endl;
+ throw r_Error();
+ }
+
+ RMInit::logOut << "r_Conv_int16::convertTo(...) temp file=" << tempFileName << endl;
+
+ //--get int16 format
+ writeToDestStream(oFile);
+ oFile.close();
+
+ //--accessing the temp file
+ if ((pFile = fopen(tempFileName.c_str(), "rb")) == NULL)
+ {
+ RMInit::logOut << "r_Conv_int16::convertTo(): unable to read back file." << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ fseek(pFile, 0, SEEK_END);
+ lenFile = ftell(pFile);
+ RMInit::logOut << "r_Conv_int16::convertTo(...) dest len=" << lenFile << endl;
+
+ if (!lenFile)
+ {
+ RMInit::logOut << "r_Conv_int16::convertTo(): source contains only NULL values." << endl;
+ throw r_Error();
+ }
+
+ //--creating the resulting type
+ desc.destType = new r_Primitive_Type("Char", r_Type::CHAR);
+
+ //--computing the marray domain
+ desc.destInterv = r_Minterval(srcIntervDim);
+ desc.destInterv << r_Sinterval((r_Long)0, (r_Long)lenFile - 1);
+
+ RMInit::logOut << "r_Conv_int16::convertTo(...) dest interval=" << desc.destInterv << endl;
+ RMInit::logOut << "r_Conv_int16::convertTo(...) dest type=" << desc.destType->type_id() << endl;
+
+ //--claim memory for desc.dest
+ desc.dest = (char*)mystore.storage_alloc(lenFile);
+ if(desc.dest==NULL)
+ {
+ RMInit::logOut << "r_Conv_int16::convertTo(" << (options?options:"NULL")
+ << ") unable to claim memory !" << endl;
+ throw r_Ememory_allocation();
+ }
+ memset(desc.dest, 0, lenFile);
+
+ //--story the data in desc.dest
+ fseek(pFile, 0, SEEK_SET);
+ fread(desc.dest, 1, lenFile, pFile);
+
+ //clean up
+ fclose(pFile);
+ pFile=NULL;
+ remove(pTempFileName);
+ }
+ catch(r_Error& err)
+ {
+ //cleanup
+ if(!hasSrcType)
+ {
+ delete desc.srcType;
+ desc.srcType=NULL;
+ }
+
+ //desc.destType
+ if(desc.destType)
+ {
+ delete desc.destType;
+ desc.destType=NULL;
+ }
+
+ //desc.dest
+ if(desc.dest)
+ {
+ mystore.storage_free(desc.dest);
+ desc.dest=NULL;
+ }
+
+ //rethrow error
+ throw;
+ }
+
+ //clean up
+ if(!hasSrcType)
+ {
+ delete desc.srcType;
+ desc.srcType=NULL;
+ }
+
+ //return result
+ return desc;
+}
+
+const char*
+r_Conv_int16::get_name() const throw()
+{
+ return get_name_from_data_format(r_int16);
+}
+
+r_Data_Format
+r_Conv_int16::get_data_format() const throw()
+{
+ return r_int16;
+}
+
+r_Convertor*
+r_Conv_int16::clone() const throw(r_Error)
+{
+ return new r_Conv_int16(desc.src, desc.srcInterv, desc.srcType);
+}
diff --git a/conversion/int16.hh b/conversion/int16.hh
new file mode 100644
index 0000000..c8d9f98
--- /dev/null
+++ b/conversion/int16.hh
@@ -0,0 +1,205 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: int16.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_int16
+ *
+ * COMMENTS:
+ * Provides interface to convert data to other formats.
+*/
+
+#ifndef _R_CONV_int16_HH_
+#define _R_CONV_int16_HH_
+
+#include <sstream>
+#include <vector>
+#include <string>
+#include <cstdio>
+using std::vector;
+using std::ofstream;
+using std::string;
+
+#include "conversion/convertor.hh"
+#include "raslib/odmgtypes.hh"
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ int16 convertor class.
+
+ Supported parameters are
+
+ \begin{tabular}{lcl}
+ {\tt flipx} && int && flip image flag on x axis, default 0\\
+ {\tt flipy} && int && flip image flag on y axis, default 1\\
+ {\tt startx} && double && start value on x axis \\
+ {\tt endx} && double && end value on x axis \\
+ {\tt sizex} && int && number of pixels in horizontal direction (int >0)
+ {\tt sizey} && int && number of pixels in vertical direction (int >0)
+ {\tt resx} && double && resolution on x axis \\
+ {\tt starty} && double && start value on y axis \\
+ {\tt endy} && double && end value on y axis \\
+ {\tt resy} && double && resolution on y axis \\
+ {\tt hstep} && double && resolution on h axis \\
+ \end{tabular}
+
+ The "flipx" parameter is a flag for mirroring the image on x axis.
+ The "flipy" parameter is a flag for mirroring the image on y axis.
+ [startx:endx, starty:endy] represents the geographical bounding box
+ of the whole image. The corresponding pixel bounding box is calculated
+ as follows:
+ if flipy is disabled:
+ [(minx-startx)/resx:(maxx-startx)/resx, (miny-starty)/resy:(maxy-starty)/resy]
+ else
+ [(minx-startx)/resx:(maxx-startx)/resx, (endy-maxy)/resy:(endy-miny)/resy]
+
+ if flipx is disabled:
+ [(minx-startx)/resx:(maxx-startx)/resx, (miny-starty)/resy:(maxy-starty)/resy]
+ else
+ [(endx-maxx)/resx:(endx-minx)/resx, (miny-starty)/resy:(maxy-starty)/resy]
+
+ The pairs (startx, endx, resx), (starty, endy, resy) apply to the whole MDD object in the database
+ whereas the pairs (minx,maxx, resx), (miny, maxy, resy) describe the part of image under consideration.
+ They are used to compute the update part's position in RasDaMan coordinates.
+ Value hstep is vertical resolution (multiplied into the value read during conversion into internal format).
+*/
+
+
+Format specification: int16
+
+input parameters:
+ geox geo reference x of upper left point (float >0)
+ geoy geo reference y of upper left point (float >0)
+ resx horizontal resolution (pixel distance) in meters (float >0)
+ resy vertical resolution (pixel distance) in meters (float >0)
+ hstep factor by which pixel values have to be multiplied to obtain real height in meters (float >0)
+
+
+An int16 file contains a sequence of sizex*sizey height values, advancing from west to east and from north to south. Each pixel consists of a 16 bit integer where the lower byte comes first in sequence (i.e., pixel value is byte[i]+byte[i+1]*256).
+There is no file header, pixels start immediately at the beginning.
+
+Points are defined as follows for pixel position (i,j) in file (starting with (0/0):
+ geo position x = geox + i*resx
+ geo position y = geoy + j*resy
+ height = ( byte[ 2*i + 2*j*sizex] + byte[ 2*i + 2*j*sizex + 1] * 256 ) * hstep
+
+where / denotes integer division
+
+class r_Conv_int16 : public r_Convertor
+{
+ public:
+ // constants to handle NULL
+ static const r_Double NULL_DB;
+ static const r_Double ZERO_DB;
+ static const r_Double ZERO_int16;
+
+ //inner class for convertor parameters
+ class r_GeoBBox
+ {
+ public:
+ r_Double startx, endx, resx;
+ r_Double starty, endy, resy;
+ r_ULong flipy, flipx;
+ };
+
+ r_Conv_int16(const char* source, const r_Minterval& lengthordomain, const r_Type* tp) throw(r_Error);
+
+ r_Conv_int16(const char* source, const r_Minterval& lengthordomain, int tp) throw(r_Error);
+
+ r_convDesc& convertFrom(const char* options = NULL) throw (r_Error);
+
+ r_convDesc& convertTo(const char* options = NULL) throw (r_Error);
+
+ const char* get_name() const throw();
+
+ r_Data_Format get_data_format() const throw();
+
+ r_Convertor* clone() const throw(r_Error);
+
+ /// dimension of src domain accepted as input in convertFrom
+ static const r_Dimension srcIntervDim;
+
+ /// dimension of dest domain accepted as input in convertTo
+ static const r_Dimension destIntervDim;
+
+ /// decode convertor options
+ static bool decodeOptions( const char* options,
+ r_GeoBBox& collBBox) throw();
+
+ /// encode convertor options
+ static string encodeOptions(const r_GeoBBox& collBBox) throw();
+
+ /// destructor
+ virtual ~r_Conv_int16( void );
+
+ /// init convertor parameters to default value
+ static void initGeoBBox( r_GeoBBox& cBBox );
+
+ private:
+
+
+ /// check limits before converting
+ void checkLimits() throw(r_Error);
+
+ ///i/o src/dest stream
+ void readFromSrcStream() throw(r_Error);
+ void readToSrcStream() throw(r_Error);
+ void writeFromDestStream() throw(r_Error);
+ void writeToDestStream(ofstream& oFile) throw(r_Error);
+
+ /// parameters
+ r_GeoBBox collBBox;
+
+ /// class constants
+ static const r_ULong paramMin;
+ static const char* paramSep;
+ static const char* paramEq;
+ static const char* paramFlipX;
+ static const char* paramFlipY;
+ static const char* paramStartX;
+ static const char* paramEndX;
+ static const char* paramResX;
+ static const char* paramStartY;
+ static const char* paramEndY;
+ static const char* paramResY;
+
+
+ /// internal data
+ class int16Row
+ {
+ public:
+ r_Double x,y,h;
+ };
+
+ typedef vector<int16Row> int16RowVec;
+
+ int16Row min, max;
+ int16RowVec demRows;
+
+ };
+
+#endif
+
diff --git a/conversion/jpeg.cc b/conversion/jpeg.cc
new file mode 100644
index 0000000..7638d82
--- /dev/null
+++ b/conversion/jpeg.cc
@@ -0,0 +1,530 @@
+/*
+* 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: jpeg.cc
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_JPEG
+ *
+ * COMMENTS:
+ *
+ * Provides functions to convert data to JPEG and back
+ *
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <string.h>
+#include <setjmp.h>
+
+extern "C" {
+#include "jpeglib.h"
+}
+
+#include "raslib/rminit.hh"
+#include "raslib/parseparams.hh"
+#include "conversion/jpeg.hh"
+#include "conversion/memfs.hh"
+
+
+
+#define JPEG_IO_BUFFER_SIZE 4096
+
+
+// JPEG-interface in C-namespace (like JPEG lib)
+extern "C" {
+
+
+typedef struct my_compress_struct {
+ jpeg_compress_struct pub;
+ thandle_t handle;
+ JOCTET *buffer;
+ int bufferSize;
+} my_compress_struct;
+
+typedef struct my_decompress_struct {
+ jpeg_decompress_struct pub;
+ thandle_t handle;
+ JOCTET *buffer;
+ int bufferSize;
+} my_decompress_struct;
+
+typedef struct my_error_mgr {
+ jpeg_error_mgr pub;
+ jmp_buf setjmp_buffer;
+} my_error_mgr;
+
+
+// See jpeg library example
+static void my_error_exit(jpeg_common_struct *cptr)
+{
+ my_error_mgr *myerr = (my_error_mgr*)(cptr->err);
+ (*cptr->err->output_message)(cptr);
+ longjmp(myerr->setjmp_buffer, 1);
+}
+
+
+
+/*
+ * Memory IO wrapper functions, rely on memFS.
+ */
+
+// Destination manager methods
+// cptr is actually a pointer to my_compress_struct
+static void dm_init_destination(jpeg_compress_struct *cptr)
+{
+ my_compress_struct *mptr = (my_compress_struct*)cptr;
+
+ if ((mptr->buffer = new JOCTET[JPEG_IO_BUFFER_SIZE]) == NULL)
+ {
+ RMInit::logOut << "r_Conv_JPEG@dm_init_destination(): out of memory" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+ mptr->bufferSize = JPEG_IO_BUFFER_SIZE;
+ cptr->dest->next_output_byte = mptr->buffer; cptr->dest->free_in_buffer = mptr->bufferSize;
+}
+
+
+static boolean dm_empty_output_buffer(jpeg_compress_struct *cptr)
+{
+ my_compress_struct *mptr = (my_compress_struct*)cptr;
+ boolean retval=FALSE;
+
+ if (memfs_write(mptr->handle, mptr->buffer, mptr->bufferSize) == mptr->bufferSize)
+ {
+ cptr->dest->next_output_byte = mptr->buffer; cptr->dest->free_in_buffer = mptr->bufferSize;
+ retval=TRUE;
+ }
+ return retval;
+}
+
+
+static void dm_term_destination(jpeg_compress_struct *cptr)
+{
+ my_compress_struct *mptr = (my_compress_struct*)cptr;
+
+ if (cptr->dest->next_output_byte != mptr->buffer)
+ {
+ memfs_write(mptr->handle, mptr->buffer, (cptr->dest->next_output_byte - mptr->buffer));
+ }
+ delete [] mptr->buffer; mptr->buffer = NULL;
+}
+
+
+// Source manager methods
+// dptr is actually a pointer to my_decompress_struct
+static void sm_init_source(jpeg_decompress_struct *dptr)
+{
+ my_decompress_struct *mptr = (my_decompress_struct*)dptr;
+
+ if ((mptr->buffer = new JOCTET[JPEG_IO_BUFFER_SIZE]) == NULL)
+ {
+ RMInit::logOut << "r_Conv_JPEG@sm_init_source(): out of memory" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+ mptr->bufferSize = JPEG_IO_BUFFER_SIZE;
+ dptr->src->next_input_byte = mptr->buffer; dptr->src->bytes_in_buffer = 0;
+}
+
+
+// See jdatasrc.c
+static boolean sm_fill_input_buffer(jpeg_decompress_struct *dptr)
+{
+ my_decompress_struct *mptr = (my_decompress_struct*)dptr;
+ int read_bytes=0;
+
+ if ((read_bytes = memfs_chunk_read(mptr->handle, mptr->buffer, mptr->bufferSize)) != 0)
+ {
+ dptr->src->bytes_in_buffer = read_bytes;
+ }
+ else
+ {
+ mptr->buffer[0] = (JOCTET)0xff;
+ mptr->buffer[1] = (JOCTET)JPEG_EOI;
+ dptr->src->bytes_in_buffer = 2;
+ }
+ dptr->src->next_input_byte = mptr->buffer;
+
+ return TRUE;
+}
+
+
+// See jdatasrc.c
+static void sm_skip_input_data(jpeg_decompress_struct *dptr, long num_bytes)
+{
+ my_decompress_struct *mptr = (my_decompress_struct*)dptr;
+
+ if (num_bytes < dptr->src->bytes_in_buffer)
+ {
+ dptr->src->next_input_byte += num_bytes; dptr->src->bytes_in_buffer -= num_bytes;
+ }
+ else
+ {
+ int read_bytes=0;
+
+ num_bytes -= dptr->src->bytes_in_buffer;
+ dptr->src->next_input_byte = mptr->buffer;
+ while (num_bytes >= mptr->bufferSize)
+ {
+ memfs_chunk_seek(mptr->handle, mptr->bufferSize, SEEK_CUR);
+ num_bytes -= mptr->bufferSize;
+ }
+ read_bytes = memfs_chunk_read(mptr->handle, mptr->buffer, mptr->bufferSize);
+ if (read_bytes <= num_bytes)
+ {
+ mptr->buffer[0] = (JOCTET)0xff;
+ mptr->buffer[1] = (JOCTET)JPEG_EOI;
+ dptr->src->bytes_in_buffer = 2;
+ }
+ else
+ {
+ dptr->src->next_input_byte = mptr->buffer + num_bytes;
+ dptr->src->bytes_in_buffer = read_bytes - num_bytes;
+ }
+ }
+}
+
+
+/*static boolean sm_resync_to_restart(jpeg_decompress_struct *dptr, int desired)
+{
+ return FALSE;
+}*/
+
+
+static void sm_term_source(jpeg_decompress_struct *dptr)
+{
+ my_decompress_struct *mptr = (my_decompress_struct*)dptr;
+
+ delete [] mptr->buffer; mptr->buffer = NULL;
+}
+
+
+} // end of C namespace
+
+
+
+
+/*
+ * r_Conv_JPEG class for converting MDD to JPEG and back
+ */
+
+void r_Conv_JPEG::initJPEG( void )
+{
+ quality = 80;
+
+ if (params == NULL)
+ params = new r_Parse_Params;
+
+ params->add("quality", &quality, r_Parse_Params::param_type_int);
+}
+
+
+r_Conv_JPEG::r_Conv_JPEG(const char *src, const r_Minterval &interv, int tp) throw(r_Error)
+: r_Convert_Memory(src, interv, tp)
+{
+ initJPEG();
+}
+
+
+r_Conv_JPEG::r_Conv_JPEG(const char *src, const r_Minterval &interv, const r_Type *tp) throw(r_Error)
+: r_Convert_Memory(src, interv, tp)
+{
+ initJPEG();
+}
+
+
+r_Conv_JPEG::~r_Conv_JPEG(void)
+{
+}
+
+
+r_convDesc &r_Conv_JPEG::convertTo( const char *options) throw(r_Error)
+{
+ struct jpeg_destination_mgr destMgr;
+ struct jpeg_compress_struct *cptr=NULL;
+ struct jpeg_error_mgr *jptr=NULL;
+ my_error_mgr jerr;
+ my_compress_struct cinfo;
+ int width=0, height=0, lineAdd=0, pixelAdd=0;
+ int i=0, j=0, spp=0;
+ J_COLOR_SPACE jcs;
+ JSAMPROW row_pointers[1];
+ JSAMPLE *row=NULL, *rowPtr=NULL;
+ r_Long jpegSize=0;
+
+ row = NULL;
+ memset(&cinfo, 0, sizeof(my_compress_struct));
+ cinfo.handle = (thandle_t)handle;
+ cptr = (struct jpeg_compress_struct*)&cinfo.pub;
+ jptr = (struct jpeg_error_mgr*)&jerr.pub;
+
+ cptr->err = jpeg_std_error(jptr);
+ jptr->error_exit = my_error_exit;
+
+ params->process(options);
+
+ if (setjmp(jerr.setjmp_buffer))
+ {
+ if (row != NULL) {delete [] row; row = NULL;}
+ jpeg_abort_compress(cptr);
+ jpeg_destroy_compress(cptr);
+ // destination manager destructor might not be called on an abort
+ if (cinfo.buffer != NULL){delete [] cinfo.buffer; cinfo.buffer=NULL;}
+ RMInit::logOut << "r_Conv_JPEG::convertTo(" << options << "): unable to save the stack" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ jpeg_create_compress(cptr);
+ jpeg_set_quality(cptr, quality, 0);
+
+ memfs_newfile(handle);
+
+ destMgr.init_destination = dm_init_destination;
+ destMgr.empty_output_buffer = dm_empty_output_buffer;
+ destMgr.term_destination = dm_term_destination;
+
+ cptr->dest = &destMgr;
+
+ width = (int)(desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1);
+ height = (int)(desc.srcInterv[1].high() - desc.srcInterv[1].low() + 1);
+
+ cptr->image_width = (JDIMENSION)width; cptr->image_height = (JDIMENSION)height;
+
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ case ctype_char:
+ jcs = JCS_GRAYSCALE; spp = 1; lineAdd = 1; pixelAdd = height; break;
+ case ctype_rgb:
+ jcs = JCS_RGB; spp = 3; lineAdd = 3; pixelAdd = 3*height; break;
+ default:
+ RMInit::logOut << "r_Conv_JPEG::convertTo(" << options << "): unsupported base type" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ cptr->input_components = spp; cptr->in_color_space = jcs;
+
+ jpeg_set_defaults(cptr);
+
+ jpeg_set_quality(cptr, quality, TRUE);
+
+ jpeg_start_compress(cptr, TRUE);
+
+ if ((row = new JSAMPLE[width * spp]) == NULL)
+ {
+ RMInit::logOut << "r_Conv_JPEG::convertTo(" << options << "): out of memory" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+
+ row_pointers[0] = row;
+
+ const unsigned char *src=NULL, *srcPtr=NULL;
+
+ src = (const unsigned char*)desc.src;
+
+ for (j=0; j<height; j++, src += lineAdd)
+ {
+ srcPtr = src; rowPtr = row;
+
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ for (i=0; i<width; i++, srcPtr += pixelAdd)
+ {
+ *rowPtr++ = (*srcPtr == 0) ? 0 : 0xff;
+ }
+ break;
+ case ctype_char:
+ for (i=0; i<width; i++, srcPtr += pixelAdd)
+ {
+ *rowPtr++ = *srcPtr;
+ }
+ break;
+ case ctype_rgb:
+ for (i=0; i<width; i++, srcPtr += pixelAdd)
+ {
+ *rowPtr++ = srcPtr[0]; *rowPtr++ = srcPtr[1]; *rowPtr++ = srcPtr[2];
+ }
+ break;
+ }
+ jpeg_write_scanlines(cptr, row_pointers, 1);
+ }
+
+ delete [] row; row = NULL;
+
+ jpeg_finish_compress(cptr);
+
+ jpeg_destroy_compress(cptr);
+
+ jpegSize = memfs_size(handle);
+
+ if ((desc.dest = (char*)mystore.storage_alloc(jpegSize)) == NULL)
+ {
+ RMInit::logOut << "r_Conv_JPEG::convertTo(" << options << "): out of memory" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+ memfs_seek(handle, 0, SEEK_SET);
+ memfs_read(handle, desc.dest, jpegSize);
+
+ desc.destInterv = r_Minterval(1);
+ desc.destInterv << r_Sinterval((r_Range)0, (r_Range)jpegSize - 1);
+
+ desc.destType = r_Type::get_any_type("char");
+
+ return desc;
+}
+
+
+r_convDesc &r_Conv_JPEG::convertFrom(const char *options) throw(r_Error)
+{
+ struct jpeg_source_mgr srcMgr;
+ struct jpeg_decompress_struct *dptr=NULL;
+ struct jpeg_error_mgr *jptr=NULL;
+ my_error_mgr jerr;
+ my_decompress_struct cinfo;
+ int width=0, height=0, lineAdd=0, pixelAdd=0;
+ int i=0, j=0, spp=0;
+ J_COLOR_SPACE jcs;
+ JSAMPROW row_pointers[1];
+ JSAMPLE *row=NULL, *rowPtr=NULL;
+ char *dest=NULL, *destPtr=NULL;
+
+ row = NULL; desc.dest = NULL;
+ memset(&cinfo, 0, sizeof(my_decompress_struct));
+ cinfo.handle = (thandle_t)handle;
+ dptr = (struct jpeg_decompress_struct*)&cinfo.pub;
+ jptr = (struct jpeg_error_mgr*)&jerr.pub;
+
+ dptr->err = jpeg_std_error(jptr);
+ jptr->error_exit = my_error_exit;
+
+ if (setjmp(jerr.setjmp_buffer))
+ {
+ if (row != NULL) {delete [] row; row = NULL;}
+ if (desc.dest != NULL) {mystore.storage_free(desc.dest); desc.dest = NULL;}
+ jpeg_abort_decompress(dptr);
+ jpeg_destroy_decompress(dptr);
+ // Source manager destructor might not be called on an abort
+ if (cinfo.buffer != NULL) {delete [] cinfo.buffer; cinfo.buffer=NULL;}
+ RMInit::logOut << "r_Conv_JPEG::convertFrom(" << options << "): unable to save the stack" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ jpeg_create_decompress(dptr);
+
+ memfs_chunk_initfs(handle, (char*)desc.src, (r_Long)(desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1));
+
+ srcMgr.init_source = sm_init_source;
+ srcMgr.fill_input_buffer = sm_fill_input_buffer;
+ srcMgr.skip_input_data = sm_skip_input_data;
+ srcMgr.resync_to_restart = NULL; //sm_resync_to_restart;
+ srcMgr.term_source = sm_term_source;
+
+ dptr->src = &srcMgr;
+
+ jpeg_read_header(dptr, TRUE);
+ width = (int)(dptr->image_width); height = (int)(dptr->image_height);
+
+ if (dptr->num_components == 1)
+ {
+ desc.baseType = ctype_char;
+ lineAdd = 1; pixelAdd = height;
+ }
+ else
+ {
+ desc.baseType = ctype_rgb;
+ lineAdd = 3; pixelAdd = 3*height;
+ dptr->out_color_space = JCS_RGB;
+ }
+
+ jpeg_start_decompress(dptr);
+
+ spp = (int)(dptr->output_components);
+
+ row = new JSAMPLE[width * spp];
+ desc.dest = (char*)mystore.storage_alloc(width * height * spp);
+
+ if ((row == NULL) || (desc.dest == NULL))
+ {
+ if (row != NULL) {delete [] row; row = NULL;}
+ RMInit::logOut << "r_Conv_JPEG::convertFrom(): out of memory" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+
+ row_pointers[0] = row; dest = desc.dest;
+ for (j=0; j<height; j++, dest += lineAdd)
+ {
+ jpeg_read_scanlines(dptr, row_pointers, 1);
+ destPtr = dest; rowPtr = row;
+ switch (spp)
+ {
+ case 1:
+ for (i=0; i<width; i++, destPtr += pixelAdd)
+ {
+ *destPtr = *rowPtr++;
+ }
+ break;
+ case 3:
+ for (i=0; i<width; i++, destPtr += pixelAdd)
+ {
+ destPtr[0] = *rowPtr++; destPtr[1] = *rowPtr++; destPtr[2] = *rowPtr++;
+ }
+ break;
+ }
+ }
+
+ delete [] row; row = NULL;
+
+ jpeg_finish_decompress(dptr);
+
+ jpeg_destroy_decompress(dptr);
+
+ desc.destInterv = r_Minterval(2);
+ desc.destInterv << r_Sinterval((r_Range)0, (r_Range)width-1)
+ << r_Sinterval((r_Range)0, (r_Range)height-1);
+
+ desc.destType = get_external_type(desc.baseType);
+
+ return desc;
+}
+
+
+
+const char *r_Conv_JPEG::get_name( void ) const
+{
+ return format_name_jpeg;
+}
+
+
+r_Data_Format r_Conv_JPEG::get_data_format( void ) const
+{
+ return r_JPEG;
+}
+
+
+r_Convertor *r_Conv_JPEG::clone( void ) const
+{
+ return new r_Conv_JPEG(desc.src, desc.srcInterv, desc.baseType);
+}
diff --git a/conversion/jpeg.hh b/conversion/jpeg.hh
new file mode 100644
index 0000000..2c2bb6b
--- /dev/null
+++ b/conversion/jpeg.hh
@@ -0,0 +1,84 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: jpeg.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_JPEG
+ *
+ * COMMENTS:
+ *
+ * Provides interface to convert data to JPEG and back.
+ *
+*/
+
+#ifndef _R_CONV_JPEG_HH_
+#define _R_CONV_JPEG_HH_
+
+#include "conversion/convertor.hh"
+
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ JPEG convertor class.
+
+ Supported parameters are
+
+ \begin{tabular}{lcl}
+ quality && int && quality ratio between 0 and 100
+ \end{tabular}
+
+ */
+
+class r_Conv_JPEG : public r_Convert_Memory
+{
+ public:
+ /// constructor using an r_Type object
+ r_Conv_JPEG( const char *src, const r_Minterval &interv, const r_Type *tp ) throw(r_Error);
+ /// constructor using convert_type_e shortcut
+ r_Conv_JPEG( const char *src, const r_Minterval &interv, int tp ) throw(r_Error);
+ /// destructor
+ ~r_Conv_JPEG( void );
+
+ /// convert to JPEG
+ virtual r_convDesc &convertTo( const char *options=NULL ) throw(r_Error);
+ /// convert from JPEG
+ virtual r_convDesc &convertFrom( const char *options=NULL ) throw(r_Error);
+ /// cloning
+ virtual r_Convertor *clone( void ) const;
+ /// identification
+ virtual const char *get_name( void ) const;
+ virtual r_Data_Format get_data_format( void ) const;
+
+
+ private:
+ /// init JPEG class
+ void initJPEG( void );
+
+ /// parameters
+ int quality;
+};
+
+#endif
diff --git a/conversion/memfs.c b/conversion/memfs.c
new file mode 100644
index 0000000..c346880
--- /dev/null
+++ b/conversion/memfs.c
@@ -0,0 +1,421 @@
+/*
+* 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: memfs.c
+ *
+ * MODULE: conversion
+ *
+ * PURPOSE:
+ * Memory Filing System used by some of the convertor modules
+ *
+ * COMMENTS
+ * None
+*/
+
+#include "mymalloc/mymalloc.h"
+
+#include <stdio.h>
+#include <malloc.h>
+#include <string.h>
+#include "conversion/memfs.hh"
+
+
+/* can't use RMDBGOUT because this is C, not C++ */
+const int MEMFSDBGLEVEL = 4;
+
+extern int RManDebug;
+
+
+
+/* This function for internal use only */
+int memfs_ensure(thandle_t handle, toff_t off)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+ char **mam2=NULL;
+ int mamSize2=0, i=0;
+
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_ensure: %d\n", off); fflush(stdout);
+ }
+#endif
+ /* Do we have to allocate a bigger mam? */
+ mamSize2 = (off >> MEMFS_LD_BLOCKSIZE);
+ if (mamSize2 >= memFS->mamSize)
+ {
+ /* Always allocate mam in powers of 2. That ensures that if we run out
+ of space the new mam will be twice as big as the old one. */
+ i = 0; while (mamSize2 != 0) {mamSize2 >>= 1; i++;}
+ mamSize2 = (1 << i);
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_ensure: growing mam from %d to %d\n", memFS->mamSize, mamSize2);
+ fflush(stdout);
+ }
+#endif
+ if ((mam2 = (char **)mymalloc(mamSize2 * sizeof(char*))) == NULL)
+ return -1;
+ /* Copy existing mam entries */
+ memcpy ((void*)mam2, (void*) memFS->mam, memFS->mamSize * sizeof(char*));
+ /* Init new mam entries */
+ for (i=memFS->mamSize; i < mamSize2; i++)
+ {
+ mam2[i] = NULL;
+ }
+ /* free old mam */
+ free(memFS->mam);
+ memFS->mam = mam2; memFS->mamSize = mamSize2;
+ }
+ /* Calculate again because its value might have been changed by the
+ above block */
+ mamSize2 = (off >> MEMFS_LD_BLOCKSIZE);
+ if ((memFS->mam)[mamSize2] == NULL)
+ {
+ /* We don't just have to allocate this one new block but all the
+ ones with lower addresses that aren't defined yet as well */
+ for (i=memFS->mamHighest+1; i <= mamSize2; i++)
+ {
+ if (((memFS->mam)[i] = (char*)mymalloc((1 << MEMFS_LD_BLOCKSIZE) * sizeof(char))) == NULL)
+ return -1;
+ }
+ memFS->mamHighest = mamSize2;
+ }
+ /* All done, the memFS can now hold an object of size off */
+ return 0;
+}
+
+
+/* Initialise the memory filing system */
+int memfs_initfs(thandle_t handle)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+ int i=0;
+
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_initfs\n"); fflush(stdout);
+ }
+#endif
+ memFS->pos = 0; memFS->high = 0;
+ memFS->mamSize = MEMFS_MAM_ENTRIES;
+ if ((memFS->mam = (char **)mymalloc(MEMFS_MAM_ENTRIES * sizeof(char *))) == NULL)
+ return -1;
+ if (((memFS->mam)[0] = (char*)mymalloc((1 << MEMFS_LD_BLOCKSIZE) * sizeof(char))) == NULL)
+ return -1;
+ memFS->mamHighest = 0;
+ for (i=1; i<MEMFS_MAM_ENTRIES; i++)
+ {
+ (memFS->mam)[i] = NULL;
+ }
+ return 0;
+}
+
+
+/* Kill the memory filing system, freeing all its resources */
+void memfs_killfs(thandle_t handle)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+ int i=0;
+
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_killfs\n"); fflush(stdout);
+ }
+#endif
+ for (i=0; i < memFS->mamSize; i++)
+ {
+ if ((memFS->mam)[i] == NULL) break;
+ free((memFS->mam)[i]);
+ }
+ free(memFS->mam);
+}
+
+
+/* Reset file pointers, leave memory setup */
+void memfs_newfile(thandle_t handle)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_newfile\n"); fflush(stdout);
+ }
+#endif
+ memFS->pos = 0; memFS->high = 0;
+}
+
+
+tsize_t memfs_read(thandle_t handle, tdata_t mem, tsize_t size)
+{
+ tsize_t todo=0, transfered = 0;
+ int block=0, offset=0, x=0;
+ memFSContext *memFS = (memFSContext *)handle;
+
+ /* Don't read over the end of the "file" */
+ todo = memFS->high - memFS->pos;
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_read: (%d, left: %d)\n", todo, memFS->high); fflush(stdout);
+ }
+#endif
+ if (todo > size) todo = size;
+ while (todo > 0)
+ {
+ block = (memFS->pos >> MEMFS_LD_BLOCKSIZE);
+ offset = memFS->pos - (block << MEMFS_LD_BLOCKSIZE);
+ /* Space left in this buffer */
+ x = (1 << MEMFS_LD_BLOCKSIZE) - offset;
+ if (x > todo) x = todo;
+ memcpy((void*)mem, (void*)(((memFS->mam)[block]) + offset), x);
+ /* tdata_t is some kind of void *, so we have to do this cast */
+ mem = (tdata_t)(((char*)mem) + x);
+ memFS->pos += x; transfered += x; todo -= x;
+ }
+ return transfered;
+}
+
+
+tsize_t memfs_write(thandle_t handle, tdata_t mem, tsize_t size)
+{
+ tsize_t transfered = 0;
+ memFSContext *memFS = (memFSContext *)handle;
+ int block=0, offset=0, x=0;
+
+ /* Make sure there's enough room for this write */
+ if (memfs_ensure(handle, memFS->pos + size) < 0) return 0;
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_write (%d)\n",size); fflush(stdout);
+ }
+#endif
+ while (size > 0)
+ {
+ /* See memfs_read */
+ block = (memFS->pos >> MEMFS_LD_BLOCKSIZE);
+ offset = memFS->pos - (block << MEMFS_LD_BLOCKSIZE);
+ x = (1 << MEMFS_LD_BLOCKSIZE) - offset;
+ if (x > size) x = size;
+ memcpy((void*)(((memFS->mam)[block]) + offset), (void*)mem, x);
+ mem = (tdata_t)(((char *)mem) + x);
+ memFS->pos += x; transfered += x; size -= x;
+ }
+ if (memFS->pos > memFS->high) {memFS->high = memFS->pos;}
+ return transfered;
+}
+
+
+toff_t memfs_seek(thandle_t handle, toff_t offset, int mode)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+
+ switch (mode)
+ {
+ case SEEK_SET: memFS->pos = offset; break;
+ case SEEK_CUR: memFS->pos += offset; break;
+ case SEEK_END: memFS->pos = memFS->high + offset; break;
+ default: break;
+ }
+ if (memFS->pos < 0) memFS->pos = 0;
+ /* Don't limit to end of file (this actually caused problems!) */
+ memfs_ensure(handle, memFS->pos);
+ if (memFS->pos > memFS->high) memFS->high = memFS->pos;
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_seek: Set pos to %d\n", memFS->pos); fflush(stdout);
+ }
+#endif
+ return memFS->pos;
+}
+
+
+int memfs_close(thandle_t handle)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_close:\n"); fflush(stdout);
+ }
+#endif
+ return 1; /* = success? */
+}
+
+
+toff_t memfs_size(thandle_t handle)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_size:\n"); fflush(stdout);
+ }
+#endif
+ return (((memFSContext *)handle)->high);
+}
+
+
+int memfs_map(thandle_t handle, tdata_t *memp, toff_t *top)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_map: %p, %d\n", *memp, *top); fflush(stdout);
+ }
+#endif
+ return 0;
+}
+
+
+void memfs_unmap(thandle_t handle, tdata_t mem, toff_t to)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_unmap: %p, %d\n", mem, to); fflush(stdout);
+ }
+#endif
+}
+
+
+
+
+
+
+/* Read-only from memory (simple chunky model, not block-oriented) */
+void memfs_chunk_initfs(thandle_t handle, char *src, r_Long size)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_initfs: %p, %d\n", src, size); fflush(stdout);
+ }
+#endif
+ memFS->pos = 0;
+ memFS->chunk = src;
+ memFS->high = size;
+}
+
+
+tsize_t memfs_chunk_read(thandle_t handle, tdata_t mem, tsize_t size)
+{
+ tsize_t todo=0;
+ memFSContext *memFS = (memFSContext *)handle;
+
+ todo = memFS->high - memFS->pos;
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_read: %d (left %d)\n", size, todo); fflush(stdout);
+ }
+#endif
+ if (todo > size) todo = size;
+ if (todo > 0)
+ {
+ memcpy((void*)mem, (void*)(memFS->chunk + memFS->pos), todo);
+ memFS->pos += todo;
+ }
+ return todo;
+}
+
+
+toff_t memfs_chunk_seek(thandle_t handle, toff_t offset, int mode)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+
+ switch (mode)
+ {
+ case SEEK_SET: memFS->pos = offset; break;
+ case SEEK_CUR: memFS->pos += offset; break;
+ case SEEK_END: memFS->pos = memFS->high + offset; break;
+ default: break;
+ }
+ if (memFS->pos < 0) memFS = 0;
+ /* Since file can't be extended this is OK here */
+ if (memFS->pos > memFS->high) memFS->pos = memFS->high;
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_seek: Position to %d\n", memFS->pos); fflush(stdout);
+ }
+#endif
+ return memFS->pos;
+}
+
+
+int memfs_chunk_close(thandle_t handle)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_close:\n"); fflush(stdout);
+ }
+#endif
+ return 1;
+}
+
+
+toff_t memfs_chunk_size(thandle_t handle)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_size:\n"); fflush(stdout);
+ }
+#endif
+ return (((memFSContext *)handle)->high);
+}
+
+
+/* Map file to memory -- since we already have it in memory in the
+ first place this is very simple. */
+int memfs_chunk_map(thandle_t handle, tdata_t *memp, toff_t *top)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_map:\n"); fflush(stdout);
+ }
+#endif
+ *memp = (tdata_t)(memFS->chunk); *top = (toff_t)(memFS->high);
+ return 1; /* Success? */
+}
+
+void memfs_chunk_unmap(thandle_t handle, tdata_t mem, toff_t to)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_unmap: %p, %d\n", mem, to); fflush(stdout);
+ }
+#endif
+}
diff --git a/conversion/memfs.cc b/conversion/memfs.cc
new file mode 100644
index 0000000..8dca196
--- /dev/null
+++ b/conversion/memfs.cc
@@ -0,0 +1,421 @@
+/*
+* 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: memfs.c
+ *
+ * MODULE: conversion
+ *
+ * PURPOSE:
+ * Memory Filing System used by some of the convertor modules
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include "mymalloc/mymalloc.h"
+
+#include <stdio.h>
+#include <malloc.h>
+#include <string.h>
+#include "conversion/memfs.hh"
+
+
+/* can't use RMDBGOUT because this is C, not C++ */
+const int MEMFSDBGLEVEL = 4;
+
+extern int RManDebug;
+
+
+
+/* This function for internal use only */
+int memfs_ensure(thandle_t handle, toff_t off)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+ char **mam2=NULL;
+ int mamSize2=0, i=0;
+
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_ensure: %d\n", off); fflush(stdout);
+ }
+#endif
+ /* Do we have to allocate a bigger mam? */
+ mamSize2 = (off >> MEMFS_LD_BLOCKSIZE);
+ if (mamSize2 >= memFS->mamSize)
+ {
+ /* Always allocate mam in powers of 2. That ensures that if we run out
+ of space the new mam will be twice as big as the old one. */
+ i = 0; while (mamSize2 != 0) {mamSize2 >>= 1; i++;}
+ mamSize2 = (1 << i);
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_ensure: growing mam from %d to %d\n", memFS->mamSize, mamSize2);
+ fflush(stdout);
+ }
+#endif
+ if ((mam2 = (char **)mymalloc(mamSize2 * sizeof(char*))) == NULL)
+ return -1;
+ /* Copy existing mam entries */
+ memcpy ((void*)mam2, (void*) memFS->mam, memFS->mamSize * sizeof(char*));
+ /* Init new mam entries */
+ for (i=memFS->mamSize; i < mamSize2; i++)
+ {
+ mam2[i] = NULL;
+ }
+ /* free old mam */
+ free(memFS->mam);
+ memFS->mam = mam2; memFS->mamSize = mamSize2;
+ }
+ /* Calculate again because its value might have been changed by the
+ above block */
+ mamSize2 = (off >> MEMFS_LD_BLOCKSIZE);
+ if ((memFS->mam)[mamSize2] == NULL)
+ {
+ /* We don't just have to allocate this one new block but all the
+ ones with lower addresses that aren't defined yet as well */
+ for (i=memFS->mamHighest+1; i <= mamSize2; i++)
+ {
+ if (((memFS->mam)[i] = (char*)mymalloc((1 << MEMFS_LD_BLOCKSIZE) * sizeof(char))) == NULL)
+ return -1;
+ }
+ memFS->mamHighest = mamSize2;
+ }
+ /* All done, the memFS can now hold an object of size off */
+ return 0;
+}
+
+
+/* Initialise the memory filing system */
+int memfs_initfs(thandle_t handle)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+ int i=0;
+
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_initfs\n"); fflush(stdout);
+ }
+#endif
+ memFS->pos = 0; memFS->high = 0;
+ memFS->mamSize = MEMFS_MAM_ENTRIES;
+ if ((memFS->mam = (char **)mymalloc(MEMFS_MAM_ENTRIES * sizeof(char *))) == NULL)
+ return -1;
+ if (((memFS->mam)[0] = (char*)mymalloc((1 << MEMFS_LD_BLOCKSIZE) * sizeof(char))) == NULL)
+ return -1;
+ memFS->mamHighest = 0;
+ for (i=1; i<MEMFS_MAM_ENTRIES; i++)
+ {
+ (memFS->mam)[i] = NULL;
+ }
+ return 0;
+}
+
+
+/* Kill the memory filing system, freeing all its resources */
+void memfs_killfs(thandle_t handle)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+ int i=0;
+
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_killfs\n"); fflush(stdout);
+ }
+#endif
+ for (i=0; i < memFS->mamSize; i++)
+ {
+ if ((memFS->mam)[i] == NULL) break;
+ free((memFS->mam)[i]);
+ }
+ free(memFS->mam);
+}
+
+
+/* Reset file pointers, leave memory setup */
+void memfs_newfile(thandle_t handle)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_newfile\n"); fflush(stdout);
+ }
+#endif
+ memFS->pos = 0; memFS->high = 0;
+}
+
+
+tsize_t memfs_read(thandle_t handle, tdata_t mem, tsize_t size)
+{
+ tsize_t todo=0, transfered = 0;
+ int block=0, offset=0, x=0;
+ memFSContext *memFS = (memFSContext *)handle;
+
+ /* Don't read over the end of the "file" */
+ todo = memFS->high - memFS->pos;
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_read: (%d, left: %d)\n", todo, memFS->high); fflush(stdout);
+ }
+#endif
+ if (todo > size) todo = size;
+ while (todo > 0)
+ {
+ block = (memFS->pos >> MEMFS_LD_BLOCKSIZE);
+ offset = memFS->pos - (block << MEMFS_LD_BLOCKSIZE);
+ /* Space left in this buffer */
+ x = (1 << MEMFS_LD_BLOCKSIZE) - offset;
+ if (x > todo) x = todo;
+ memcpy((void*)mem, (void*)(((memFS->mam)[block]) + offset), x);
+ /* tdata_t is some kind of void *, so we have to do this cast */
+ mem = (tdata_t)(((char*)mem) + x);
+ memFS->pos += x; transfered += x; todo -= x;
+ }
+ return transfered;
+}
+
+
+tsize_t memfs_write(thandle_t handle, tdata_t mem, tsize_t size)
+{
+ tsize_t transfered = 0;
+ memFSContext *memFS = (memFSContext *)handle;
+ int block=0, offset=0, x=0;
+
+ /* Make sure there's enough room for this write */
+ if (memfs_ensure(handle, memFS->pos + size) < 0) return 0;
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_write (%d)\n",size); fflush(stdout);
+ }
+#endif
+ while (size > 0)
+ {
+ /* See memfs_read */
+ block = (memFS->pos >> MEMFS_LD_BLOCKSIZE);
+ offset = memFS->pos - (block << MEMFS_LD_BLOCKSIZE);
+ x = (1 << MEMFS_LD_BLOCKSIZE) - offset;
+ if (x > size) x = size;
+ memcpy((void*)(((memFS->mam)[block]) + offset), (void*)mem, x);
+ mem = (tdata_t)(((char *)mem) + x);
+ memFS->pos += x; transfered += x; size -= x;
+ }
+ if (memFS->pos > memFS->high) {memFS->high = memFS->pos;}
+ return transfered;
+}
+
+
+toff_t memfs_seek(thandle_t handle, toff_t offset, int mode)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+
+ switch (mode)
+ {
+ case SEEK_SET: memFS->pos = offset; break;
+ case SEEK_CUR: memFS->pos += offset; break;
+ case SEEK_END: memFS->pos = memFS->high + offset; break;
+ default: break;
+ }
+ if (memFS->pos < 0) memFS->pos = 0;
+ /* Don't limit to end of file (this actually caused problems!) */
+ memfs_ensure(handle, memFS->pos);
+ if (memFS->pos > memFS->high) memFS->high = memFS->pos;
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_seek: Set pos to %d\n", memFS->pos); fflush(stdout);
+ }
+#endif
+ return memFS->pos;
+}
+
+
+int memfs_close(thandle_t handle)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_close:\n"); fflush(stdout);
+ }
+#endif
+ return 1; /* = success? */
+}
+
+
+toff_t memfs_size(thandle_t handle)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_size:\n"); fflush(stdout);
+ }
+#endif
+ return (((memFSContext *)handle)->high);
+}
+
+
+int memfs_map(thandle_t handle, tdata_t *memp, toff_t *top)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_map: %p, %d\n", *memp, *top); fflush(stdout);
+ }
+#endif
+ return 0;
+}
+
+
+void memfs_unmap(thandle_t handle, tdata_t mem, toff_t to)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_unmap: %p, %d\n", mem, to); fflush(stdout);
+ }
+#endif
+}
+
+
+
+
+
+
+/* Read-only from memory (simple chunky model, not block-oriented) */
+void memfs_chunk_initfs(thandle_t handle, char *src, r_Long size)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_initfs: %p, %d\n", src, size); fflush(stdout);
+ }
+#endif
+ memFS->pos = 0;
+ memFS->chunk = src;
+ memFS->high = size;
+}
+
+
+tsize_t memfs_chunk_read(thandle_t handle, tdata_t mem, tsize_t size)
+{
+ tsize_t todo=0;
+ memFSContext *memFS = (memFSContext *)handle;
+
+ todo = memFS->high - memFS->pos;
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_read: %d (left %d)\n", size, todo); fflush(stdout);
+ }
+#endif
+ if (todo > size) todo = size;
+ if (todo > 0)
+ {
+ memcpy((void*)mem, (void*)(memFS->chunk + memFS->pos), todo);
+ memFS->pos += todo;
+ }
+ return todo;
+}
+
+
+toff_t memfs_chunk_seek(thandle_t handle, toff_t offset, int mode)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+
+ switch (mode)
+ {
+ case SEEK_SET: memFS->pos = offset; break;
+ case SEEK_CUR: memFS->pos += offset; break;
+ case SEEK_END: memFS->pos = memFS->high + offset; break;
+ default: break;
+ }
+ if (memFS->pos < 0) memFS = 0;
+ /* Since file can't be extended this is OK here */
+ if (memFS->pos > memFS->high) memFS->pos = memFS->high;
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_seek: Position to %d\n", memFS->pos); fflush(stdout);
+ }
+#endif
+ return memFS->pos;
+}
+
+
+int memfs_chunk_close(thandle_t handle)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_close:\n"); fflush(stdout);
+ }
+#endif
+ return 1;
+}
+
+
+toff_t memfs_chunk_size(thandle_t handle)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_size:\n"); fflush(stdout);
+ }
+#endif
+ return (((memFSContext *)handle)->high);
+}
+
+
+/* Map file to memory -- since we already have it in memory in the
+ first place this is very simple. */
+int memfs_chunk_map(thandle_t handle, tdata_t *memp, toff_t *top)
+{
+ memFSContext *memFS = (memFSContext *)handle;
+
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_map:\n"); fflush(stdout);
+ }
+#endif
+ *memp = (tdata_t)(memFS->chunk); *top = (toff_t)(memFS->high);
+ return 1; /* Success? */
+}
+
+void memfs_chunk_unmap(thandle_t handle, tdata_t mem, toff_t to)
+{
+#ifdef RMANDEBUG
+ if (RManDebug >= MEMFSDBGLEVEL)
+ {
+ printf("memfs_chunk_unmap: %p, %d\n", mem, to); fflush(stdout);
+ }
+#endif
+}
diff --git a/conversion/memfs.h b/conversion/memfs.h
new file mode 100644
index 0000000..42958ad
--- /dev/null
+++ b/conversion/memfs.h
@@ -0,0 +1,85 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: memfs.hh
+ *
+ * MODULE: conversion
+ *
+ * PURPOSE:
+ * Memory Filing System used by some of the convertor modules.
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _MEMFS_HH_
+#define _MEMFS_HH_
+
+/* For data types used by the memfs */
+#include "tiffio.h"
+#include "raslib/odmgtypes.hh"
+
+
+/* Claim blocks in 4k chunks */
+const int MEMFS_LD_BLOCKSIZE = 12;
+/* Initially preserve enough room for 16 blocks */
+const int MEMFS_MAM_ENTRIES = 16;
+
+typedef struct memFSContext {
+ r_Long pos, high;
+ int mamSize, mamHighest;
+ char **mam;
+ char *chunk;
+} memFSContext;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Flexible, read-write memFS */
+int memfs_initfs(thandle_t handle);
+void memfs_killfs(thandle_t handle);
+void memfs_newfile(thandle_t handle);
+tsize_t memfs_read(thandle_t handle, tdata_t mem, tsize_t size);
+tsize_t memfs_write(thandle_t handle, tdata_t mem, tsize_t size);
+toff_t memfs_seek(thandle_t handle, toff_t offset, int mode);
+int memfs_close(thandle_t handle);
+toff_t memfs_size(thandle_t handle);
+int memfs_map(thandle_t handle, tdata_t *memp, toff_t *top);
+void memfs_unmap(thandle_t handle, tdata_t mem, toff_t top);
+
+/* Simple, read-only memFS */
+void memfs_chunk_initfs(thandle_t handle, char *src, r_Long size);
+tsize_t memfs_chunk_read(thandle_t handle, tdata_t mem, tsize_t size);
+toff_t memfs_chunk_seek(thandle_t handle, toff_t offset, int mode);
+int memfs_chunk_close(thandle_t handle);
+toff_t memfs_chunk_size(thandle_t handle);
+int memfs_chunk_map(thandle_t handle, tdata_t *memp, toff_t *top);
+void memfs_chunk_unmap(thandle_t handle, tdata_t mem, toff_t to);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/conversion/memfs.hh b/conversion/memfs.hh
new file mode 100644
index 0000000..1b88b37
--- /dev/null
+++ b/conversion/memfs.hh
@@ -0,0 +1,85 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: memfs.hh
+ *
+ * MODULE: conversion
+ *
+ * PURPOSE:
+ * Memory Filing System used by some of the convertor modules.
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _MEMFS_HH_
+#define _MEMFS_HH_
+
+/* For data types used by the memfs */
+#include "tiffio.h"
+#include "raslib/odmgtypes.hh"
+
+
+/* Claim blocks in 4k chunks */
+const int MEMFS_LD_BLOCKSIZE = 12;
+/* Initially preserve enough room for 16 blocks */
+const int MEMFS_MAM_ENTRIES = 16;
+
+typedef struct memFSContext {
+ r_Long pos, high;
+ int mamSize, mamHighest;
+ char **mam;
+ char *chunk;
+} memFSContext;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Flexible, read-write memFS */
+int memfs_initfs(thandle_t handle);
+void memfs_killfs(thandle_t handle);
+void memfs_newfile(thandle_t handle);
+tsize_t memfs_read(thandle_t handle, tdata_t mem, tsize_t size);
+tsize_t memfs_write(thandle_t handle, tdata_t mem, tsize_t size);
+toff_t memfs_seek(thandle_t handle, toff_t offset, int mode);
+int memfs_close(thandle_t handle);
+toff_t memfs_size(thandle_t handle);
+int memfs_map(thandle_t handle, tdata_t *memp, toff_t *top);
+void memfs_unmap(thandle_t handle, tdata_t mem, toff_t top);
+
+/* Simple, read-only memFS */
+void memfs_chunk_initfs(thandle_t handle, char *src, r_Long size);
+tsize_t memfs_chunk_read(thandle_t handle, tdata_t mem, tsize_t size);
+toff_t memfs_chunk_seek(thandle_t handle, toff_t offset, int mode);
+int memfs_chunk_close(thandle_t handle);
+toff_t memfs_chunk_size(thandle_t handle);
+int memfs_chunk_map(thandle_t handle, tdata_t *memp, toff_t *top);
+void memfs_chunk_unmap(thandle_t handle, tdata_t mem, toff_t to);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/conversion/nitf.cc b/conversion/nitf.cc
new file mode 100644
index 0000000..dbdfee0
--- /dev/null
+++ b/conversion/nitf.cc
@@ -0,0 +1,702 @@
+/*
+* 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>.
+*/
+
+#include <string>
+#include <stdio.h>
+#include <cstdlib>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <iostream>
+#include <fstream>
+#include <strstream>
+#include <exception>
+
+
+#include "nitf.h"
+#include "image.h"
+#include "graphic.h"
+#include "text.h"
+#include "des.h"
+#include "res.h"
+#include "utilities.h"
+
+using namespace std;
+using namespace RasNITF;
+
+nitf::nitf(){
+
+ isEmpty = true;
+
+ m_li = NULL;
+ m_ls = NULL;
+ m_lt = NULL;
+ m_ld = NULL;
+ m_lr = NULL;
+ m_udhd = NULL;
+ m_xhd = NULL;
+
+ m_images = NULL;
+ m_graphics = NULL;
+ m_texts = NULL;
+ m_des = NULL;
+ m_res = NULL;
+
+ n_numi=0;
+}
+/*
+nitf::nitf(char* data){
+
+}
+*/
+nitf::~nitf(){
+
+ if (m_li != NULL) {
+ delete m_li;
+ m_li = NULL;
+ }
+
+ if (m_ls != NULL) {
+ delete m_ls;
+ m_ls = NULL;
+ }
+
+ if (m_lt != NULL) {
+ delete m_lt;
+ m_lt = NULL;
+ }
+
+ if (m_ld != NULL) {
+ delete m_ld;
+ m_ld = NULL;
+ }
+
+ if (m_lr != NULL) {
+ delete m_lr;
+ m_lr = NULL;
+ }
+
+ if (m_udhd != NULL) {
+ delete m_udhd;
+ m_udhd = NULL;
+ }
+
+ if (m_xhd != NULL) {
+ delete m_xhd;
+ m_xhd = NULL;
+ }
+
+ if (m_images != NULL) {
+ delete[] m_images;
+ m_images = NULL;
+ }
+
+ if (m_graphics != NULL) {
+ delete[] m_graphics;
+ m_graphics = NULL;
+ }
+
+ if (m_texts != NULL) {
+ delete[] m_texts;
+ m_texts = NULL;
+ }
+
+ if (m_des != NULL) {
+ delete[] m_des;
+ m_des = NULL;
+ }
+
+ if (m_res != NULL) {
+ delete[] m_res;
+ m_res = NULL;
+ }
+
+}
+
+bool nitf::checkempty(){
+ return isEmpty;
+}
+
+void nitf::empty(){
+
+ if (!this->isEmpty){
+
+ if (m_li != NULL) {
+ delete m_li;
+ m_li = NULL;
+ }
+
+ if (m_ls != NULL) {
+ delete m_ls;
+ m_ls = NULL;
+ }
+
+ if (m_lt != NULL) {
+ delete m_lt;
+ m_lt = NULL;
+ }
+
+ if (m_ld != NULL) {
+ delete m_ld;
+ m_ld = NULL;
+ }
+
+ if (m_lr != NULL) {
+ delete m_lr;
+ m_lr = NULL;
+ }
+
+ if (m_udhd != NULL) {
+ delete m_udhd;
+ m_udhd = NULL;
+ }
+
+ if (m_xhd != NULL) {
+ delete m_xhd;
+ m_xhd = NULL;
+ }
+
+ if (m_images != NULL) {
+ delete[] m_images;
+ m_images = NULL;
+ }
+
+ if (m_graphics != NULL) {
+ delete[] m_graphics;
+ m_graphics = NULL;
+ }
+
+ if (m_texts != NULL) {
+ delete[] m_texts;
+ m_texts = NULL;
+ }
+
+ if (m_des != NULL) {
+ delete[] m_des;
+ m_des = NULL;
+ }
+
+ if (m_res != NULL) {
+ delete[] m_res;
+ m_res = NULL;
+ }
+ }
+
+ this->isEmpty = true;
+}
+
+void nitf::stats() const {
+ int adress=n_hl;
+ cout<<"Printing statistics for the NITF file in memmory\n";
+ cout<<"================================================\n";
+ cout<<"Filename:\t\t"<<endl;
+ cout<<"File title:\n";
+ cout.write(m_ftitle,80);
+ cout<<"\nFile Length\t\t"<<n_fl;
+ cout<<"\nFile Header Length\t"<<n_hl;
+ cout<<"\nNumber of Images:\t"<<n_numi;
+ cout<<"\n====================IMAGES======================\n";
+ for(int i=0; i<n_numi; i++) {
+ cout<<"Length of Image Header "<<i<<"\t"<<n_lish[i]<<" Starting at "<<adress<<endl;
+ adress+=n_lish[i];
+ cout<<"Length of Image "<<i<<"\t"<<n_li[i]<<" Starting at "<<adress<<endl;
+ adress+=n_li[i];
+ }
+ cout<<"\nNumber of Graphics:\t"<<n_nums;
+ cout<<"\n===================GRAPHICS======================\n";
+ for(int i=0; i<n_nums; i++) {
+ cout<<"Length of Graphic Header "<<i<<"\t"<<n_lssh[i]<<" Starting at "<<adress<<endl;
+ adress+=n_lssh[i];
+ cout<<"Length of Graphic "<<i<<"\t"<<n_ls[i]<<" Starting at "<<adress<<endl;
+ adress+=n_ls[i];
+
+ }
+ cout<<"\nNumber of Texts:\t"<<n_numt;
+ cout<<"\n====================TEXTS========================\n";
+ for(int i=0; i<n_numt; i++) {
+
+ cout<<"Length of Text Header "<<i<<"\t"<<n_ltsh[i]<<" Starting at "<<adress<<endl;
+ adress+=n_ltsh[i];
+ cout<<"Length of Text "<<i<<"\t"<<n_lt[i]<<" Starting at "<<adress<<endl;
+ adress+=n_lt[i];
+ }
+ cout<<"\nNumber of Deses:\t"<<n_numdes;
+ cout<<"\n====================DESES======================\n";
+ for(int i=0; i<n_numdes; i++) {
+ cout<<"Length of Des Header "<<i<<"\t"<<n_ldsh[i]<<" Starting at "<<adress<<endl;
+ adress+=n_ldsh[i];
+ cout<<"Length of Des "<<i<<"\t"<<n_ld[i]<<" Starting at "<<adress<<endl;
+ adress+=n_ld[i];
+
+ }
+ cout<<"\nNumber of Reses:\t"<<n_numres;
+ cout<<"\n====================RESES======================\n";
+ for(int i=0; i<n_numres; i++) {
+
+ cout<<"Length of Res Header "<<i<<"\t"<<n_lrsh[i]<<" Starting at "<<adress<<endl;
+ adress+=n_lrsh[i];
+ cout<<"Length of Res "<<i<<"\t"<<n_lr[i]<<" Starting at "<<adress<<endl;
+ adress+=n_lr[i];
+ }
+ cout<<"\n\nThank you for using statistics, have a nice day\n";
+ cout<<"---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---\n";
+}
+
+
+int nitf::read_file(string filename){
+
+ ifstream hNITF;
+ hNITF.open(filename.c_str(), ios::in);
+ if (!hNITF.good()) exit(-1);
+ bool read_image_data = true;
+
+ return read(hNITF, read_image_data);
+
+}
+
+int nitf::read_headers_from(char* file_data, long file_length){
+
+ istrstream hNITF(file_data, file_length);
+ if (!hNITF.good()) exit(-1);
+ bool read_image_data = false;
+
+ return read(hNITF, read_image_data);;
+
+}
+
+
+int nitf::read(istream &hNITF, bool read_image_data){
+
+ char temp_buffer[100];
+ int charsread = 0;
+
+ // CHECK IF EMPTY EXCEPTION
+ if (!hNITF.good()) exit(-1);
+
+ // read file name and version and check for consistency
+
+ charsread += read_verify2(hNITF, m_fhdr, 9);
+
+ if (strncmp(m_fhdr, "NITF02.10", 9) != 0)
+ exit(2);
+
+ // copy all security fields as character data
+ charsread += read_verify2(hNITF, m_clevel, (2 + 4 + 10 + 14 + 80 + 1 + 2 + 11 + 2 + 20 + 2 + 8 + 4 + 1 + 8 + 43 +
+ 1 + 40 + 1 + 8 + 15 + 5 + 5 + 1 + 3 + 24 + 18));
+
+ // read file length
+ charsread += read_verify2(hNITF, m_fl, 12);
+ n_fl = charptrtolong(m_fl, 12);
+
+ // read header length
+ charsread += read_verify2(hNITF, m_hl, 6);
+ n_hl = charptrtolong(m_hl, 6);
+
+ // read number of images
+ charsread += read_verify2(hNITF, m_numi, 3);
+ n_numi = charptrtoint(m_numi, 3);
+ m_li = new char[n_numi*(6+10)];
+
+ for (int i = 0; i < n_numi; i++ ){
+
+ charsread += read_verify2(hNITF, temp_buffer, 6);
+ n_lish.push_back(charptrtolong(temp_buffer, 6));
+ strncpy((char*)(m_li + i*16), temp_buffer, 6);
+
+ charsread += read_verify2(hNITF, temp_buffer, 10);
+ n_li.push_back(charptrtolong(temp_buffer, 10));
+ strncpy((char*)(m_li + i*16 + 6), temp_buffer, 10);
+ }
+
+ // read number of graphics
+
+ charsread += read_verify2(hNITF, m_nums, 3);
+ n_nums = charptrtoint(m_nums, 3);
+ m_ls = new char[n_nums*(4 + 6)];
+
+ for (int i = 0; i < n_nums; i++ ){
+
+ charsread += read_verify2(hNITF, temp_buffer, 4);
+ n_lssh.push_back(charptrtolong(temp_buffer, 4));
+ strncpy((char*)(m_ls + i*10), temp_buffer, 4);
+
+ charsread += read_verify2(hNITF, temp_buffer, 6);
+ n_ls.push_back(charptrtolong(temp_buffer, 6));
+ strncpy((char*)(m_ls + i*10 + 4), temp_buffer, 6);
+ }
+
+ // read NUMX field
+
+ charsread += read_verify2(hNITF, m_numx, 3);
+
+ // read number of texts
+
+ charsread += read_verify2(hNITF, m_numt, 3);
+ n_numt = charptrtoint(m_numt, 3);
+ m_lt = new char[n_numt*(4+5)];
+
+ for (int i = 0; i < n_numt; i++ ){
+
+ charsread += read_verify2(hNITF, temp_buffer, 4);
+ n_ltsh.push_back(charptrtolong(temp_buffer, 4));
+ strncpy((char*)(m_lt+i*9), temp_buffer, 4);
+
+ charsread += read_verify2(hNITF, temp_buffer, 5);
+ n_lt.push_back(charptrtolong(temp_buffer, 5));
+ strncpy((char*)(m_lt + i*9 + 4), temp_buffer, 5);
+ }
+
+ // read DES sizes data
+
+ charsread += read_verify2(hNITF, m_numdes, 3);
+ n_numdes = charptrtoint(m_numdes, 3);
+ m_ld = new char[n_numdes * (4 + 9)];
+
+ for (int i = 0; i < n_numdes; i++ ){
+
+ charsread += read_verify2(hNITF, temp_buffer, 4);
+ n_ldsh.push_back(charptrtolong(temp_buffer, 4));
+ strncpy((char*)(m_ld+i*13), temp_buffer, 4);
+
+ charsread += read_verify2(hNITF, temp_buffer, 9);
+ n_ld.push_back(charptrtolong(temp_buffer, 9));
+ strncpy((char*)(m_ld + i*13 + 4), temp_buffer, 9);
+ }
+
+ // read RES sizes data
+
+ charsread += read_verify2(hNITF, m_numres, 3);
+ n_numres = charptrtoint(m_numres, 3);
+ m_lr = new char[n_numres * (4 + 7)];
+
+ for (int i = 0; i < n_numres; i++){
+
+ charsread += read_verify2(hNITF, temp_buffer, 4);
+ n_lrsh.push_back(charptrtolong(temp_buffer, 4));
+ strncpy((char*)(m_lr + i*11), temp_buffer, 4);
+
+ charsread += read_verify2(hNITF, temp_buffer, 7);
+ n_lr.push_back(charptrtolong(temp_buffer, 7));
+ strncpy((char*)(m_lr + i*11 + 4), temp_buffer, 7);
+ }
+
+ // read UDHDL
+
+ charsread += read_verify2(hNITF, m_udhdl, 5);
+ n_udhdl = charptrtoint(m_udhdl, 5);
+
+ // read UDHOFL and UDHD if necessary
+
+ if (n_udhdl > 0) {
+
+ charsread += read_verify2(hNITF, m_udhofl, 3);
+ m_udhd = new char[n_udhdl-3];
+ charsread += read_verify2(hNITF, m_udhd, n_udhdl-3);
+ }
+
+ // read XHDL
+
+ charsread += read_verify2(hNITF, m_xhdl, 5);
+ n_xhdl = charptrtoint(m_xhdl, 5);
+
+ // read XHOFL and XHD if necessary
+
+ if (n_xhdl > 0) {
+ charsread += read_verify2(hNITF, m_xhdlofl, 3);
+ m_xhd = new char[n_xhdl-3];
+ charsread += read_verify2(hNITF, m_xhd, n_xhdl-3);
+ }
+
+ if (((long)(hNITF.tellg()))!= n_hl){
+ cout<< "header length read not as specified" << endl;
+ cout<<endl<<"read: tellg: "<< hNITF.tellg() << " nhl " << n_hl<<endl;
+ cout<< "chars read: " << charsread << endl;
+ exit(3);
+ }
+
+ // read images
+
+ if (n_numi > 0) {
+ m_images = new image[n_numi];
+ for(int i=0; i<n_numi; i++) {
+ m_images[i].read_file(hNITF, n_lish[i], n_li[i], read_image_data);
+ }
+ } else {
+ m_images = NULL;
+ }
+
+ // read graphics
+
+ if (n_nums > 0) {
+ m_graphics = new graphic[n_nums];
+ for(int i=0; i<n_nums; i++) {
+ m_graphics[i].read_file(hNITF, n_lssh[i], n_ls[i]);
+ }
+ } else {
+ m_graphics = NULL;
+ }
+
+ // read texts
+
+ if (n_numt > 0) {
+ m_texts = new text[n_numt];
+ for(int i=0; i<n_numt; i++) {
+ m_texts[i].read_file(hNITF, n_ltsh[i], n_lt[i]);
+ }
+ } else {
+ m_texts = NULL;
+ }
+
+
+ if (n_numdes > 0) {
+ m_des = new des[n_numdes];
+ for(int i=0; i<n_numdes; i++) {
+ m_des[i].read_file(hNITF, n_ldsh[i], n_ld[i]);
+ }
+ } else {
+ m_des = NULL;
+ }
+
+ if (n_numres > 0) {
+ m_res = new res[n_numres];
+ for(int i=0; i<n_numres; i++) {
+ m_res[i].read_file(hNITF, n_lrsh[i], n_lr[i]);
+ }
+ } else {
+ m_res = NULL;
+ }
+
+
+ this->isEmpty = false;
+
+ return charsread;
+
+}
+
+
+
+
+int nitf::write_file(std::string filename){
+
+ int charswritten = 0;
+ ofstream fNITF(filename.c_str());
+
+ fNITF.write(m_fhdr, 9);
+ fNITF.write(m_clevel, 2);
+ fNITF.write(m_stype, 4);
+ fNITF.write(m_ostaid, 10);
+ fNITF.write(m_fdt, 14);
+ fNITF.write(m_ftitle, 80);
+ fNITF.write(m_fsclas, 1);
+ fNITF.write(m_fsclsy, 2);
+ fNITF.write(m_fscode, 11);
+ fNITF.write(m_fsctlh, 2);
+ fNITF.write(m_fsrel, 20);
+ fNITF.write(m_fsdctp, 2);
+ fNITF.write(m_fsdcdt, 8);
+ fNITF.write(m_fsdcxm, 4);
+ fNITF.write(m_fsdg, 1);
+ fNITF.write(m_fsdgdt, 8);
+ fNITF.write(m_fscltx, 43);
+ fNITF.write(m_fscatp, 1);
+ fNITF.write(m_fscaut, 40);
+ fNITF.write(m_fscrsn, 1);
+ fNITF.write(m_fssrdt, 8);
+ fNITF.write(m_fsctln, 15);
+ fNITF.write(m_fscop, 5);
+ fNITF.write(m_fscpys, 5);
+ fNITF.write(m_encryp, 1);
+ fNITF.write(m_fbkgc, 3);
+ fNITF.write(m_oname, 24);
+ fNITF.write(m_ophone, 18);
+ fNITF.write(m_fl, 12);
+ fNITF.write(m_hl, 6);
+
+ charswritten += 9 + 2 + 4 + 10 + 14 + 80 + 1+ 2 + 11 + 2 + 20 + 2 + 8 + 4 + 1 + 8 + 43 + 1 + 40 + 1 +8 + 15 + 5 + 5 + 1 + 3 + 24 + 18 + 12 + 6;
+
+ fNITF.write(m_numi, 3);
+ charswritten += 3;
+ if(n_numi > 0){
+ fNITF.write(m_li, n_numi * (6 + 10));
+ charswritten += n_numi * (6 + 10);
+ }
+
+ fNITF.write(m_nums, 3);
+ charswritten += 3;
+ if(n_nums > 0){
+ fNITF.write(m_ls, n_nums * (4 + 6));
+ charswritten += n_nums * (4 + 6);
+ }
+
+ fNITF.write(m_numx, 3);
+
+ fNITF.write(m_numt, 3);
+ charswritten += 6;
+ if(n_numt > 0) {
+ fNITF.write(m_lt, n_numt * (4 + 5));
+ charswritten += n_numt * (4 + 5);
+ }
+
+ fNITF.write(m_numdes, 3);
+ charswritten += 3;
+ if(n_numdes > 0) {
+ fNITF.write(m_ld, n_numdes * (4 + 9));
+ charswritten += n_numdes * (4 + 9);
+ }
+
+ fNITF.write(m_numres, 3);
+ charswritten += 3;
+ if(n_numres > 0) {
+ fNITF.write(m_lr, n_numdes * (4 + 7));
+ charswritten += n_numdes* (4 + 7);
+ }
+
+ fNITF.write(m_udhdl, 5);
+ if (n_udhdl > 0){
+ fNITF.write(m_udhofl, 3);
+ fNITF.write(m_udhd, n_udhdl - 3);
+ charswritten += n_udhdl;
+ }
+
+
+ fNITF.write(m_xhdl, 5);
+ if (n_xhdl > 0){
+ fNITF.write(m_xhdlofl, 3);
+ fNITF.write(m_xhd, n_xhdl - 3);
+ charswritten += n_xhdl;
+ }
+
+ for(int i=0; i< n_numi; i++){
+ m_images[i].write_file(fNITF);
+ }
+
+ for(int i=0; i< n_nums; i++){
+ m_graphics[i].write_file(fNITF);
+ }
+
+ for(int i=0; i< n_numt; i++){
+ m_texts[i].write_file(fNITF);
+ }
+
+ for(int i=0; i< n_numdes; i++){
+ m_des[i].write_file(fNITF);
+ }
+
+ for(int i=0; i< n_numres; i++){
+ m_res[i].write_file(fNITF);
+ }
+
+ return charswritten;
+}
+
+void nitf::image_to_pixel_sequential(int index) {
+
+ if( !isEmpty ) {
+ if( (index < 0) || (index > n_numi)) {
+ throw(74);
+ exit(3);
+ } else {
+ m_images[index].to_pixel_sequential();
+ }
+ }
+}
+
+long nitf::get_image_size(int image_index) const
+{
+ return m_images[image_index].get_size();
+}
+
+int nitf::get_image_width(int image_index) const
+{
+ return m_images[image_index].get_width();
+}
+
+int nitf::get_image_height(int image_index) const
+{
+ return m_images[image_index].get_height();
+}
+
+long nitf::get_image_offset(int image_index) const
+{
+ long offset = 0;
+
+ offset += n_hl;
+
+ for(int ctr = 0; ctr < image_index; ctr++ ) {
+ offset+= n_li[ctr] + n_lish[ctr];
+ }
+
+ offset += n_lish[image_index];
+
+ return offset;
+}
+
+bool nitf::isRGB(int image_index){
+
+ bool RGB = false;
+
+ if (m_images[image_index].get_irep() == " RGB") {
+ if (m_images[image_index].get_nbpp_bytes() == 1 ){
+ RGB = true;
+ } else {
+ // throw(74);
+ exit(1704);
+ }
+ }
+
+ return RGB;
+
+}
+
+bool nitf::isGRAY(int image_index){
+
+ bool GRAY = false;
+
+ if ((m_images[image_index].get_irep() == " MONO") && (m_images[image_index].get_pvtype() == "INT")) {
+ if (m_images[image_index].get_nbpp_bytes() == 1 ){
+ GRAY = true;
+ } else {
+ // throw(74);
+ exit(1704);
+ }
+ }
+
+ return GRAY;
+}
+
+bool nitf::isBOOL(int image_index){
+
+ bool isBOOL = false;
+
+ if ((m_images[image_index].get_irep() == " MONO") && (m_images[image_index].get_pvtype() == " B")) {
+ if (m_images[image_index].get_nbpp_bytes() == 1 ){
+ isBOOL = true;
+ } else {
+ // throw(74);
+ exit(1704);
+ }
+ }
+
+ return isBOOL;
+}
diff --git a/conversion/nitf.h b/conversion/nitf.h
new file mode 100644
index 0000000..892eb14
--- /dev/null
+++ b/conversion/nitf.h
@@ -0,0 +1,165 @@
+/*
+* 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>.
+*/
+
+/**
+ * This is the definition of the NITF class, an agregation of the Classes Header,
+ * Image, Graphic and Text
+ */
+
+#ifndef __RASNITF_NITF_H
+#define __RASNITF_NITF_H
+
+#include<string>
+#include<vector>
+#include<iostream>
+#include<fstream>
+
+
+namespace RasNITF{
+
+class image;
+class graphic;
+class text;
+class des;
+class res;
+
+class nitf {
+
+ char m_fhdr[9];
+ char m_clevel[2];
+ char m_stype[4];
+ char m_ostaid[10];
+ char m_fdt[14];
+ char m_ftitle[80];
+ char m_fsclas[1];
+ char m_fsclsy[2];
+ char m_fscode[11];
+ char m_fsctlh[2];
+ char m_fsrel[20];
+ char m_fsdctp[2];
+ char m_fsdcdt[8];
+ char m_fsdcxm[4];
+ char m_fsdg[1];
+ char m_fsdgdt[8];
+ char m_fscltx[43];
+ char m_fscatp[1];
+ char m_fscaut[40];
+ char m_fscrsn[1];
+ char m_fssrdt[8];
+ char m_fsctln[15];
+ char m_fscop[5];
+ char m_fscpys[5];
+ char m_encryp[1];
+ char m_fbkgc[3];
+ char m_oname[24];
+ char m_ophone[18];
+
+ char m_fl[12];
+ char m_hl[6];
+ char m_numi[3];
+ char* m_li; // image sizes data
+ char m_nums[3];
+ char* m_ls; // graphic sizes data
+ char m_numx[3];
+ char m_numt[3];
+ char* m_lt; // text sizes data
+ char m_numdes[3];
+ char* m_ld; // des sizes data
+ char m_numres[3];
+ char* m_lr; // res sizes data
+ char m_udhdl[5];
+ char m_udhofl[3];
+ char* m_udhd;
+ char m_xhdl[5];
+ char m_xhdlofl[3];
+ char* m_xhd;
+
+ // DATA
+
+ //std::ifstream hNITF;
+
+ long n_fl;
+ long n_hl;
+
+ int n_numi;
+ std::vector<long> n_lish;
+ std::vector<long> n_li;
+ image *m_images;
+
+ int n_nums;
+ std::vector<long> n_lssh;
+ std::vector<long> n_ls;
+ graphic *m_graphics;
+
+ int n_numt;
+ std::vector<long> n_ltsh;
+ std::vector<long> n_lt;
+ text *m_texts;
+
+ int n_numdes;
+ std::vector<long> n_ldsh;
+ std::vector<long> n_ld;
+ des *m_des;
+
+ int n_numres;
+ std::vector<long> n_lrsh;
+ std::vector<long> n_lr;
+ res *m_res;
+
+ int n_udhdl;
+ int n_xhdl;
+
+ bool isEmpty;
+
+public:
+
+ nitf();
+ ~nitf();
+
+ int read_file(std::string filename);
+ int read_headers_from(char* file_data, long file_length);
+ int read(std::istream &hNITF, bool read_image_data);
+
+ int write_file(std::string filename);
+
+ void image_to_pixel_sequential(int index);
+
+ void stats() const;
+ void empty();
+ bool checkempty();
+
+ long get_image_size(int index = 0) const;
+ int get_image_width(int index = 0) const;
+ int get_image_height(int index = 0) const;
+ int get_image_pixel_type(int index = 0) const;
+ long get_image_offset(int index = 0) const;
+
+ bool isRGB(int image_index);
+ bool isGRAY(int image_index);
+ bool isBOOL(int image_index);
+
+};
+
+}
+
+#endif
diff --git a/conversion/ntf.cc b/conversion/ntf.cc
new file mode 100644
index 0000000..7db1bc7
--- /dev/null
+++ b/conversion/ntf.cc
@@ -0,0 +1,218 @@
+/*
+* 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: ntf.cc
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_NTF
+ *
+ * COMMENTS:
+ *
+ * Provides functions to convert data to NTF and back.
+ *
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <string.h>
+#include <new>
+
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/parseparams.hh"
+#include "conversion/ntf.hh"
+#include "conversion/memfs.hh"
+
+// nitf reader library
+
+#include "nitf.h"
+#include "image.h"
+
+r_Conv_NTF::r_Conv_NTF( const char *src, const r_Minterval &interv, const r_Type *tp )
+ throw(r_Error):r_Convert_Memory(src, interv, tp)
+{
+}
+
+r_Conv_NTF::r_Conv_NTF( const char *src, const r_Minterval &interv, int tp )
+ throw(r_Error):r_Convert_Memory(src, interv, tp)
+{
+}
+
+r_Conv_NTF::~r_Conv_NTF( void ){
+}
+
+/***********************************************************
+ * NAME: r_Conv_NTF::convertFrom
+ * ---------------------------------------------------------
+ * PURPOSE: convert from NITF image file data to the
+ * corresponding rasdaman type pixel sequential data
+ ***********************************************************/
+
+r_convDesc& r_Conv_NTF::convertFrom( const char *options ) throw(r_Error){
+
+ char *nitf_file_data = NULL;
+ char *nitf_img = NULL;
+ long fileSize = 0;
+ RasNITF::nitf nitf_file;
+
+ nitf_file_data = (char*) desc.src;
+
+ //READ NITF HEADERS
+
+ nitf_file.read_headers_from(nitf_file_data, int(desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1));
+
+ // MOVE POINTER TO THE IMAGE DATA
+
+ nitf_img = (char*)(desc.src + nitf_file.get_image_offset());
+ fileSize = nitf_file.get_image_size();
+
+ // CONVERT ALL DATA TO PIXEL SEQUENTIAL
+
+ nitf_file.image_to_pixel_sequential(0); // the address of the image is also known internaly so no need to pass the pointer
+
+ // ALLOCATE STORAGE FOR DESC.DEST WITH? THE SIZE OF THE IMAGE
+
+ if ((desc.dest = (char*)mystore.storage_alloc(fileSize)) == NULL)
+ {
+ RMInit::logOut << "r_Conv_NTF::convertTo(): out of memory!" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+
+ // COPY THE PIXEL SEQUENTIAL DATA TO THE DESC.DEST
+
+ memcpy(desc.dest, nitf_img, fileSize);
+
+ // SET THE INTERVALS
+
+ desc.destInterv = r_Minterval(2);
+ desc.destInterv << r_Sinterval(( r_Range)0, (r_Range) ( nitf_file.get_image_width() - 1))
+ << r_Sinterval(( r_Range)0, (r_Range) ( nitf_file.get_image_height() -1));
+
+ // SETR BASE TYPE
+
+ int image_index = 0;
+
+ if(nitf_file.isRGB(image_index)) {
+ desc.baseType = ctype_rgb;
+ } else if(nitf_file.isGRAY(image_index)) {
+ desc.baseType = ctype_char;
+ } else if(nitf_file.isBOOL(image_index)) {
+ desc.baseType = ctype_bool;
+ }
+ else {
+ RMInit::logOut << "r_Conv_NTF::convertFrom:" << "unsupported NITF file pixel type" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+
+
+/* switch (nitf_file.get_image_pixel_type()){
+ case NITF_BI:
+ desc.baseType = ctype_bool;
+ break;
+ case NITF_GRAY:
+ desc.baseType = ctype_char;
+ break;
+ case NITF_RGB:
+ desc.baseType = ctype_rgb;
+ break;
+ default:
+ RMInit::logOut << "r_Conv_NTF::convertFrom:" << "unsupported NITF file pixel type" << endl;
+ }
+*/
+ desc.destType = get_external_type(desc.baseType);
+
+ return desc;
+
+}
+
+/***********************************************************
+ * NAME: r_Conv_NTF::convertTo
+ * ---------------------------------------------------------
+ * PURPOSE: convert from rasdaman data to the
+ * corresponding nitf storage type
+ ***********************************************************/
+
+r_convDesc& r_Conv_NTF::convertTo( const char *options ) throw(r_Error){
+
+ int width=0, height=0;
+ int fileSize = 0;
+
+ // DETERMINE WIDTH AND HEIGHT
+
+ width = (int)(desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1);
+ height = (int)(desc.srcInterv[1].high() - desc.srcInterv[1].low() + 1);
+
+ // CALCULATE THE SIZE OF THE IMAGE FILE
+
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ fileSize = width * height * 1;
+ break;
+ case ctype_char:
+ fileSize = width * height * 1;
+ break;
+ case ctype_rgb:
+ fileSize = width * height * 3;
+ default:
+ RMInit::logOut << "r_Conv_BMP::convertTo(): Unknown base type!" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ // ALLOCATE STORAGE FOR THE IMAGE DATA
+
+ if ((desc.dest = (char*)mystore.storage_alloc(fileSize)) == NULL)
+ {
+ RMInit::logOut << "r_Conv_NTF::convertTo(): out of memory!" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+
+ memcpy(desc.dest, desc.src, fileSize);
+
+ // SET THE SIZE OF THE DATA
+
+ desc.destInterv = r_Minterval(1);
+ desc.destInterv << r_Sinterval((r_Range)0, (r_Range)fileSize-1);
+
+ // SET THE TYPE OF TEH DATA
+
+ desc.destType = r_Type::get_any_type("char");
+
+ return desc;
+}
+
+
+r_Convertor* r_Conv_NTF::clone( void ) const{
+ return new r_Conv_NTF(desc.src, desc.srcInterv, desc.baseType);
+}
+
+const char * r_Conv_NTF::get_name( void ) const{
+ return format_name_ntf;
+}
+
+r_Data_Format r_Conv_NTF::get_data_format( void ) const{
+ return r_NTF;
+}
diff --git a/conversion/ntf.hh b/conversion/ntf.hh
new file mode 100644
index 0000000..e4800ae
--- /dev/null
+++ b/conversion/ntf.hh
@@ -0,0 +1,80 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: ntf.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_NTF
+ *
+ * COMMENTS:
+ *
+ * Provides interface to convert data to other formats.
+ *
+*/
+
+#ifndef _R_CONV_NTF_HH_
+#define _R_CONV_NTF_HH_
+
+#include "conversion/convertor.hh"
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ NTF convertor class.
+ Completely native implementation, doesn't use external libs.
+*/
+
+class r_Conv_NTF : public r_Convert_Memory
+{
+ public:
+
+ /// constructor using an r_Type object
+ r_Conv_NTF( const char *src, const r_Minterval &interv, const r_Type *tp ) throw(r_Error);
+
+ /// constructor using convert_type_e shortcut
+ r_Conv_NTF( const char *src, const r_Minterval &interv, int tp ) throw(r_Error);
+
+ /// destructor
+ ~r_Conv_NTF( void );
+
+ /// convert to NTF
+ virtual r_convDesc &convertTo( const char *options=NULL ) throw(r_Error);
+
+ /// convert from NTF
+ virtual r_convDesc &convertFrom( const char *options=NULL ) throw(r_Error);
+
+ /// cloning
+ virtual r_Convertor *clone( void ) const;
+
+ /// identification
+ virtual const char *get_name( void ) const;
+ virtual r_Data_Format get_data_format( void ) const;
+ private:
+
+ ///keeps the block index
+ char *bl_num, *bl_size, *d_offset;
+
+};
+
+#endif
diff --git a/conversion/png.cc b/conversion/png.cc
new file mode 100644
index 0000000..b869a82
--- /dev/null
+++ b/conversion/png.cc
@@ -0,0 +1,597 @@
+/*
+* 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: png.cc
+ *
+ * MODULE: conversion
+ * Provides functions to convert data to PNG and back.
+ *
+ * CLASSES: r_Conv_PNG
+ *
+ * COMMENTS:
+ * - option parsing known bugs:
+ * * no overflow check on options string buffer
+ * * missing ")" is silently ignored
+ * * on hex input, non-hex chars are silently discarded (!)
+ * * too large numbers are mapped to unsigned short's max int
+ * * negative numbers are mapped to unsigned short's max int
+ * - do not use "," within an option because this is the parse_param separator
+ * - FIXME: define some 3xxx error codes instead of general exception
+ *
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <string.h>
+
+#include "png.h"
+
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+#include "debug.hh"
+
+#include "conversion/png.hh"
+#include "conversion/memfs.hh"
+
+#include "raslib/parseparams.hh"
+
+
+// transparency keyword in option string (cf. PNG standard):
+#define TRANSP_KEY "tRNS"
+
+
+/* memfs interface functions in C namespace */
+
+extern "C" {
+
+static void png_mem_read_data(png_struct *png_ptr, png_byte *data, png_size_t length)
+{
+ void *handle=NULL;
+
+ handle = (void*)png_get_io_ptr(png_ptr);
+ memfs_chunk_read(handle, (tdata_t)data, (tsize_t)length);
+}
+
+
+static void png_mem_write_data(png_struct *png_ptr, png_byte *data, png_size_t length)
+{
+ void *handle=NULL;
+
+ handle = (void*)png_get_io_ptr(png_ptr);
+ memfs_write(handle, (tdata_t)data, (tsize_t)length);
+}
+
+
+static void png_mem_flush_data(png_struct *png_ptr)
+{
+ void *handle=NULL;
+
+ handle = (void*)png_get_io_ptr(png_ptr);
+}
+
+
+/* Customized error handling */
+static void *png_user_error_ptr = NULL;
+
+static void png_user_warning_fn(png_struct *png_ptr, const char *warning_msg)
+{
+ fprintf(stdout, "r_Conv_PNG warning: %s\n", warning_msg); fflush(stdout);
+}
+
+static void png_user_error_fn(png_struct *png_ptr, const char *error_msg)
+{
+ fprintf(stderr, "r_Conv_PNG error: %s\n", error_msg);
+ // return from this routine, exception will be thrown in setjmp code
+}
+
+} // end of C namespace
+
+
+
+
+/*
+ * r_Conv_PNG class for converting MDD to PNG and back
+ */
+
+const char *r_Conv_PNG::name_InfoKey = "Description";
+const char *r_Conv_PNG::name_InfoText = "rasdaman MDD encoded as PNG";
+const char *r_Conv_PNG::method_convertTo = "r_Conv_PNG::convertTo()";
+const char *r_Conv_PNG::method_convertFrom = "r_Conv_PNG::convertFrom()";
+
+r_Conv_PNG::r_Conv_PNG(const char *src, const r_Minterval &interv, int tp) throw(r_Error)
+: r_Convert_Memory(src, interv, tp)
+{
+}
+
+
+r_Conv_PNG::r_Conv_PNG(const char *src, const r_Minterval &interv, const r_Type *tp) throw(r_Error)
+: r_Convert_Memory(src, interv, tp)
+{
+}
+
+
+r_Conv_PNG::~r_Conv_PNG(void)
+{
+}
+
+
+r_convDesc &r_Conv_PNG::convertTo( const char *options ) throw(r_Error)
+{
+ ENTER( "r_Conv_PNG::convertTo( " << (options==NULL?"(null)":options) << " )" );
+
+ png_struct *write_ptr=NULL;
+ png_info *info_ptr = NULL;
+ int i=0, j=0;
+ png_uint_32 width=0, height=0;
+ int colourType=0, compType=0;
+ int spp=0, bps=0, lineAdd=0, pixelAdd=0;
+ png_color_8 sig_bit;
+ png_text infotext[1];
+ char *trans_string = NULL; // transparency string buffer
+ int itemsScanned = 0; // # of items scanned in options string
+ bool transpFound = false; // keyword for transparency found in options?
+
+ i = 0; // error state: 0 is ok, !=0 is error
+
+ // option analysis: create parse object -- PB 2005-jul-12
+ if (params == NULL)
+ params = new r_Parse_Params();
+ params->add(TRANSP_KEY, &trans_string, r_Parse_Params::param_type_string);
+ transpFound = params->process(options);
+
+ // check for good options, if any
+ if (options != NULL && ! transpFound)
+ {
+ RMInit::logOut << "Error: illegal PNG option string: " << options << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_user_error_ptr, png_user_error_fn, png_user_warning_fn);
+
+ if (write_ptr == NULL)
+ i=1;
+ else
+ {
+ info_ptr = png_create_info_struct(write_ptr);
+ if (info_ptr == NULL)
+ {
+ RMInit::logOut << "Error: unable to allocate PNG header." << endl;
+ i=1;
+ }
+ else if (setjmp(write_ptr->jmpbuf))
+ {
+ png_destroy_write_struct(&write_ptr, &info_ptr);
+ RMInit::logOut << "Error: unable to save PNG stack" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ }
+
+ if (i != 0)
+ {
+ png_destroy_write_struct(&write_ptr, &info_ptr);
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ memfs_newfile(handle);
+
+ png_set_write_fn(write_ptr, (void*)handle, png_mem_write_data, png_mem_flush_data);
+
+ // Compression
+ compType = PNG_COMPRESSION_TYPE_BASE;
+
+ // Size
+ width = desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1;
+ height = desc.srcInterv[1].high() - desc.srcInterv[1].low() + 1;
+
+ // Depth and sample format and transparency
+ // added transparency -- PB 2005-jul-12
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ spp = 1; bps = 1; pixelAdd = height; lineAdd = 1;
+ colourType = PNG_COLOR_TYPE_GRAY; sig_bit.gray = 1;
+ if (transpFound)
+ {
+ itemsScanned = sscanf( trans_string, " %hi ", &(info_ptr->trans_values.gray) );
+ if (itemsScanned == 1) // all required items found?
+ {
+ info_ptr->valid |= PNG_INFO_tRNS; // activate tRNS chunk
+ }
+ else
+ {
+ RMInit::logOut << "Error: illegal syntax in transparency color specification - should be \"%i\", but is: " << trans_string << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ }
+ break;
+
+ case ctype_char:
+ spp = 1; bps = 8; pixelAdd = height; lineAdd = 1;
+ colourType = PNG_COLOR_TYPE_GRAY; sig_bit.gray = 8;
+ if (transpFound)
+ {
+ itemsScanned = sscanf( trans_string, " %hi ", &(info_ptr->trans_values.gray) );
+ if (itemsScanned == 1) // all required items found?
+ {
+ info_ptr->valid |= PNG_INFO_tRNS; // activate tRNS chunk
+ }
+ else
+ {
+ RMInit::logOut << "Error: illegal syntax in transparency color specification - should be \"%i\", but is: " << trans_string << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ }
+ break;
+
+ case ctype_rgb:
+ spp = 3; bps = 8; pixelAdd = 3*height; lineAdd = 3;
+ colourType = PNG_COLOR_TYPE_RGB;
+ sig_bit.red = 8; sig_bit.green = 8; sig_bit.blue = 8;
+ if (transpFound)
+ {
+ itemsScanned = sscanf( trans_string, " ( %hi ; %hi ; %hi ) ", &(info_ptr->trans_values.red), &(info_ptr->trans_values.green), &(info_ptr->trans_values.blue) );
+ if (itemsScanned == 3) // all required items found?
+ {
+ info_ptr->valid |= PNG_INFO_tRNS; // activate tRNS chunk
+ }
+ else
+ {
+ RMInit::logOut << "Error: illegal syntax in item #" << itemsScanned << " of transparency color specification - should be \"(%i;%i;%i)\", but is: " << trans_string << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ }
+ break;
+
+ default:
+ RMInit::logOut << "Error: " << method_convertTo << ": Unknown base type." << endl;
+ throw r_Error(r_Error::r_Error_General);
+ } // switch
+
+ // adjust transparency color value to pixel depth (unconditionally, even if transparency is unused)
+ if (bps == 8)
+ {
+ info_ptr->trans_values.red &= 0xff;
+ info_ptr->trans_values.green &= 0xff;
+ info_ptr->trans_values.blue &= 0xff;
+ info_ptr->trans_values.gray &= 0xff;
+ }
+
+ if (trans_string != NULL)
+ {
+ delete [] trans_string;
+ trans_string = NULL;
+ }
+
+
+ png_set_IHDR(write_ptr, info_ptr, width, height, bps, colourType, PNG_INTERLACE_NONE, compType, PNG_FILTER_TYPE_BASE);
+ png_set_sBIT(write_ptr, info_ptr, &sig_bit);
+
+ // Info text
+ infotext[0].key = new char[strlen(name_InfoKey)+1];
+ strcpy(infotext[0].key, name_InfoKey);
+ infotext[0].text = new char[strlen(name_InfoText)+1];
+ strcpy(infotext[0].text, name_InfoText);
+ infotext[0].compression = PNG_TEXT_COMPRESSION_NONE;
+ infotext[0].text_length = strlen(infotext[0].text);
+ png_set_text(write_ptr, info_ptr, infotext, 1);
+
+ // Write header
+ png_write_info(write_ptr, info_ptr);
+
+ png_byte *row=NULL, *rowPtr=NULL;
+ const unsigned char *src=NULL, *srcPtr=NULL;
+
+ row = new png_byte[((bps * spp * width + 7) >> 3)];
+ src = (const unsigned char*)(desc.src);
+
+ for (j=0; j<height; j++)
+ {
+ rowPtr = row; srcPtr = src;
+
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ {
+ int mask=0;
+ png_byte val=0;
+
+ val = 0; mask = 0x80; // png docs: leftmost pixel in high-order bits
+ for (i=0; i<width; i++, srcPtr += pixelAdd)
+ {
+ if (*srcPtr != 0) val |= mask;
+ mask >>= 1;
+ if (mask == 0)
+ {
+ *rowPtr++ = val; val = 0; mask = 0x80;
+ }
+ }
+ if (mask != 0x80) *rowPtr++ = val;
+ }
+ break;
+ case ctype_char:
+ {
+ for (i=0; i<width; i++, srcPtr += pixelAdd)
+ {
+ *rowPtr++ = *srcPtr;
+ }
+ }
+ break;
+ case ctype_rgb:
+ {
+ for (i=0; i<width; i++, srcPtr += pixelAdd)
+ {
+ *rowPtr++ = srcPtr[0];
+ *rowPtr++ = srcPtr[1];
+ *rowPtr++ = srcPtr[2];
+ }
+ }
+ break;
+ }
+
+ png_write_row(write_ptr, row);
+
+ src += lineAdd;
+ }
+
+ delete [] row; row=NULL;
+
+ png_write_end(write_ptr, info_ptr);
+
+#ifdef RMANDEBUG
+ // if (RManDebug >= 4)
+ {
+ RMInit::dbgOut << "wrote PNG image: width=" << width << ", height=" << height << ", bps=" << bps << ", colour=";
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ RMInit::dbgOut << "bw";
+ if (transpFound)
+ RMInit::dbgOut << ", transparent=" << info_ptr->trans_values.gray;
+ break;
+ case ctype_char:
+ RMInit::dbgOut << "grey";
+ if (transpFound)
+ RMInit::dbgOut << ", transparent=" << info_ptr->trans_values.gray;
+ break;
+ case ctype_rgb:
+ RMInit::dbgOut << "rgb";
+ if (transpFound)
+ RMInit::dbgOut << ", transparent=(" << info_ptr->trans_values.red << info_ptr->trans_values.green << info_ptr->trans_values.blue << ")";
+ break;
+ default:
+ RMInit::dbgOut << "(illegal)";
+ break;
+ }
+ RMInit::dbgOut << endl;
+ }
+#endif
+
+ // --- Cleanup -------------------------------------------------------
+ png_destroy_write_struct(&write_ptr, &info_ptr);
+
+ delete [] infotext[0].key; infotext[0].key=NULL;
+ delete [] infotext[0].text; infotext[0].text=NULL;
+
+ r_Long pngSize = memfs_size(handle);
+
+ if ((desc.dest = (char*)mystore.storage_alloc(pngSize)) == NULL)
+ {
+ RMInit::logOut << "Error: " << method_convertTo << ": out of memory." << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+ memfs_seek(handle, 0, SEEK_SET);
+ memfs_read(handle, desc.dest, pngSize);
+
+ desc.destInterv = r_Minterval(1);
+ desc.destInterv << r_Sinterval((r_Range)0, (r_Range)pngSize - 1);
+
+ // set result type to char string
+ desc.destType = r_Type::get_any_type("char");
+
+ LEAVE( "r_Conv_PNG::convertTo()" );
+ return desc;
+}
+
+
+r_convDesc &r_Conv_PNG::convertFrom(const char *options) throw(r_Error)
+{
+ png_struct *read_ptr=NULL;
+ png_info *info_ptr = NULL;
+ int i=0, j=0, pass=0, numPasses=0;
+ png_uint_32 width=0, height=0, pitch=0;
+ int colourType=0, interlaceType=0, compType=0, filterType=0;
+ int spp=0, bps=0, lineAdd=0, pixelAdd=0;
+
+ i = 0;
+ read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_user_error_ptr, png_user_error_fn, png_user_warning_fn);
+ if (read_ptr == NULL) i=1;
+ else
+ {
+ info_ptr = png_create_info_struct(read_ptr);
+ if (info_ptr == NULL) i=1;
+ else if (setjmp(read_ptr->jmpbuf))
+ {
+ png_destroy_read_struct(&read_ptr, &info_ptr, NULL);
+ RMInit::logOut << "r_Conv_PNG::convertFrom(" << options << "): unable to save the stack" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ }
+ if (i != 0)
+ {
+ png_destroy_read_struct(&read_ptr, &info_ptr, NULL);
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ memfs_chunk_initfs(handle, (char*)desc.src, (r_Long)(desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1));
+
+ desc.dest = NULL;
+
+ png_set_read_fn(read_ptr, (void*)handle, png_mem_read_data);
+
+ png_read_info(read_ptr, info_ptr);
+
+ png_get_IHDR(read_ptr, info_ptr, &width, &height, &bps, &colourType, &interlaceType, &compType, &filterType);
+
+ if (bps > 8)
+ {
+ RMInit::logOut << method_convertFrom << " warning: 16 bit samples quantized to 8 bit" << endl;
+ png_set_strip_16(read_ptr);
+ }
+
+ if ((colourType & PNG_COLOR_MASK_ALPHA) != 0)
+ {
+ RMInit::logOut << method_convertFrom << " warning: image contains alpha channel which will be lost" << endl;
+ png_set_strip_alpha(read_ptr);
+ }
+
+ if (bps < 8)
+ {
+ png_set_packing(read_ptr); // extract depths 1-4 as 1 byte per pixel
+ }
+
+ switch (colourType)
+ {
+ case PNG_COLOR_TYPE_GRAY:
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ pitch = width; lineAdd = 1; pixelAdd = height;
+ if (bps == 1) desc.baseType = ctype_bool; else desc.baseType = ctype_char;
+ break;
+ case PNG_COLOR_TYPE_PALETTE:
+ png_set_expand(read_ptr);
+ case PNG_COLOR_TYPE_RGB:
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ pitch = 3*width; lineAdd = 3; pixelAdd = 3*height;
+ desc.baseType = ctype_rgb;
+ break;
+ default:
+ RMInit::logOut << method_convertFrom << ": don't understand image format" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ numPasses = png_set_interlace_handling(read_ptr);
+
+#ifdef RMANDEBUG
+ if (RManDebug >= 4)
+ {
+ RMInit::dbgOut << "PNG image: width " << width << ", height " << height << ", bps " << bps;
+ RMInit::dbgOut << ", colour ";
+ switch (desc.baseType)
+ {
+ case ctype_bool: RMInit::dbgOut << "bw"; break;
+ case ctype_char: RMInit::dbgOut << "grey"; break;
+ case ctype_rgb: RMInit::dbgOut << "rgb"; break;
+ }
+ RMInit::dbgOut << ", interlace level " << numPasses << endl;
+ }
+#endif
+
+ png_byte *row = new png_byte[pitch];
+
+ desc.dest = (char*)mystore.storage_alloc(pitch * height);
+
+ for (pass=0; pass < numPasses; pass++)
+ {
+ unsigned char *dest, *destPtr;
+
+ dest = (unsigned char*)(desc.dest);
+ for (j=0; j<height; j++, dest += lineAdd)
+ {
+ png_byte *rowPtr=NULL;
+
+ destPtr = dest; rowPtr = row;
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ case ctype_char:
+ {
+ // In case of multiple passes set up the buffer according to the last pass
+ if (pass != 0)
+ {
+ for (i=0; i<width; i++, destPtr += pixelAdd)
+ {
+ *rowPtr++ = *destPtr;
+ }
+ destPtr = dest; rowPtr = row;
+ }
+ png_read_row(read_ptr, row, NULL);
+ for (i=0; i<width; i++, destPtr += pixelAdd)
+ {
+ *destPtr = *rowPtr++;
+ }
+ }
+ break;
+ case ctype_rgb:
+ {
+ if (pass != 0)
+ {
+ for (i=0; i<width; i++, destPtr += pixelAdd)
+ {
+ *rowPtr++ = destPtr[0]; *rowPtr++ = destPtr[1]; *rowPtr++ = destPtr[2];
+ }
+ destPtr = dest; rowPtr = row;
+ }
+ png_read_row(read_ptr, row, NULL);
+ for (i=0; i<width; i++, destPtr += pixelAdd)
+ {
+ destPtr[0] = *rowPtr++; destPtr[1] = *rowPtr++; destPtr[2] = *rowPtr++;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ png_read_end(read_ptr, info_ptr);
+
+ delete [] row; row=NULL;
+
+ png_destroy_read_struct(&read_ptr, &info_ptr, NULL);
+
+ desc.destInterv = r_Minterval(2);
+ desc.destInterv << r_Sinterval((r_Range)0, (r_Range)width-1)
+ << r_Sinterval((r_Range)0, (r_Range)height-1);
+
+ desc.destType = get_external_type(desc.baseType);
+
+ return desc;
+}
+
+
+
+const char *r_Conv_PNG::get_name( void ) const
+{
+ return format_name_png;
+}
+
+
+r_Data_Format r_Conv_PNG::get_data_format( void ) const
+{
+ return r_PNG;
+}
+
+
+r_Convertor *r_Conv_PNG::clone( void ) const
+{
+ return new r_Conv_PNG(desc.src, desc.srcInterv, desc.baseType);
+}
diff --git a/conversion/png.hh b/conversion/png.hh
new file mode 100644
index 0000000..6b56300
--- /dev/null
+++ b/conversion/png.hh
@@ -0,0 +1,79 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: png.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_PNG
+ *
+ * COMMENTS:
+ *
+ * Provides interface to convert data to other formats.
+ *
+*/
+
+#ifndef _R_CONV_PNG_HH_
+#define _R_CONV_PNG_HH_
+
+#include "conversion/convertor.hh"
+
+
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ PNG convertor class.
+
+ This class doesn't have parameters.
+*/
+
+class r_Conv_PNG : public r_Convert_Memory
+{
+ public:
+ /// constructor using an r_Type object
+ r_Conv_PNG( const char *src, const r_Minterval &interv, const r_Type *tp ) throw(r_Error);
+ /// constructor using convert_type_e shortcut
+ r_Conv_PNG( const char *src, const r_Minterval &interv, int tp ) throw(r_Error);
+ /// destructor
+ ~r_Conv_PNG( void );
+
+ /// convert to PNG
+ virtual r_convDesc &convertTo( const char *options=NULL ) throw(r_Error);
+ /// convert from PNG
+ virtual r_convDesc &convertFrom( const char *options=NULL ) throw(r_Error);
+ /// cloning
+ virtual r_Convertor *clone( void ) const;
+ /// identification
+ virtual const char *get_name( void ) const;
+ virtual r_Data_Format get_data_format( void ) const;
+
+ private:
+ /// names
+ static const char *name_InfoKey;
+ static const char *name_InfoText;
+ static const char *method_convertTo;
+ static const char *method_convertFrom;
+};
+
+#endif
diff --git a/conversion/res.cc b/conversion/res.cc
new file mode 100644
index 0000000..ffca7f9
--- /dev/null
+++ b/conversion/res.cc
@@ -0,0 +1,110 @@
+/*
+* 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>.
+*/
+
+#include <iostream>
+#include <fstream>
+
+#include "res.h"
+#include "nitf.h"
+#include "utilities.h"
+
+using namespace std;
+using namespace RasNITF;
+
+res::res(){
+
+ m_resshf = NULL;
+ m_resdata = NULL;
+}
+
+res::~res(){
+
+ if(m_resshf != NULL){
+ delete m_resshf;
+ m_resshf = NULL;
+ }
+
+ if(m_resdata != NULL){
+ delete m_resdata;
+ m_resdata = NULL;
+ }
+}
+
+int res::read_file(istream &hNITF, long lrsh, long lr){
+
+ int charsread = 0;
+
+ header_length = lrsh;
+ data_length = lr;
+
+ charsread += read_verify2(hNITF, m_re, 2 + 25 + 2 + 167 + 4);
+ n_resshl = charptrtolong(m_resshl,4);
+
+ if (n_resshl > 0) {
+ m_resshf = new char[n_resshl];
+ charsread += read_verify2(hNITF, m_resshf, n_resshl);
+ }
+
+ m_resdata = new char[data_length];
+ charsread += read_verify2(hNITF, m_resdata, data_length);
+
+ return charsread;
+}
+
+int res::write_file(ofstream &fNITF)
+
+{
+
+ int charswritten = 0;
+
+ fNITF.write(m_re, 2);
+ fNITF.write(m_restag, 25);
+ fNITF.write(m_resver, 2);
+ fNITF.write(m_ressg, 167);
+ fNITF.write(m_resshl, 4);
+
+ if (fNITF.good()) charswritten += 2 + 25 + 2 + 167 + 4;
+
+ if (n_resshl > 0) {
+ fNITF.write(m_resshf, n_resshl);
+ }
+
+ if (fNITF.good()) charswritten += n_resshl;
+
+ if( m_resdata != NULL) {
+ fNITF.write( m_resdata, data_length);
+ }
+
+ if (fNITF.good()) charswritten += data_length;
+
+ return charswritten;
+
+}
+
+string res::get_lr() const {
+ return res_dl;
+}
+
+string res::get_lrsh() const {
+ return res_hl;
+}
diff --git a/conversion/res.h b/conversion/res.h
new file mode 100644
index 0000000..a655938
--- /dev/null
+++ b/conversion/res.h
@@ -0,0 +1,64 @@
+/*
+* 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>.
+*/
+
+#ifndef __RASNITF_RES_H
+#define __RASNITF_RES_H
+
+#include <vector>
+#include <iostream>
+#include <fstream>
+
+namespace RasNITF
+{
+
+class res {
+
+ char m_re[2];
+ char m_restag[25];
+ char m_resver[2];
+ char m_ressg[167];
+ char m_resshl[4];
+ char* m_resshf;
+ char* m_resdata;
+
+ long n_resshl;
+ long data_length;
+ long header_length;
+
+ std::string res_hl;
+ std::string res_dl;
+ public:
+
+ res();
+ ~res();
+
+ int read_file(std::istream &,long,long);
+ int write_file(std::ofstream &);
+ std::string get_lr() const;
+ std::string get_lrsh() const;
+
+};
+
+}
+
+#endif
diff --git a/conversion/test/Makefile b/conversion/test/Makefile
new file mode 100644
index 0000000..410e1c4
--- /dev/null
+++ b/conversion/test/Makefile
@@ -0,0 +1,142 @@
+# -*-Makefile-*-
+#
+# 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>. # Top Level makefile. This points to the various modules that have to be build
+# and/or deployed
+#
+# MAKEFILE FOR:
+# test programs of module conversion
+#
+# COMMENTS:
+#
+##################################################################
+#
+# This is just an example Makefile for a test program.
+# The dependency of the test program on the lib of the
+# corresponding module is in the Makefile of the module.
+#
+
+######################### Definitions ############################
+
+# standard include with general options
+include $(RMANBASE)/Makefile.inc
+
+# all test programs
+ifeq ($(OSTYPE),linux-gnu)
+ALLTESTS = test_convertor test_png test_jpeg test_bmp test_vff
+else
+ALLTESTS = test_convertor test_hdf test_png test_jpeg test_bmp test_vff
+endif
+
+# For the time being: HDF includes / libs
+HDFBASE = $(SUPPORT_BASE)
+HDFINC = -I$(HDFBASE)/include
+HDFLIB = -L$(HDFBASE)/lib -ldf -ljpeg -lz -lmfhdf -lnsl
+
+ifeq ($(OSTYPE),linux-gnu)
+ LINKLIBS=$(CONVERSION) $(CLIENTCOMM) $(COMPRESSION) $(RASLIB) $(RASODMG)
+ CLIENTLDFLAGS += -lz
+else
+ ifdef RMANGCC
+ LINKLIBS=$(CONVERSION) $(CLIENTCOMM) $(COMPRESSION) $(RASLIB) $(RASODMG)
+ CLIENTLDFLAGS += -lsocket -lnsl -lz
+ else
+ LINKLIBS=$(CONVERSION) $(RASLIB)
+ endif
+endif
+
+########################### Targets ##############################
+
+# test target for convertors like r_TIFF
+.PHONY : convertor
+convertor: test_module $(ALLTESTS)
+
+.PHONY : test_module
+test_module:
+ cd $(RMANBASE)/conversion; $(MAKE)
+
+.PHONY : tiff
+tiff: test_module test_convertor
+
+.PHONY : hdf
+hdf: test_module test_hdf
+
+.PHONY : png
+png: test_module test_png
+
+.PHONY : jpeg
+jpeg: test_module test_jpeg
+
+.PHONY : bmp
+bmp: test_module test_bmp
+
+.PHONY : vff
+vff: test_module test_vff
+
+
+test_convertor: test_convertor.o $(LINKLIBS)
+ $(PURIFY) $(CXX) $(CLIENTLDFLAGS) -o $@ $^ -L$(SUPPORT_BASE)/lib -ltiff -ljpeg -lz -lcrypto
+
+test_hdf: test_hdf.o $(LINKLIBS)
+ $(PURIFY) $(CXX) $(CLIENTLDFLAGS) -o $@ $^ -L$(SUPPORT_BASE)/lib -lcrypto -lz $(HDFLIB)
+
+test_png: test_png.o $(LINKLIBS)
+ $(PURIFY) $(CXX) $(CLIENTLDFLAGS) -o $@ $^ -L$(SUPPORT_BASE)/lib -lpng -lz -lcrypto
+
+test_jpeg: test_jpeg.o $(LINKLIBS)
+ $(PURIFY) $(CXX) $(CLIENTLDFLAGS) -o $@ $^ -L$(SUPPORT_BASE)/lib -ljpeg -lz -lcrypto
+
+test_bmp: test_bmp.o $(LINKLIBS)
+ $(PURIFY) $(CXX) $(CLIENTLDFLAGS) -o $@ $^ -L$(SUPPORT_BASE)/lib -lcrypto -lz
+
+test_vff: test_vff.o $(LINKLIBS)
+ $(PURIFY) $(CXX) $(CLIENTLDFLAGS) -o $@ $^ -L$(SUPPORT_BASE)/lib -lcrypto -lz
+
+
+.PHONY : clean
+clean:
+ -rm $(ALLTESTS)
+ -rm *.o
+
+# deletes all non modified, but checked out files
+.PHONY : rcsclean
+rcsclean:
+ -rcsclean
+
+######################## Dependencies ############################
+
+test_convertor.o: test_convertor.cc
+ $(CXX) test_convertor.cc -c -o $@ $(CLIENTCXXFLAGS)
+
+test_hdf.o: test_hdf.cc
+ $(CXX) test_hdf.cc -c -o $@ $(HDFINC) $(CLIENTCXXFLAGS)
+
+test_png.o: test_png.cc
+ $(CXX) test_png.cc -c -o $@ $(CLIENTCXXFLAGS)
+
+test_jpeg.o: test_jpeg.cc
+ $(CXX) test_jpeg.cc -c -o $@ $(CLIENTCXXFLAGS)
+
+test_bmp.o: test_bmp.cc
+ $(CXX) test_bmp.cc -c -o $@ $(CLIENTCXXFLAGS)
+
+test_vff.o: test_vff.cc
+ $(CXX) test_vff.cc -c -o $@ $(CLIENTCXXFLAGS)
diff --git a/conversion/test/test_bmp.cc b/conversion/test/test_bmp.cc
new file mode 100644
index 0000000..c98712e
--- /dev/null
+++ b/conversion/test/test_bmp.cc
@@ -0,0 +1,83 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <string.h>
+
+
+#include "conversion/convertor.hh"
+#include "conversion/bmp.hh"
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+int main(int argc, char *argv[])
+{
+ char filename[256] = "Somewhere.bmp";
+ long fsize=0;
+ FILE *fp=NULL;
+ char *data=NULL;
+ r_Minterval interv(1);
+ r_Minterval imgInterv;
+ r_Conv_BMP *bmp=NULL;
+ r_convDesc desc;
+ r_Type *baseType=NULL;
+ char *imgData=NULL;
+
+ if (argc > 1)
+ strcpy(filename, argv[1]);
+
+ fp = fopen(filename, "rb");
+ if (fp == NULL)
+ {
+ cerr << "Unable to open file " << filename << endl;
+ exit(-1);
+ }
+
+ fseek(fp, 0, SEEK_END);
+ fsize = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
+ data = new char[fsize];
+ fread(data, 1, fsize, fp);
+ fclose(fp);
+
+ interv << r_Sinterval((r_Range)0, (r_Range)fsize-1);
+
+ cout << "Convert from BMP..." << endl;
+ bmp = new r_Conv_BMP(data, interv, r_Convertor::ctype_char);
+ desc = bmp->convertFrom();
+ baseType = desc.destType;
+ imgData = desc.dest;
+ imgInterv = desc.destInterv;
+ delete [] data;
+ data=NULL;
+ delete bmp;
+ bmp=NULL;
+
+ cout << "Convert to BMP..." << endl;
+ bmp = new r_Conv_BMP(imgData, imgInterv, baseType);
+ desc = bmp->convertTo("compress=1");
+ fsize = desc.destInterv[0].high() - desc.destInterv[0].low() + 1;
+
+ fp = fopen("result.bmp", "wb");
+ fwrite(desc.dest, 1, fsize, fp);
+ fclose(fp);
+
+ free(desc.dest);
+ desc.dest=NULL;
+ delete desc.destType;
+ desc.destType=NULL;
+ delete bmp;
+ bmp=NULL;
+
+ cout << "Clean up..." << endl;
+
+ delete baseType;
+ baseType=NULL;
+ free(imgData);
+ imgData=NULL;
+
+ return 0;
+}
diff --git a/conversion/test/test_convertor.cc b/conversion/test/test_convertor.cc
new file mode 100644
index 0000000..9305278
--- /dev/null
+++ b/conversion/test/test_convertor.cc
@@ -0,0 +1,276 @@
+#include <iostream>
+#include <stdio.h>
+#include <string.h>
+#include "conversion/convertor.hh"
+#include "conversion/tiff.hh"
+#include "raslib/rminit.hh"
+#include "rasodmg/gmarray.hh"
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+// define if you want to use r_Type variables to set the
+// array type.
+//#define TEST_CONV_USE_RTYPES
+
+
+void ConvertToTIFFCore(r_Conv_TIFF *tiff, const char *save, const char *params)
+{
+ r_convDesc desc;
+ FILE *tfile;
+ long size;
+
+ try
+ {
+ // desc will become invalid when the TIFF object is deleted.
+ // The same applies to all data allocated by the TIFF object,
+ // e.g. the buffer holding the resulting TIFF.
+ desc = tiff->convertTo(params);
+
+ size = (long)(desc.destInterv[0].high() - desc.destInterv[0].low() + 1);
+ if ((tfile = fopen(save, "wb")) == NULL)
+ {
+ cerr << "Error opening file " << save << endl;
+ }
+ else
+ {
+ fwrite((void*)(desc.dest), (size_t)1, (size_t)size, tfile);
+ fclose(tfile);
+ }
+ cout << "test_convertor: r_Conv_TIFF::convertTo successful. "
+ << "size = " << size << ", type = ";
+ desc.destType->print_status(cout); cout << endl;
+ // This is the job of the client!
+ free(desc.dest);
+ delete desc.destType;
+ }
+ catch (r_Error &err)
+ {
+ cout << "An error occurred: " << err.what() << endl;
+ }
+}
+
+
+void ConvertToTIFF(char *data, r_Minterval &iv, r_Type *type, const char *save, const char *params)
+{
+ r_Conv_TIFF *tiff;
+
+ cout << "test_convertor (r_Type): ";
+ if (type)
+ {
+ cout << "Base Type is "; type->print_status(cout); cout << endl;
+ }
+ else
+ {
+ cout << "Base type not defined!" << endl;
+ }
+
+ tiff = new r_Conv_TIFF(data, iv, type);
+ ConvertToTIFFCore(tiff, save, params);
+ delete tiff;
+}
+
+
+void ConvertToTIFF(char *data, r_Minterval &iv, int type, const char *save, const char *params)
+{
+ r_Conv_TIFF *tiff;
+
+ cout << "test_convertor (int):" << endl;
+
+ tiff = new r_Conv_TIFF(data, iv, type);
+ ConvertToTIFFCore(tiff, save, params);
+ delete tiff;
+}
+
+
+void ConvertFromTIFF(char *name, const char *params, const char *save_as = NULL)
+{
+ FILE *fp;
+ long size;
+ r_convDesc desc;
+ r_Conv_TIFF *tiff;
+ char *data;
+ r_Minterval iv;
+
+ fp = fopen(name, "r");
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ data = new char[size];
+ fseek(fp, 0, SEEK_SET);
+ fread((void*)data, (size_t)1, (size_t)size, fp);
+ fclose(fp);
+
+ // Set interval
+ iv = r_Minterval(1); iv << r_Sinterval(r_Range(0), r_Range(size - 1));
+
+ // Base type is coded in TIFF
+ tiff = new r_Conv_TIFF(data, iv, (int)0);
+
+ desc = tiff->convertFrom();
+
+ cout << "test_convertor: r_Conv_TIFF::convertFrom successful."
+ << " domain = " << desc.destInterv << ", type = ";
+ desc.destType->print_status(cout); cout << endl;
+
+ delete [] data;
+
+ // save file again as TIFF to check convertFrom validity?
+ if (save_as != NULL)
+ {
+ cout << "test_convertor: Saving data again as <" << save_as << ">..." << endl;
+ ConvertToTIFF(desc.dest, desc.destInterv, desc.baseType, save_as, params);
+ }
+
+ // The order in which objects are deleted is important!
+ free(desc.dest);
+ delete desc.destType;
+
+ // Delete this last. From then on desc is invalid.
+ delete tiff;
+}
+
+
+
+// Flag bits for main()
+#define CONVERTOR_WRITE_BACK 1
+
+
+// Calling convention: test_convertor [-x # -y # -c <compression> -v -h]
+// Where -x: width, -y: height, -c: compression, -v: write again as TIFF after reading
+// -h: Help on usage
+// width, height default to 200, 100
+int main (int argc, char *argv[])
+{
+ r_GMarray dummyArray; // need this for linking on Linux, don't know why
+ char *data, *lineBase, *line;
+ int width = 200, height = 100;
+ unsigned int flags = 0;
+ int i, j;
+ char params[256];
+ const char *paramptr = NULL;
+#ifdef TEST_CONV_USE_RTYPES
+ r_Type *type;
+#endif
+ struct nametable {char *write, *verify;} tiffnames[] = {
+ {"grey.tif", "grey2.tif"},
+ {"bool.tif", "bool2.tif"},
+ {"rgb.tif", "rgb2.tif"}
+ };
+
+ i = 1;
+ while (i < argc)
+ {
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'x': width = atoi(argv[++i]); break;
+ case 'y': height = atoi(argv[++i]); break;
+ case 'c':
+ sprintf(params, "comptype=%s", argv[++i]);
+ paramptr = params;
+ break;
+ case 'v': flags |= CONVERTOR_WRITE_BACK; break;
+ case 'h':
+ cout << "Usage: " << argv[0] << "[-w # -h # -c <string> -v -h]" << endl;
+ cout << "\t-x #: width" << endl;
+ cout << "\t-y #: height" << endl;
+ cout << "\t-c <string>: compression (see r_Conv_TIFF::compNames)" << endl;
+ cout << "\t-v: write the TIFF files just read back as TIFF files for verifying" << endl;
+ cout << "\t-h: this help" << endl;
+ exit(0);
+ default: cout << "Bad switch -" << argv[i][1] << endl; break;
+ }
+ }
+ i++;
+ }
+
+ cout << "test_convertor: use images of size " << width << " * " << height
+ << ", compression: ";
+
+ // Allocate enough room for _all_ types of data.
+ if ((data = new char[3*width*height]) == NULL)
+ {
+ cout << "Out of memory error!" << endl; exit(0);
+ }
+
+ r_Minterval iv(2);
+ iv << r_Sinterval(r_Range(0), r_Range(width - 1))
+ << r_Sinterval(r_Range(0), r_Range(height - 1));
+
+ // Take into account that MDD arrays are transposed compared to
+ // images!
+ cout << "Greyscale:" << endl;
+ lineBase = data;
+ for (j=0; j<height; j++, lineBase++)
+ {
+ line = lineBase;
+ for (i=0; i<width; i++, line += height)
+ {
+ *line = (char)((i+j) & 0xff);
+ }
+ }
+
+#ifdef TEST_CONV_USE_RTYPES
+ type = r_Type::get_base_type("char");
+ ConvertToTIFF(data, iv, type, tiffnames[0].write, paramptr);
+ delete type;
+#else
+ ConvertToTIFF(data, iv, (int)(r_Convertor::ctype_char), tiffnames[0].write, paramptr);
+#endif
+
+ cout << "Bitmap:" << endl;
+ lineBase = data;
+ for (j=0; j<height; j++, lineBase++)
+ {
+ line = lineBase;
+ for (i=0; i<width; i++, line += height)
+ {
+ *line = (char)((i + j) & 1);
+ }
+ }
+
+#ifdef TEST_CONV_USE_RTYPES
+ type = r_Type::get_base_type("boolean");
+ ConvertToTIFF(data, iv, type, tiffnames[1].write, paramptr);
+ delete type;
+#else
+ ConvertToTIFF(data, iv, (int)(r_Convertor::ctype_bool), tiffnames[1].write, paramptr);
+#endif
+
+ cout << "RGB:" << endl;
+ lineBase = data;
+ for (j=0; j<height; j++, lineBase += 3)
+ {
+ line = lineBase;
+ for (i=0; i<width; i++, line += 3*height)
+ {
+ line[0] = ((i+j) & 0xff); line [1] = ((0xff - (i+j)) & 0xff);
+ line[2] = (((i+j) >> 1) & 0xff);
+ }
+ }
+
+#ifdef TEST_CONV_USE_RTYPES
+ type = r_Type::get_base_type("struct{ char red, char green, char blue }");
+ ConvertToTIFF(data, iv, type, tiffnames[2].write, paramptr);
+ delete type;
+#else
+ ConvertToTIFF(data, iv, (int)(r_Convertor::ctype_rgb), tiffnames[2].write, paramptr);
+#endif
+
+ delete [] data;
+
+ // Try the other way around: convert from TIFF
+ ConvertFromTIFF("rgb.tif", paramptr,
+ ((flags & CONVERTOR_WRITE_BACK) != 0) ? tiffnames[2].verify : NULL);
+
+ ConvertFromTIFF("bool.tif", paramptr,
+ ((flags & CONVERTOR_WRITE_BACK) != 0) ? tiffnames[1].verify : NULL);
+
+ ConvertFromTIFF("grey.tif", paramptr,
+ ((flags & CONVERTOR_WRITE_BACK) != 0) ? tiffnames[0].verify : NULL);
+
+ return 0;
+}
diff --git a/conversion/test/test_hdf.cc b/conversion/test/test_hdf.cc
new file mode 100644
index 0000000..a11b98a
--- /dev/null
+++ b/conversion/test/test_hdf.cc
@@ -0,0 +1,309 @@
+#include "conversion/convertor.hh"
+#include "conversion/hdf.hh"
+#include "raslib/minterval.hh"
+#include "raslib/primitivetype.hh"
+
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+char *TypeIDToName(int tpid)
+{
+ switch (tpid)
+ {
+ case r_Primitive_Type::BOOL: return "bool"; break;
+ case r_Primitive_Type::CHAR: return "char"; break;
+ case r_Primitive_Type::OCTET: return "octet"; break;
+ case r_Primitive_Type::SHORT: return "short"; break;
+ case r_Primitive_Type::USHORT: return "ushort"; break;
+ case r_Primitive_Type::LONG: return "long"; break;
+ case r_Primitive_Type::ULONG: return "ulong"; break;
+ case r_Primitive_Type::FLOAT: return "float"; break;
+ case r_Primitive_Type::DOUBLE: return "double"; break;
+ default: return"?"; break;
+ }
+}
+
+
+int TestHDF(r_Minterval &domain, r_Type *tp, const char *params=NULL)
+{
+ r_Primitive_Type *prim;
+ char *src, *dest;
+ r_Minterval destInterv;
+ r_Conv_HDF *hdf;
+ r_Type *destType;
+ r_convDesc desc;
+ int i, j, k;
+ int rank, array_size, datasize;
+ int *dimsizes, *dimsteps, *dimidx;
+ char **srcPtrs;
+ int ptid, retid;
+
+ if (tp->isStructType())
+ {
+ cerr << "No structured types allowed!" << endl;
+ return -1;
+ }
+ prim = (r_Primitive_Type*)tp;
+ ptid = prim->type_id();
+ cout << "Source domain = " << domain << ", type = " << TypeIDToName(ptid) << endl;
+
+ switch (ptid)
+ {
+ case r_Primitive_Type::BOOL:
+ case r_Primitive_Type::CHAR:
+ case r_Primitive_Type::OCTET:
+ datasize = 1; break;
+ case r_Primitive_Type::SHORT:
+ case r_Primitive_Type::USHORT:
+ datasize = 2; break;
+ case r_Primitive_Type::LONG:
+ case r_Primitive_Type::ULONG:
+ case r_Primitive_Type::FLOAT:
+ datasize = 4; break;
+ case r_Primitive_Type::DOUBLE:
+ datasize = 8; break;
+ default:
+ cerr << "Unrecognized base type" << endl;
+ return -1;
+ }
+
+ rank = domain.dimension();
+ dimsizes = new int[rank]; dimsteps = new int[rank]; dimidx = new int[rank];
+ srcPtrs = new char*[rank];
+ for (i=0; i<rank; i++)
+ {
+ dimsizes[i] = domain[i].high() - domain[i].low() + 1;
+ dimidx[i] = 0;
+ }
+ array_size = datasize;
+ for (i=rank-1; i>=0; i--)
+ {
+ dimsteps[i] = array_size; array_size *= dimsizes[i];
+ }
+ src = new char[array_size];
+
+ for (i=0; i<rank; i++) srcPtrs[i] = src;
+
+ k = 0;
+ do
+ {
+ //cout << (int)(srcPtrs[0] - src) << endl;
+
+ // A bit inefficient, but customized code for the entire loop for each type
+ // would result in way too much code for testing purposes only.
+ switch (ptid)
+ {
+ case r_Primitive_Type::BOOL:
+ case r_Primitive_Type::CHAR:
+ case r_Primitive_Type::OCTET:
+ *((char*)srcPtrs[0]) = (char)k;
+ break;
+ case r_Primitive_Type::SHORT:
+ case r_Primitive_Type::USHORT:
+ *((short*)srcPtrs[0]) = (short)k;
+ break;
+ case r_Primitive_Type::LONG:
+ case r_Primitive_Type::ULONG:
+ *((long*)srcPtrs[0]) = (long)k;
+ break;
+ case r_Primitive_Type::FLOAT:
+ *((float*)srcPtrs[0]) = (float)k;
+ break;
+ case r_Primitive_Type::DOUBLE:
+ *((double*)srcPtrs[0]) = (double)k;
+ break;
+ default: break;
+ }
+ k++; i = 0;
+ do
+ {
+ dimidx[i]++;
+ if (dimidx[i] < dimsizes[i]) break;
+ dimidx[i] = 0; i++;
+ }
+ while (i < rank);
+ if (i < rank)
+ {
+ srcPtrs[i] += dimsteps[i];
+ if (i > 0)
+ {
+ // Init the array with the value x_0 + x_1 + ... + x_(n-1)
+ k = dimidx[0];
+ for (j=1; j<rank; j++) k += dimidx[j];
+ for (j=i; j>0; j--) {srcPtrs[j-1] = srcPtrs[j];;}
+ }
+ }
+ }
+ while (i < rank);
+
+ hdf = new r_Conv_HDF(src, domain, tp);
+
+ dest = NULL;
+
+ try
+ {
+ desc = hdf->convertTo(params);
+ dest = desc.dest;
+ destInterv = desc.destInterv;
+ destType = desc.destType;
+ }
+ catch(r_Error &err)
+ {
+ cerr << "Exception! " << err.what() << endl;
+ }
+
+ cout << "Encoded interval " << desc.destInterv << endl;
+
+ delete hdf;
+
+ if (dest != NULL)
+ {
+ try
+ {
+ hdf = new r_Conv_HDF(dest, destInterv, destType);
+
+ desc = hdf->convertFrom();
+
+ cout << "retrieved type = "; desc.destType->print_status();
+ retid = ((r_Primitive_Type*)(desc.destType))->type_id();
+ cout << ", (" << ((retid == ptid) ? "OK" : "Differs") << ')' << endl;
+ cout << "retrieved domain " << desc.destInterv << ' ';
+ i = 0;
+ if (desc.destInterv.dimension() == rank)
+ {
+ for (i=0; i<rank; i++)
+ {
+ if (desc.destInterv[i].high() - desc.destInterv[i].low() != domain[i].high() - domain[i].low())
+ break;
+ }
+ }
+ if (i < rank)
+ {
+ cout << "Incompatible!" << endl;
+ return -1;
+ }
+ cout << "(OK)" << endl;
+
+ for (i=0; i<array_size; i++)
+ {
+ if (src[i] != desc.dest[i]) break;
+ }
+ if (i == array_size)
+ {
+ cout << "Data identical" << endl;
+ }
+ else
+ {
+ cout << "Data differs at " << i << endl;
+ }
+
+ cout << endl;
+
+ delete destType;
+ delete desc.destType;
+
+ free(desc.dest); // HDF^-1 ( HDF (X) )
+ }
+ catch(r_Error &err)
+ {
+ cerr << "Exception! " << err.what() << endl;
+ }
+ }
+
+ delete hdf;
+
+ if (dest != NULL)
+ free(dest); // HDF (X)
+
+ delete [] src; // X
+
+ delete [] dimsizes; delete [] dimsteps; delete [] dimidx; delete [] srcPtrs;
+
+ // Delete the base type passed from the caller too
+ delete tp;
+
+ return 0;
+}
+
+
+
+
+
+int main(int argc, char *argv[])
+{
+ r_Minterval interv;
+ r_Type *tp;
+
+ // 3D data set over char
+ interv = r_Minterval(3);
+ interv << r_Sinterval(r_Range(0), r_Range(19))
+ << r_Sinterval(r_Range(0), r_Range(29))
+ << r_Sinterval(r_Range(0), r_Range(39));
+ tp = r_Type::get_any_type("char");
+ TestHDF(interv, tp);
+
+ // 2D data set over short
+ interv = r_Minterval(2);
+ interv << r_Sinterval(r_Range(0), r_Range(100))
+ << r_Sinterval(r_Range(0), r_Range(200));
+ tp = r_Type::get_any_type("short");
+ TestHDF(interv, tp);
+
+ // 1D data set over long
+ interv = r_Minterval(1);
+ interv << r_Sinterval(r_Range(0), r_Range(400));
+ tp = r_Type::get_any_type("long");
+ TestHDF(interv, tp);
+
+ // 2D data set over float
+ interv = r_Minterval(2);
+ interv << r_Sinterval(r_Range(0), r_Range(200))
+ << r_Sinterval(r_Range(0), r_Range(300));
+ tp = r_Type::get_any_type("float");
+ TestHDF(interv, tp);
+
+ // 2D data set over double
+ interv = r_Minterval(2);
+ interv << r_Sinterval(r_Range(100), r_Range(300))
+ << r_Sinterval(r_Range(100), r_Range(400));
+ tp = r_Type::get_any_type("double");
+ TestHDF(interv, tp);
+
+ // 1D data set over octet
+ interv = r_Minterval(1);
+ interv << r_Sinterval(r_Range(0), r_Range(200));
+ tp = r_Type::get_any_type("octet");
+ TestHDF(interv, tp);
+
+ // 1D data set over bool
+ interv = r_Minterval(1);
+ interv << r_Sinterval(r_Range(0), r_Range(200));
+ tp = r_Type::get_any_type("boolean");
+ TestHDF(interv, tp);
+
+ // 1D data set over unsigned short
+ interv = r_Minterval(1);
+ interv << r_Sinterval(r_Range(0), r_Range(200));
+ tp = r_Type::get_any_type("ushort");
+ TestHDF(interv, tp);
+
+ // 1D data set over unsigned long
+ interv = r_Minterval(1);
+ interv << r_Sinterval(r_Range(0), r_Range(200));
+ tp = r_Type::get_any_type("ulong");
+ TestHDF(interv, tp);
+
+ // 4D data set over char
+ interv = r_Minterval(4);
+ interv << r_Sinterval(r_Range(100), r_Range(149))
+ << r_Sinterval(r_Range(110), r_Range(184))
+ << r_Sinterval(r_Range(120), r_Range(219))
+ << r_Sinterval(r_Range(130), r_Range(204));
+ tp = r_Type::get_any_type("char");
+ TestHDF(interv, tp);
+
+ return 0;
+}
diff --git a/conversion/test/test_jpeg.cc b/conversion/test/test_jpeg.cc
new file mode 100644
index 0000000..e56a3d4
--- /dev/null
+++ b/conversion/test/test_jpeg.cc
@@ -0,0 +1,295 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <string.h>
+#include <math.h>
+
+
+#include "conversion/convertor.hh"
+#include "conversion/jpeg.hh"
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+static int init_identity(int offset)
+{
+ return offset;
+}
+
+static int init_square(int offset)
+{
+ return offset * offset;
+}
+
+static int SinTabOK = 0;
+static int SinusTable[512];
+
+static int init_sine(int offset)
+{
+ if (SinTabOK == 0)
+ {
+ int i;
+
+ for (i=0; i<512; i++)
+ {
+ SinusTable[i] = (int)(255*sin(M_PI * offset / 512.0));
+ }
+ SinTabOK = 1;
+ }
+ return SinusTable[offset & 511];
+}
+
+static int JpegErrorFileNumber;
+
+int test_picture(int width, int height, int bpp, const char *params, int (*init)(int))
+{
+ char *data;
+ r_Minterval interv(2);
+ int datasize;
+ int baseType;
+ int bytespp;
+ int i;
+
+ switch (bpp)
+ {
+ case 1: baseType = r_Convertor::ctype_bool; bytespp = 1; break;
+ case 8: baseType = r_Convertor::ctype_char; bytespp = 1; break;
+ case 24: baseType = r_Convertor::ctype_rgb; bytespp = 3; break;
+ default:
+ cerr << "Unknown bpp value " << bpp << endl;
+ return -1;
+ }
+
+ interv << r_Sinterval((r_Range)0, (r_Range)width-1)
+ << r_Sinterval((r_Range)0, (r_Range)height-1);
+
+ datasize = (width * bytespp * height);
+ data = new char[datasize];
+
+ cout << "Test: bpp = " << bpp << ", domain = " << interv << ", params = " << ((params == NULL) ? "" : params) << ", size = " << datasize << endl;
+
+ if (bpp > 1)
+ {
+ for (i=0; i<datasize; i++) data[i] = (char)init(i);
+ }
+ else
+ {
+ int j, count;
+
+ for (i=0; i<datasize; i+=8)
+ {
+ count = datasize - i; if (count > 8) count = 8;
+ for (j=0; j<count; j++) data[i+j] = ((init(i>>3) & (1<<j)) == 0) ? 0 : 1;
+ }
+ }
+
+ r_Conv_JPEG *jpeg = NULL;
+ char *dest = NULL;
+
+ try
+ {
+ r_convDesc desc;
+ int destsize;
+ int status = 0;
+
+ jpeg = new r_Conv_JPEG(data, interv, baseType);
+ desc = jpeg->convertTo(params);
+ destsize = desc.destInterv[0].high() - desc.destInterv[0].low() + 1;
+ cout << "\tConverted to JPEG, domain " << desc.destInterv << endl;
+ dest = desc.dest;
+ r_Minterval destInterv(desc.destInterv);
+ delete desc.destType;
+ delete jpeg;
+ jpeg = new r_Conv_JPEG(dest, destInterv, r_Convertor::ctype_char);
+ desc = jpeg->convertFrom();
+ cout << "\tConverted from JPEG, domain " << desc.destInterv << endl;
+
+ if (interv == desc.destInterv)
+ {
+ unsigned char *b, *d;
+ double totalError;
+ unsigned char maxError;
+ int i;
+
+ // Bitmaps get expanded to greyscale...
+ if (baseType == r_Convertor::ctype_bool)
+ {
+ for (i=0; i<datasize; i++)
+ {
+ if (data[i] != 0) data[i] = 0xff;
+ }
+ }
+
+ b = (unsigned char*)data; d = (unsigned char*)desc.dest;
+ totalError = 0.0; maxError = abs(*b - *d);
+ for (i=0; i<datasize; i++)
+ {
+ b[i] = abs(b[i] - d[i]);
+ if (b[i] > maxError) maxError = b[i];
+ totalError += (double)(b[i]);
+ }
+
+ r_Conv_JPEG *errpeg;
+ r_convDesc cdsc;
+ char errfile[256];
+ FILE *fp;
+ int errType;
+
+ errType = (baseType == r_Convertor::ctype_bool) ? r_Convertor::ctype_char : baseType;
+ sprintf(errfile, "jerror%d.jpg", JpegErrorFileNumber++);
+ cout << "\tCreating error file <" << errfile << "> ..." << endl;
+ cout << "\t(max error = " << (int)maxError << ", avg error = "
+ << totalError / (double)datasize << ")" << endl;
+
+ errpeg = new r_Conv_JPEG(data, interv, errType);
+ cdsc = errpeg->convertTo("quality=90");
+ i = (int)(cdsc.destInterv[0].high() - cdsc.destInterv[0].low() + 1);
+ if ((fp = fopen(errfile, "wb")) == NULL)
+ {
+ cerr << "\tUnable to open output file!" << endl;
+ }
+ else
+ {
+ fwrite(cdsc.dest, 1, i, fp);
+ fclose(fp);
+ }
+ delete cdsc.destType;
+ free(cdsc.dest);
+ delete errpeg;
+ }
+ else
+ {
+ cout << "\t Domain differs!!!" << endl;
+ status = -1;
+ }
+
+ delete jpeg;
+ delete [] data;
+ free(dest);
+ free(desc.dest);
+ delete desc.destType;
+
+ return status;
+ }
+ catch (r_Error &err)
+ {
+ cerr << "Error: " << err.what() << endl;
+
+ delete [] data;
+ if (dest != NULL) delete [] dest;
+ if (jpeg != NULL) delete jpeg;
+
+ return -1;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ char jpegfile[256] = "";
+ char params[256];
+ const char *paramptr = NULL;
+
+ i = 1;
+ while (i < argc)
+ {
+ if (strcmp(argv[i], "-file") == 0)
+ {
+ strcpy(jpegfile, argv[++i]);
+ }
+ else if (strcmp(argv[i], "-quality") == 0)
+ {
+ sprintf(params, "quality=%s", argv[++i]);
+ paramptr = params;
+ }
+ i++;
+ }
+
+ if (jpegfile[0] == '\0')
+ {
+ JpegErrorFileNumber = 0;
+ test_picture(400, 300, 1, paramptr, init_identity);
+ test_picture(400, 300, 8, paramptr, init_identity);
+ test_picture(400, 300, 24, paramptr, init_identity);
+ test_picture(701, 333, 1, paramptr, init_square);
+ test_picture(701, 333, 8, paramptr, init_square);
+ test_picture(701, 333, 24, paramptr, init_square);
+ test_picture(3007, 3999, 1, paramptr, init_sine);
+ test_picture(3007, 3999, 8, paramptr, init_sine);
+ test_picture(3007, 3999, 24, paramptr, init_sine);
+ }
+ else
+ {
+ FILE *fp;
+ long fileSize;
+ char *data = NULL;
+ char *cdata = NULL;
+ r_convDesc desc;
+ r_Type *baseType;
+ r_Conv_JPEG *jpeg;
+
+ if ((fp = fopen(jpegfile, "rb")) == NULL)
+ {
+ cerr << "Unable to open input file" << endl;
+ return -1;
+ }
+ fseek(fp, 0, SEEK_END); fileSize = ftell(fp); fseek(fp, 0, SEEK_SET);
+ data = new char[fileSize];
+ fread(data, 1, fileSize, fp);
+ fclose(fp);
+
+ jpeg = NULL; baseType = NULL;
+ try
+ {
+ r_Minterval interv(1);
+ interv << r_Sinterval((r_Range)0, (r_Range)fileSize-1);
+
+ jpeg = new r_Conv_JPEG(data, interv, 0);
+ cout << "Converting file <" << jpegfile << "> to MDD..." << endl;
+ desc = jpeg->convertFrom();
+
+ r_Minterval imgInterv(desc.destInterv);
+ delete [] data; data = NULL;
+ cdata = desc.dest;
+ baseType = desc.destType;
+ delete jpeg;
+
+ cout << "Resulting domain " << imgInterv << ", ";
+ baseType->print_status();
+ cout << endl;
+
+ jpeg = new r_Conv_JPEG(cdata, imgInterv, baseType);
+ cout << "Converting MDD back to JPEG..." << endl;
+ desc = jpeg->convertTo(paramptr);
+ free(cdata);
+ cdata = desc.dest;
+
+ cout << "Resulting domain " << desc.destInterv << ", ";
+ desc.destType->print_status();
+ cout << endl;
+
+ fp = fopen("result.jpg", "wb");
+ fileSize = desc.destInterv[0].high() - desc.destInterv[0].low() + 1;
+ fwrite(cdata, 1, fileSize, fp);
+ fclose(fp);
+
+ delete baseType;
+ free(cdata);
+
+ delete desc.destType;
+ delete jpeg;
+ }
+ catch (r_Error &err)
+ {
+ cerr << "Conversion failed: " << err.what() << endl;
+ if (baseType != NULL) delete baseType;
+ if (cdata != NULL) delete [] cdata;
+ if (jpeg != NULL) delete jpeg;
+ }
+ if (data != NULL)
+ delete [] data;
+ }
+ return 0;
+}
diff --git a/conversion/test/test_png.cc b/conversion/test/test_png.cc
new file mode 100644
index 0000000..bc481fc
--- /dev/null
+++ b/conversion/test/test_png.cc
@@ -0,0 +1,237 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <string.h>
+#include <math.h>
+
+
+#include "conversion/convertor.hh"
+#include "conversion/png.hh"
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+static int init_identity(int offset)
+{
+ return offset;
+}
+
+static int init_square(int offset)
+{
+ return offset * offset;
+}
+
+static int SinTabOK = 0;
+static int SinusTable[512];
+
+static int init_sine(int offset)
+{
+ if (SinTabOK == 0)
+ {
+ int i;
+
+ for (i=0; i<512; i++)
+ {
+ SinusTable[i] = (int)(255*sin(M_PI * offset / 512.0));
+ }
+ SinTabOK = 1;
+ }
+ return SinusTable[offset & 511];
+}
+
+int test_picture(int width, int height, int bpp, int (*init)(int))
+{
+ char *data;
+ r_Minterval interv(2);
+ int datasize;
+ int baseType;
+ int bytespp;
+ int i;
+
+ switch (bpp)
+ {
+ case 1: baseType = r_Convertor::ctype_bool; bytespp = 1; break;
+ case 8: baseType = r_Convertor::ctype_char; bytespp = 1; break;
+ case 24: baseType = r_Convertor::ctype_rgb; bytespp = 3; break;
+ default:
+ cerr << "Unknown bpp value " << bpp << endl;
+ return -1;
+ }
+
+ interv << r_Sinterval((r_Range)0, (r_Range)width-1)
+ << r_Sinterval((r_Range)0, (r_Range)height-1);
+
+ datasize = (width * bytespp * height);
+ data = new char[datasize];
+
+ cout << "Test: bpp = " << bpp << ", domain = " << interv << ", size = " << datasize << endl;
+
+ if (bpp > 1)
+ {
+ for (i=0; i<datasize; i++) data[i] = (char)init(i);
+ }
+ else
+ {
+ int j, count;
+
+ for (i=0; i<datasize; i+=8)
+ {
+ count = datasize - i; if (count > 8) count = 8;
+ for (j=0; j<count; j++) data[i+j] = ((init(i>>3) & (1<<j)) == 0) ? 0 : 1;
+ //for (j=0; j<count; j++) cout << (char)(data[i+j] + '0'); cout << endl;
+ }
+ }
+
+ r_Conv_PNG *png = NULL;
+ char *dest = NULL;
+
+ try
+ {
+ r_convDesc desc;
+ int destsize;
+ int status = -1;
+
+ png = new r_Conv_PNG(data, interv, baseType);
+ desc = png->convertTo();
+ destsize = desc.destInterv[0].high() - desc.destInterv[0].low() + 1;
+ cout << "\tConverted to PNG, domain " << desc.destInterv << endl;
+ dest = desc.dest;
+ r_Minterval destInterv(desc.destInterv);
+ delete desc.destType;
+ delete png;
+ png = new r_Conv_PNG(dest, destInterv, r_Convertor::ctype_char);
+ desc = png->convertFrom();
+ cout << "\tConverted from PNG, domain " << desc.destInterv << endl;
+
+ if (interv == desc.destInterv)
+ status = memcmp(data, desc.dest, datasize);
+
+ delete png;
+ delete [] data;
+ free(dest);
+ free(desc.dest);
+ delete desc.destType;
+
+ if (status != 0)
+ {
+ cout << "\t!!! Data not identical !!!" << endl;
+ }
+
+ return 0;
+ }
+ catch (r_Error &err)
+ {
+ cerr << "Error: " << err.what() << endl;
+
+ delete [] data;
+ if (dest != NULL) free(dest);
+ if (png != NULL) delete png;
+
+ return -1;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ char pngfile[256] = "";
+
+ i = 1;
+ while (i < argc)
+ {
+ if (strcmp(argv[i], "-file") == 0)
+ {
+ strcpy(pngfile, argv[++i]);
+ }
+ i++;
+ }
+
+ if (pngfile[0] == '\0')
+ {
+ // No PNG-file given, standard test-suite
+ test_picture(400, 300, 1, init_identity);
+ test_picture(400, 300, 8, init_identity);
+ test_picture(400, 300, 24, init_identity);
+ test_picture(701, 333, 1, init_square);
+ test_picture(701, 333, 8, init_square);
+ test_picture(701, 333, 24, init_square);
+ test_picture(3007, 3999, 1, init_sine);
+ test_picture(3007, 3999, 8, init_sine);
+ test_picture(3007, 3999, 24, init_sine);
+ }
+ else
+ {
+ // Work on this file
+ FILE *fp;
+ size_t fsize;
+ char *data;
+ r_convDesc desc;
+ r_Conv_PNG *png;
+ r_Type *baseType;
+
+ if ((fp = fopen(pngfile, "rb")) == NULL)
+ {
+ cerr << "Unable to open input file" << endl;
+ return -1;
+ }
+ fseek(fp, 0, SEEK_END); fsize = ftell(fp); fseek(fp, 0, SEEK_SET);
+
+ data = new char[fsize];
+ fread(data, 1, fsize, fp);
+ fclose(fp);
+
+ png = NULL; baseType = NULL;
+ try
+ {
+ r_Minterval interv(1);
+ interv << r_Sinterval((r_Range)0, (r_Range)fsize-1);
+
+ png = new r_Conv_PNG(data, interv, r_Convertor::ctype_char);
+ cout << "Converting file <" << pngfile << "> to MDD..." << endl;
+ desc = png->convertFrom();
+
+ cout << "Resulting domain " << desc.destInterv << ", ";
+ desc.destType->print_status();
+ cout << endl;
+
+ interv = r_Minterval(desc.destInterv);
+
+ delete [] data;
+ data = desc.dest;
+ baseType = desc.destType;
+ delete png;
+
+ fsize = (interv[0].high() - interv[0].low() + 1) * (interv[1].high() - interv[1].low() + 1);
+
+ png = new r_Conv_PNG(data, interv, baseType);
+ cout << "Converting MDD back to PNG..." << endl;
+ desc = png->convertTo();
+
+ cout << "Resulting domain " << desc.destInterv << ", ";
+ desc.destType->print_status();
+ cout << endl;
+
+ fp = fopen("result.png", "wb");
+ fwrite(desc.dest, 1, (desc.destInterv[0].high() - desc.destInterv[0].low() + 1), fp);
+ fclose(fp);
+
+ delete baseType;
+
+ free(data);
+ free(desc.dest);
+ delete desc.destType;
+ delete png;
+ }
+ catch (r_Error &err)
+ {
+ cerr << "Conversion failed: " << err.what() << endl;
+ if (baseType != NULL) delete baseType;
+ if (data != NULL) delete [] data;
+ if (png != NULL) delete png;
+ }
+ }
+
+ return 0;
+}
diff --git a/conversion/test/test_vff.cc b/conversion/test/test_vff.cc
new file mode 100644
index 0000000..e3d6016
--- /dev/null
+++ b/conversion/test/test_vff.cc
@@ -0,0 +1,169 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <iostream>
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#endif
+
+#include "conversion/vff.hh"
+#include "raslib/rminit.hh"
+#include "raslib/basetype.hh"
+
+#ifdef __GNUG__
+#include "rasodmg/transaction.hh"
+#include "raslib/template_inst.hh"
+#else
+RMINITGLOBALS('C')
+#endif
+
+
+
+static void PrintUsage(const char *name)
+{
+ cout << "Usage: " << name << " [-o <vffoutfile> -p <params> -h] <vffinfile>" << endl;
+}
+
+
+int main(int argc, char *argv[])
+{
+ const char *infile=NULL;
+ const char *outfile=NULL;
+ const char *params=NULL;
+ int i;
+
+ i=1;
+ while (i<argc)
+ {
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'o':
+ outfile = argv[++i]; break;
+ case 'p':
+ params = argv[++i]; break;
+ case 'h':
+ PrintUsage(argv[0]); exit(0);
+ default:
+ cerr << "Unknown switch " << argv[i] << endl;
+ break;
+ }
+ }
+ else
+ {
+ if (infile != NULL)
+ cerr << "More than one input file, ignored" << endl;
+ else
+ infile = argv[i];
+ }
+ i++;
+ }
+
+ if (infile == NULL)
+ {
+ PrintUsage(argv[0]);
+ exit(-1);
+ }
+
+ FILE *fp;
+ if ((fp = fopen(infile, "rb")) == NULL)
+ {
+ cerr << "Unable to open input file " << infile << endl;
+ return -1;
+ }
+
+ size_t fsize;
+ char *data;
+
+ fseek(fp, 0, SEEK_END);
+ fsize = ftell(fp);
+
+ if ((data = new char[fsize]) == NULL)
+ {
+ cerr << "Unable to claim memory for file" << endl;
+ fclose(fp);
+ return -1;
+ }
+ fseek(fp, 0, SEEK_SET);
+ fread(data, 1, fsize, fp);
+ fclose(fp);
+
+ r_Minterval interv(1);
+ interv << r_Sinterval((r_Range)0, (r_Range)fsize-1);
+ r_Conv_VFF conv(data, interv, r_Convertor::ctype_char);
+ r_convDesc desc;
+
+ cout << "Convert from VFF... " << flush;
+ try
+ {
+ desc = conv.convertFrom(params);
+ cout << "OK" << endl;
+
+ r_Conv_VFF convb(desc.dest, desc.destInterv, desc.destType);
+ r_convDesc descb;
+
+ cout << "Convert back to VFF... " << flush;
+ try
+ {
+ descb = convb.convertTo(params);
+ cout << "OK" << endl;
+
+ if (outfile != NULL)
+ {
+ if ((fp = fopen(outfile, "wb")) == NULL)
+ {
+ cerr << "Unable to write to file " << outfile << endl;
+ }
+ else
+ {
+ fsize = (size_t)(descb.destInterv[0].high() - descb.destInterv[0].low() + 1);
+ fwrite(descb.dest, 1, fsize, fp);
+ fclose(fp);
+ }
+ }
+
+ // endianness-safe comparison of binary data:
+ // convert the just created VFF data back to an MDD and compare the
+ // result with the first MDD thus converted.
+ r_Conv_VFF convc(descb.dest, descb.destInterv, descb.destType);
+ r_convDesc descc;
+
+ cout << "Compare binary data... " << flush;
+ try
+ {
+ descc = convc.convertFrom(params);
+ if (memcmp(descc.dest, desc.dest, desc.destInterv.cell_count() * ((r_Base_Type*)desc.destType)->size()) == 0)
+ cout << "identical" << endl;
+ else
+ cout << "differs!!!" << endl;
+
+ delete descc.destType;
+ free(descc.dest);
+ }
+ catch (r_Error &err)
+ {
+ cerr << "failed: " << err.what() << endl;
+ }
+
+ delete descb.destType;
+ free(descb.dest);
+ }
+ catch (r_Error &err)
+ {
+ cerr << "failed: " << err.what() << endl;
+ }
+ delete desc.destType;
+ free(desc.dest);
+ }
+ catch (r_Error &err)
+ {
+ cerr << "failed: " << err.what() << endl;
+ }
+
+ delete [] data;
+
+ return 0;
+}
diff --git a/conversion/text.cc b/conversion/text.cc
new file mode 100644
index 0000000..82ec81b
--- /dev/null
+++ b/conversion/text.cc
@@ -0,0 +1,138 @@
+/*
+* 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>.
+*/
+
+#include <iostream>
+#include <fstream>
+
+#include "text.h"
+#include "nitf.h"
+#include "utilities.h"
+
+using namespace std;
+using namespace RasNITF;
+
+RasNITF::text::text()
+{
+ m_text_data = NULL;
+ m_txshd = NULL;
+}
+
+RasNITF::text::~text()
+{
+ if(m_text_data != NULL)
+ delete m_text_data;
+ m_text_data = NULL;
+
+ if(m_txshd != NULL)
+ delete m_txshd;
+ m_txshd = NULL;
+
+}
+
+int RasNITF::text::read_file(istream &hNITF, long th_length, long text_length)
+{
+ int charsread = 0;
+ long starting_position = 0;
+
+ header_length=th_length;
+ starting_position = hNITF.tellg();
+ charsread += read_verify2(hNITF, m_te, 2 + 7 + 3 + 14 + 80 + 1 + 2 + 11 + 2 + 20 + 2 + 8+ 4+ 1+ 8+ 43 + 1 + 40 + 1 + 8+ 15+ 1+ 3);
+
+ // read txshdl
+
+ charsread += read_verify2(hNITF, m_txshdl, 5);
+ n_txshdl = charptrtolong(m_txshdl, 5);
+
+ if (n_txshdl > 0) {
+ n_txshdl -= 3;
+ charsread += read_verify2(hNITF, m_txsofl, 3);
+ m_txshd = new char[n_txshdl];
+ if(m_txshd == NULL) cerr<<"ERROR: could not allocate memory";
+ charsread += read_verify2(hNITF, m_txshd, n_txshdl);
+ n_txshdl += 3;
+
+ }
+
+ // check if we are where we should be
+ if((long)(hNITF.tellg()) != starting_position + th_length) exit(2);
+
+ // store the text data
+
+ m_text_data = new char[text_length];
+ if(m_text_data == NULL) cerr<<"ERROR: could not allocate memory";
+ charsread += read_verify2(hNITF, m_text_data, text_length);
+ data_length = text_length;
+
+ return charsread;
+}
+
+int RasNITF::text::write_file(ofstream &fNITF)
+{
+
+ fNITF.write(m_te, 2);
+ fNITF.write(m_textid, 7);
+ fNITF.write(m_txtalvl, 3);
+ fNITF.write(m_txtdt, 14);
+ fNITF.write(m_txtitl, 80);
+ fNITF.write(m_tsclas, 1);
+ fNITF.write(m_tsclsy, 2);
+ fNITF.write(m_tscode, 11);
+ fNITF.write(m_tsctlh, 2);
+ fNITF.write(m_tsrel, 20);
+ fNITF.write(m_tsdctp, 2);
+ fNITF.write(m_tsdcdt, 8);
+ fNITF.write(m_tsdcxm, 4);
+ fNITF.write(m_tsdg, 1);
+ fNITF.write(m_tsdgdt, 8);
+ fNITF.write(m_tscltx, 43);
+ fNITF.write(m_tscatp, 1);
+ fNITF.write(m_tscaut, 40);
+ fNITF.write(m_tscrsn, 1);
+ fNITF.write(m_tssrdt, 8);
+ fNITF.write(m_tsctln, 15);
+ fNITF.write(m_encryp, 1);
+ fNITF.write(m_txtfmt, 3);
+
+ fNITF.write(m_txshdl, 5);
+
+ if (n_txshdl > 0) {
+ fNITF.write(m_txsofl, 3);
+ fNITF.write(m_txshd, n_txshdl - 3);
+ }
+
+ if( m_text_data != NULL) {
+ fNITF.write( m_text_data, data_length);
+ }
+
+ //TODO:
+ return 0;
+
+}
+
+string RasNITF::text::get_lt() const {
+ return text_dl;
+}
+
+string RasNITF::text::get_ltsh() const {
+ return text_hl;
+}
diff --git a/conversion/text.h b/conversion/text.h
new file mode 100644
index 0000000..3746286
--- /dev/null
+++ b/conversion/text.h
@@ -0,0 +1,86 @@
+/*
+* 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>.
+*/
+
+
+#ifndef __TEXT_H_INCLUDED
+#define __TEXT_H_INCLUDED
+
+#include<vector>
+#include <iostream>
+#include <fstream>
+
+namespace RasNITF
+{
+/* forward declarations follow : */
+
+class nitf;
+
+class text
+{
+ private:
+ char m_te[2];
+ char m_textid[7];
+ char m_txtalvl[3];
+ char m_txtdt[14];
+ char m_txtitl[80];
+ char m_tsclas[1];
+ char m_tsclsy[2];
+ char m_tscode[11];
+ char m_tsctlh[2];
+ char m_tsrel[20];
+ char m_tsdctp[2];
+ char m_tsdcdt[8];
+ char m_tsdcxm[4];
+ char m_tsdg[1];
+ char m_tsdgdt[8];
+ char m_tscltx[43];
+ char m_tscatp[1];
+ char m_tscaut[40];
+ char m_tscrsn[1];
+ char m_tssrdt[8];
+ char m_tsctln[15];
+ char m_encryp[1];
+ char m_txtfmt[3];
+ char m_txshdl[5];
+ char m_txsofl[3];
+ char* m_txshd;
+ char *m_text_data;
+
+ int header_length;
+ int data_length;
+ int n_txshdl;
+ int n_txsofl;
+
+ std::string text_hl ;
+ std::string text_dl ;
+
+ public:
+ text();
+ ~text(); //destructor freeing memory
+ int read_file(std::istream &,long,long);
+ int write_file(std::ofstream &); //writes the information to the data file
+ std::string get_lt() const;
+ std::string get_ltsh() const;
+};
+}
+#endif
diff --git a/conversion/tiff.cc b/conversion/tiff.cc
new file mode 100644
index 0000000..463f858
--- /dev/null
+++ b/conversion/tiff.cc
@@ -0,0 +1,653 @@
+/*
+* 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: tiff.cc
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_TIFF
+ *
+ * COMMENTS:
+ *
+ * Provides functions to convert data to TIFF and back.
+ *
+*/
+
+#include <iostream>
+#include <string.h>
+
+#ifdef AIX
+#include <strings.h>
+#endif
+
+#include "conversion/tiff.hh"
+#include "conversion/memfs.hh"
+#include "raslib/error.hh"
+#include "raslib/rminit.hh"
+#include "raslib/parseparams.hh"
+
+const int r_Conv_TIFF::defaultRPS = 32;
+
+const char r_Conv_TIFF::dummyFileFmt[] = "/tmp/%p.tif";
+
+const struct r_Convertor::convert_string_s r_Conv_TIFF::compNames[] = {
+ {"none", COMPRESSION_NONE},
+ {"ccittrle", COMPRESSION_CCITTRLE},
+ {"ccittfax3", COMPRESSION_CCITTFAX3},
+ {"ccittfax4", COMPRESSION_CCITTFAX4},
+ {"lzw", COMPRESSION_LZW},
+ {"ojpeg", COMPRESSION_OJPEG},
+ {"jpeg", COMPRESSION_JPEG},
+ {"next", COMPRESSION_NEXT},
+ {"ccittrlew", COMPRESSION_CCITTRLEW},
+ {"packbits", COMPRESSION_PACKBITS},
+ {"thunderscan", COMPRESSION_THUNDERSCAN},
+ {"pixarfilm", COMPRESSION_PIXARFILM},
+ {"pixarlog", COMPRESSION_PIXARLOG},
+ {"deflate", COMPRESSION_DEFLATE},
+ {"dcs", COMPRESSION_DCS},
+ {"jbig", COMPRESSION_JBIG},
+#ifndef LINUX
+ {"sgilog", COMPRESSION_SGILOG},
+ {"sgilog24", COMPRESSION_SGILOG24},
+ {"it8ctpad", COMPRESSION_IT8CTPAD},
+ {"it8lw", COMPRESSION_IT8LW},
+ {"it8mp", COMPRESSION_IT8MP},
+ {"it8bl", COMPRESSION_IT8BL},
+#endif
+ {NULL, COMPRESSION_NONE}
+};
+
+const struct r_Convertor::convert_string_s r_Conv_TIFF::resunitNames[] = {
+ {"none", RESUNIT_NONE},
+ {"inch", RESUNIT_INCH},
+ {"centimeter", RESUNIT_CENTIMETER},
+ {NULL, RESUNIT_NONE}
+};
+
+// Change these according to the platform!
+// Fill order of bits in bitmap mode. Define 0 for LSB, otherwise MSB
+#define _R_TIFF_BITFILLORDER 1
+
+
+// Setup internal macros according to the fill-order
+#if (_R_TIFF_BITFILLORDER == 0)
+#define _R_TIFF_MASK_VALUE 1
+#define _R_TIFF_MASK_SHIFT(x) (x) <<= 1;
+#else
+#define _R_TIFF_MASK_VALUE (1<<7)
+#define _R_TIFF_MASK_SHIFT(x) (x) >>= 1;
+#endif
+
+
+// TIFF class functions
+
+// Translate string compression type to libtiff compression type
+int r_Conv_TIFF::get_compression_from_name(const char* strComp)
+{
+ unsigned short i=0;
+ int tiffComp=COMPRESSION_NONE;
+
+ if(strComp != NULL)
+ {
+ for (i=0; compNames[i].key != NULL; i++)
+ {
+ if (strcasecmp(compNames[i].key, strComp) == 0)
+ {
+ tiffComp = compNames[i].id;
+ break;
+ }
+ }
+
+ if (compNames[i].key == NULL)
+ RMInit::logOut << "r_Conv_TIFF::get_compression_from_name(): unsupported compression type " << strComp << endl;
+ }
+
+ return tiffComp;
+}
+
+// Translate string resolution unit type to libtiff resolution unit type
+int r_Conv_TIFF::get_resunit_from_name(const char* strResUnit)
+{
+ unsigned short i=0;
+ int tiffResUnit=RESUNIT_NONE;
+
+ if(strResUnit != NULL)
+ {
+ for (i=0; resunitNames[i].key != NULL; i++)
+ {
+ if (strcasecmp(resunitNames[i].key, strResUnit) == 0)
+ {
+ tiffResUnit = resunitNames[i].id;
+ break;
+ }
+ }
+
+ if (resunitNames[i].key == NULL)
+ RMInit::logOut << "r_Conv_TIFF::get_resunit_from_name(): unsupported resolution unit type " << strResUnit << endl;
+ }
+
+ return tiffResUnit;
+}
+
+void r_Conv_TIFF::initTIFF( void )
+{
+ compType = NULL;
+ quality = 80;
+ override_bpp = 0;
+ override_bps = 0;
+ override_depth = 0;
+
+ if (params == NULL)
+ params = new r_Parse_Params();
+
+ params->add("comptype", &compType, r_Parse_Params::param_type_string);
+ params->add("quality", &quality, r_Parse_Params::param_type_int);
+ params->add("bpp", &override_bpp, r_Parse_Params::param_type_int);
+ params->add("bps", &override_bps, r_Parse_Params::param_type_int);
+ params->add("depth", &override_depth, r_Parse_Params::param_type_int);
+}
+
+
+r_Conv_TIFF::r_Conv_TIFF(const char *src, const r_Minterval &interv, const r_Type *tp) throw(r_Error)
+: r_Convert_Memory(src, interv, tp)
+{
+ initTIFF();
+}
+
+
+r_Conv_TIFF::r_Conv_TIFF(const char *src, const r_Minterval &interv, int type) throw(r_Error)
+: r_Convert_Memory(src, interv, type)
+{
+ initTIFF();
+}
+
+
+r_Conv_TIFF::~r_Conv_TIFF(void)
+{
+ if (compType != NULL)
+ {
+ delete [] compType;
+ compType = NULL;
+ }
+}
+
+
+// Compression modes recommended:
+//
+// Bitmap, Greyscales: COMPRESSION_LZW, COMPRESSION_DEFLATE
+// RGB: COMPRESSION_JPEG, COMPRESSION_SGILOG24
+r_convDesc &r_Conv_TIFF::convertTo( const char *options ) throw(r_Error)
+{
+ if (options != NULL)
+ printf("tiff convert option = %s\n", options);
+ else
+ printf("tiff options are null = %s\n");
+ TIFF *tif=NULL;
+ char dummyFile[256];
+ uint16 cmap[256]; // Colour map (for greyscale images)
+ uint32 pixelAdd=0, lineAdd=0; // number of _bytes_ to add to a pointer
+ // to the source data to get the address
+ // of the pixel to the right / downwards.
+ uint16 bps=0, bpp=0;
+ uint32 width=0, height=0, i=0;
+ int tiffcomp = COMPRESSION_NONE;
+
+ params->process(options);
+
+ // translate string compression type to libtiff compression type
+ if (compType != NULL)
+ tiffcomp=get_compression_from_name(compType);
+
+ // Set dimensions
+ width = (uint32)(desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1);
+ height = (uint32)(desc.srcInterv[1].high() - desc.srcInterv[1].low() + 1);
+
+ switch (desc.baseType)
+ {
+ // MDD arrays are transposed compared to the format needed for images.
+ // Therefore the pixelAdd and lineAdd values change places.
+ case ctype_bool:
+ bps = 1; bpp = 1; pixelAdd = height; lineAdd = 1;
+ break;
+ case ctype_char:
+ bps = 8; bpp = 8; pixelAdd = height; lineAdd = 1;
+ break;
+ case ctype_rgb:
+ bps = 8; bpp = 24; pixelAdd = 3*height; lineAdd = 3;
+ break;
+ default: RMInit::logOut << "r_Conv_TIFF::convertTo(): unknown base type!" << endl;
+ throw r_Error(BASETYPENOTSUPPORTEDBYOPERATION);
+ }
+
+ // Just to make sure nothing serious goes wrong if this conversion
+ // function is called more than once.
+ memfs_newfile(handle);
+
+ // Open a dummy output file (all operations will be redirected to
+ // Memory). Make dummy file unique for each object by using the
+ // address of its memFSContext (kind of a hack, I know...). That
+ // should ensure re-entrancy.
+ sprintf(dummyFile, dummyFileFmt, (void*)handle);
+ tif = TIFFClientOpen(dummyFile, "w", handle,
+ memfs_read, memfs_write, memfs_seek, memfs_close, memfs_size,
+ memfs_map, memfs_unmap);
+
+ if (tif == NULL)
+ {
+ RMInit::logOut << "r_Conv_TIFF::convertTo(): couldn't open file " << dummyFile << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ TIFFSetField(tif, TIFFTAG_ARTIST, "RasDaMan");
+ TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, "Image");
+ TIFFSetField(tif, TIFFTAG_SOFTWARE, "RasDaMan");
+ //TIFFSetField(tif, TIFFTAG_SUBFILETYPE, (uint32)0);
+ TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
+ TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
+ // UNIX doesn't mind which fill-order. NT only understands this one.
+ TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
+ TIFFSetField(tif, TIFFTAG_COMPRESSION, (uint16)tiffcomp);
+ TIFFSetField(tif, TIFFTAG_ORIENTATION, (uint16)ORIENTATION_TOPLEFT);
+ // Format-dependent tags
+ if (desc.baseType == ctype_rgb)
+ {
+ TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, (uint16)PHOTOMETRIC_RGB);
+ TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (uint16)3);
+ }
+ else
+ {
+ if (desc.baseType == ctype_char)
+ {
+ TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, (uint16)PHOTOMETRIC_PALETTE);
+ }
+ else
+ {
+ TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, (uint16)PHOTOMETRIC_MINISBLACK);
+ }
+ TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (uint16)1);
+ }
+ TIFFSetField(tif, TIFFTAG_PLANARCONFIG, (uint16)PLANARCONFIG_CONTIG);
+ TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, (uint32)-1));
+ //TIFFSetField(tif, TIFFTAG_MINSAMPLEVALUE, (uint16)0);
+ //TIFFSetField(tif, TIFFTAG_MAXSAMPLEVALUE, (uint16)255);
+ TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, (uint16)RESUNIT_INCH);
+ TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float)90.0);
+ TIFFSetField(tif, TIFFTAG_YRESOLUTION, (float)90.0);
+ TIFFSetField(tif, TIFFTAG_XPOSITION, (float)0.0);
+ TIFFSetField(tif, TIFFTAG_YPOSITION, (float)0.0);
+ if ((tiffcomp == COMPRESSION_JPEG) || (tiffcomp == COMPRESSION_OJPEG))
+ {
+ if (quality == 100)
+ {
+ TIFFSetField(tif, TIFFTAG_JPEGPROC, JPEGPROC_LOSSLESS);
+ }
+ else
+ {
+ TIFFSetField(tif, TIFFTAG_JPEGQUALITY, quality);
+ }
+ }
+
+ // build the colour-map (greyscale, i.e. all 3 components identical)
+ // TIFF needs 16 bit values for this (--> tools/tiffdither.c)
+ for (i=0; i<256; i++) cmap[i] = (uint16)(i*((1L << 16) - 1)/255);
+ TIFFSetField(tif, TIFFTAG_COLORMAP, cmap, cmap, cmap);
+
+ // Be VERY, VERY careful about the order and the items you write
+ // out. TIFFWriteDirectory, e.g., has very ugly side-effects.
+ uint32 *tbuff=NULL;
+ const char *l=NULL, *line = desc.src;
+ uint8 *normal=NULL; // normalised source data
+ uint32 row=0;
+
+ // cout << "r_Conv_TIFF: Main Loop:" << endl;
+ if ((tbuff = new uint32[((width * bpp + 31) >> 5)]) != NULL)
+ {
+ // now go line by line
+ for (row = 0; row < height; row++, line += lineAdd)
+ {
+ normal = (uint8 *)tbuff; l = line;
+
+ // copy data in the correct format to the buffer
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ {
+ uint8 val = 0, mask = _R_TIFF_MASK_VALUE;
+
+ // convert 8bpp bitmap to 1bpp bitmap
+ for (i=0; i < width; i++, l += pixelAdd)
+ {
+ // fill bits in lsb order
+ if (*l != 0) val |= mask;
+ _R_TIFF_MASK_SHIFT(mask);
+ if (mask == 0) {*normal++ = val; val = 0; mask = _R_TIFF_MASK_VALUE;}
+ }
+ if (mask != _R_TIFF_MASK_VALUE) *normal++ = val;
+ }
+ break;
+ case ctype_char:
+ {
+ // copy data (and transpose)
+ for (i=0; i < width; i++, l += pixelAdd)
+ {
+ *normal++ = *l;
+ }
+ }
+ break;
+ case ctype_rgb:
+ {
+ // copy data (and transpose)
+ for (i=0; i < width; i++, l += pixelAdd)
+ {
+ *normal++ = l[0]; *normal++ = l[1]; *normal++ = l[2];
+ }
+ }
+ break;
+ }
+ if (TIFFWriteScanline(tif, (tdata_t)tbuff, row, 0) < 0) break;
+ }
+
+ delete [] tbuff; tbuff = NULL;
+ }
+
+ if (row < height) // error
+ {
+ RMInit::logOut << "r_Conv_TIFF::convertTo(): error writing data!" << endl;
+ TIFFClose(tif); remove(dummyFile);
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ TIFFClose(tif);
+ // Now delete the dummy file
+ remove(dummyFile);
+
+ r_Long tifSize = memfs_size(handle);
+
+ // Allocate an array of just the right size and "load" object there
+ if ((desc.dest = (char*)mystore.storage_alloc(sizeof(char) * tifSize)) == NULL)
+ {
+ RMInit::logOut << "r_Conv_TIFF::convertTo(): out of memory" << endl;
+ throw r_Error(MEMMORYALLOCATIONERROR);
+ }
+ memfs_seek(handle, 0, SEEK_SET);
+ memfs_read(handle, desc.dest, tifSize);
+
+ // Set up destination interval
+ desc.destInterv = r_Minterval(1);
+ desc.destInterv << r_Sinterval(r_Range(0), r_Range(tifSize - 1));
+
+ // define the base type as char for now
+ desc.destType = r_Type::get_any_type("char");
+
+ return desc;
+}
+
+
+
+r_convDesc &r_Conv_TIFF::convertFrom(const char *options) throw(r_Error)
+{
+ if (options != NULL)
+ printf("tiff convert option = %s\n", options);
+ else
+ printf("tiff options are null = %s\n");
+ params->process(options);
+ TIFF *tif=NULL;
+ char dummyFile[256];
+ int isOK=0, typeSize=0;
+ uint16 bps=0, bpp=0, spp=0, planar=0, photometric=0;
+ uint32 width=0, height=0, pixelAdd=0, lineAdd=0, i=0;
+ uint16 *reds=NULL, *greens=NULL, *blues=NULL;
+
+ // Init simple (chunky) memFS
+ memfs_chunk_initfs(handle, (char*)desc.src, (r_Long)(desc.srcInterv[0].high()-desc.srcInterv[0].low()+1));
+
+ desc.dest = NULL;
+
+ // Create dummy file for use in the TIFF open function
+ sprintf(dummyFile, dummyFileFmt, (void*)handle);
+ fclose(fopen(dummyFile, "wb"));
+ //cout << "r_Conv_TIFF: Dummy created OK" << endl;
+
+ // Open and force memory mapping mode
+ tif = TIFFClientOpen(dummyFile, "rM", handle,
+ memfs_chunk_read, memfs_chunk_read, memfs_chunk_seek, memfs_chunk_close,
+ memfs_chunk_size, memfs_chunk_map, memfs_chunk_unmap);
+
+ if (tif == NULL)
+ {
+ RMInit::logOut << "r_Conv_TIFF::convertFrom(): unable to open file!" << endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+ //cout << "r_Conv_TIFF: Opened OK" << endl;
+
+ //TIFFPrintDirectory(tif, stdout, 0);
+
+ TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bps);
+ TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
+ bpp = spp * bps;
+ TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar);
+ TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
+ TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
+ TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric);
+
+ // Filter out the kind of image we understand.
+ isOK = 1;
+ if ((bps != 1) && (bps != 8))
+ {
+ RMInit::logOut << "r_Conv_TIFF::convertFrom(): bad number of bits per sample: " << bps << " (must be 1 or 8)" << endl;
+ if (override_bps)
+ bps = override_bps;
+ else
+ isOK = 0;
+ }
+ if ((bpp != 1) && (bpp != 8) && (bpp != 24))
+ {
+ RMInit::logOut << "r_Conv_TIFF::convertFrom(): bad number of bits per pixel: " << bpp << " (must be 1, 8 or 24)" << endl;
+ if (override_bpp)
+ bpp = override_bpp;
+ else
+ isOK = 0;
+ }
+ if (planar != PLANARCONFIG_CONTIG)
+ {
+ RMInit::logOut << "r_Conv_TIFF::convertFrom(): can't handle bitplanes!" << endl;
+ isOK = 0;
+ }
+
+ if (isOK)
+ {
+ //cout << "r_Conv_TIFF: Image OK: bps = " << bps << ", spp = " << spp << ", width = " << width << ", height = " << height << endl;
+
+ if (bpp == 24)
+ {
+ pixelAdd = 3*height; lineAdd = 3; typeSize = 3;
+ desc.baseType = ctype_rgb;
+ }
+ else
+ {
+ if ((photometric == PHOTOMETRIC_PALETTE) && (override_depth != 1))
+ {
+ TIFFGetField(tif, TIFFTAG_COLORMAP, &reds, &greens, &blues);
+ for (i=0; i<256; i++)
+ {
+ if ((reds[i] != greens[i]) || (greens[i] != blues[i])) break;
+ }
+ if (i < 256)
+ {
+ pixelAdd = 3*height; lineAdd = 3; typeSize = 3;
+ desc.baseType = ctype_rgb;
+ }
+ else
+ {
+ pixelAdd = height; lineAdd = 1; typeSize = 1;
+ desc.baseType = ctype_char;
+ }
+ if (override_depth)
+ {
+ switch (override_depth)
+ {
+ case 1:
+ pixelAdd = height; lineAdd = 1; typeSize = 1;
+ desc.baseType = ctype_bool;
+ break;
+ case 8:
+ pixelAdd = height; lineAdd = 1; typeSize = 1;
+ desc.baseType = ctype_char;
+ break;
+ case 24:
+ pixelAdd = 3*height; lineAdd = 3; typeSize = 3;
+ desc.baseType = ctype_rgb;
+ break;
+ }
+ }
+ }
+ else
+ {
+ pixelAdd = height; lineAdd = 1; typeSize = 1;
+ desc.baseType = (bpp == 1) ? ctype_bool : ctype_char;
+ }
+ }
+
+ if ((desc.dest = (char*)mystore.storage_alloc(width*height*typeSize*sizeof(char))) == NULL)
+ {
+ RMInit::logOut << "r_Conv_TIFF::convertFrom(): out of memory error!" << endl;
+ }
+ else
+ {
+ //cout << "r_Conv_TIFF: baseType = " << desc.baseType << ", size = " << typeSize << ", pixelAdd = " << pixelAdd << ", lineAdd = " << lineAdd << endl;
+
+ uint32 *tbuff=NULL;
+ char *l=NULL, *line = desc.dest;
+ uint8 *normal=NULL;
+ uint32 row = 0;
+
+ if ((tbuff = new uint32[(width * bpp + 31) >> 5]) != NULL)
+ {
+ for (row = 0; row < height; row++, line += lineAdd)
+ {
+ if (TIFFReadScanline(tif, (tdata_t)tbuff, row, 0) < 0) break;
+
+ normal = (uint8 *)tbuff; l = line;
+
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ {
+ uint8 mask = _R_TIFF_MASK_VALUE;
+
+ for (i=0; i < width; i++, l += pixelAdd)
+ {
+ *l = (((*normal) & mask) == 0) ? 0 : 1;
+ _R_TIFF_MASK_SHIFT(mask);
+ if (mask == 0) {normal++; mask = _R_TIFF_MASK_VALUE;}
+ }
+ }
+ break;
+ case ctype_char:
+ {
+ if (reds != NULL)
+ {
+ for (i=0; i < width; i++, l += pixelAdd)
+ {
+ *l = (reds[*normal++]) >> 8;
+ }
+ }
+ else
+ {
+ for (i=0; i < width; i++, l += pixelAdd)
+ {
+ *l = *normal++;
+ }
+ }
+ }
+ break;
+ case ctype_rgb:
+ {
+ if (reds != NULL)
+ {
+ for (i=0; i < width; i++, l += pixelAdd)
+ {
+ uint8 val = *normal++;
+
+ l[0] = (reds[val]) >> 8;
+ l[1] = (greens[val]) >> 8;
+ l[2] = (blues[val]) >> 8;
+ }
+ }
+ else
+ {
+ for (i=0; i < width; i++, l += pixelAdd)
+ {
+ l[0] = *normal++; l[1] = *normal++; l[2] = *normal++;
+ }
+ }
+ }
+ break;
+ }
+ }
+ delete [] tbuff; tbuff = NULL;
+ }
+
+ if (row < height)
+ {
+ RMInit::logOut << "r_Conv_TIFF::convertFrom(): error reading data!" << endl;
+ TIFFClose(tif); remove(dummyFile);
+ throw r_Error(r_Error::r_Error_General);
+ }
+ }
+ }
+
+ TIFFClose(tif);
+
+ remove(dummyFile);
+
+ // Build destination interval
+ desc.destInterv = r_Minterval(2);
+ desc.destInterv << r_Sinterval(r_Range(0), r_Range(width - 1))
+ << r_Sinterval( r_Range(0), r_Range(height - 1));
+
+ desc.destType = get_external_type(desc.baseType);
+
+ return desc;
+}
+
+
+
+const char *r_Conv_TIFF::get_name( void ) const
+{
+ return format_name_tiff;
+}
+
+
+r_Data_Format r_Conv_TIFF::get_data_format( void ) const
+{
+ return r_TIFF;
+}
+
+
+r_Convertor *r_Conv_TIFF::clone( void ) const
+{
+ return new r_Conv_TIFF(desc.src, desc.srcInterv, desc.baseType);
+}
diff --git a/conversion/tiff.hh b/conversion/tiff.hh
new file mode 100644
index 0000000..008f1c5
--- /dev/null
+++ b/conversion/tiff.hh
@@ -0,0 +1,145 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: tiff.hh
+ *
+ * MODULE: conversion
+ *
+ * PURPOSE:
+ * Provides interface to convert data between TIFF and internal format.
+ * The convertFrom() and convertTo() methods accept a null-terminated
+ * option string of the following syntax:
+ * optionString ::= ( option )*
+ * option ::= "comptype=" string
+ * "quality=" int
+ * "bpp=" int
+ * "bps=" int
+ * "depth=" int
+ *
+ * CLASSES: r_Conv_TIFF
+ *
+ * COMMENTS:
+ *
+*/
+
+#ifndef _R_CONV_TIFF_HH_
+#define _R_CONV_TIFF_HH_
+
+#include "conversion/convertor.hh"
+
+
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ TIFF convertor class.
+
+ Supported parameters are
+
+ \begin{tabular}{lcl}
+ {\tt comptype} && string && compression type (see below)\\
+ {\tt quality} && int && quality parameter (JPEG)\\
+ {\tt bpp} && int && override number of bits per p (if not set in the tiff)\\
+ {\tt bps} && int && override number of bits per s (if not set in the tiff)\\
+ {\tt depth} && int && override number of colors in the mdd\\
+ \end{tabular}
+
+ The compression type defaults to lzw, but it may be one of the
+ following (but not all types may be supported by the version of
+ the TIFF library; note also that some compression types are only
+ valid for specific colour depths):
+
+ \begin{tabular}{ll}
+ {\tt none}\\
+ {\tt ccittrle}\\
+ {\tt ccittfax3}\\
+ {\tt ccittfax4}\\
+ {\tt lzw}\\
+ {\tt ojpeg}\\
+ {\tt jpeg}\\
+ {\tt next}\\
+ {\tt ccittrlew}\\
+ {\tt packbits}\\
+ {\tt thunderscan}\\
+ {\tt pixarfilm}\\
+ {\tt pixarlog}\\
+ {\tt deflate}\\
+ {\tt dcs}\\
+ {\tt jbig}\\
+ {\tt sgilog} && Not Linux\\
+ {\tt sgilog24} && Not Linux\\
+ {\tt it8ctpad} && Not Linux\\
+ {\tt it8lw} && Not Linux\\
+ {\tt it8mp} && Not Linux\\
+ {\tt it8bl} && Not Linux\\
+ \end{tabular}
+
+ For more information refer to the TIFFlib manual pages.
+ */
+
+class r_Conv_TIFF : public r_Convert_Memory
+{
+ public:
+ /// constructor using an r_Type object
+ r_Conv_TIFF( const char *src, const r_Minterval &interv, const r_Type *tp ) throw(r_Error);
+ /// constructor using convert_type_e shortcut
+ r_Conv_TIFF( const char *src, const r_Minterval &interv, int type ) throw(r_Error);
+ /// destructor
+ ~r_Conv_TIFF( void );
+
+ /// convert to TIFF
+ virtual r_convDesc &convertTo( const char *options=NULL) throw(r_Error);
+ /// convert from TIFF
+ virtual r_convDesc &convertFrom( const char *options=NULL ) throw(r_Error);
+ /// cloning
+ virtual r_Convertor *clone( void ) const;
+ /// identification
+ virtual const char *get_name( void ) const;
+ virtual r_Data_Format get_data_format( void ) const;
+
+ /// translate string compression type to libtiff compression type
+ static int get_compression_from_name(const char* strComp);
+
+ /// translate string resolution unit type to libtiff resolution unit type
+ static int get_resunit_from_name(const char* strComp);
+
+ private:
+ /// init TIFF class
+ void initTIFF( void );
+ /// parameters
+ char *compType;
+ int quality;
+ int override_bpp;
+ int override_bps;
+ int override_depth;
+ /// connection between string compression type and libtiff compression type
+ static const convert_string_t compNames[];
+ /// connection between string resolution unit type and libtiff resolution unit type
+ static const convert_string_t resunitNames[];
+ /// default rows per strip (32)
+ static const int defaultRPS;
+ /// temporary dummy file
+ static const char dummyFileFmt[];
+};
+
+#endif
diff --git a/conversion/tor.cc b/conversion/tor.cc
new file mode 100644
index 0000000..0663fd4
--- /dev/null
+++ b/conversion/tor.cc
@@ -0,0 +1,230 @@
+/*
+* 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>.
+*/
+
+#include "conversion/tor.hh"
+#include "raslib/endian.hh"
+#include "raslib/rminit.hh"
+#include "raslib/parseparams.hh"
+#include "raslib/primitivetype.hh"
+
+void r_Conv_TOR::initTOR()
+{
+ if(params ==NULL)
+ {
+ params = new r_Parse_Params(3);
+ }
+}
+
+r_Conv_TOR::r_Conv_TOR(const char* source, const r_Minterval& lengthordomain, const r_Type* tp) throw(r_Error)
+ : r_Convertor(source, lengthordomain, tp, true)
+ {
+ initTOR();
+ }
+
+r_Conv_TOR::r_Conv_TOR(const char* source, const r_Minterval& lengthordomain, int tp) throw(r_Error)
+ : r_Convertor(source, lengthordomain, tp)
+ {
+ initTOR();
+ }
+
+r_convDesc&
+r_Conv_TOR::convertFrom(const char* options) throw (r_Error)
+ {
+ int swap = 0;
+ int rescale = 0;
+ char* domain = NULL;
+ params->add("swapendianness", &swap, r_Parse_Params::param_type_int);
+ params->add("rescale", &rescale, r_Parse_Params::param_type_int);
+ params->add("domain", &domain, r_Parse_Params::param_type_string);
+ params->process(options);
+ r_Minterval t;
+ RMInit::logOut << "r_Conv_TOR::convert swap " << swap << " rescale " << rescale << " domain " << (domain?domain:"NULL") << std::endl;
+ if (domain == NULL)
+ {
+ RMInit::logOut << "r_Conv_TOR::convertFrom no domain specified in options string" << std::endl;
+ throw r_Error();
+ }
+ try {
+ t = r_Minterval(domain);
+ }
+ catch (r_Eno_interval& e)
+ {
+ RMInit::logOut << "r_Conv_TOR::convertFrom no correct domain specified in options string" << std::endl;
+ throw r_Error();
+ }
+ if (t.dimension() != 2)
+ {
+ RMInit::logOut << "r_Conv_TOR::convertFrom domain in options string must have 2 dimensions" << std::endl;
+ throw r_Error();
+ }
+ r_Range x = t[0].high() - t[0].low() + 1;
+ r_Range y = t[1].high() - t[1].low() + 1;
+ r_UShort* array = (r_UShort*)mystore.storage_alloc(x * y * sizeof(r_UShort));
+ double max = 0;
+ double min = 0;
+ r_Char tc;
+ double maxu = 0;
+ double minu = 0;
+ r_UShort tu;
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ case ctype_char:
+ case ctype_uint8:
+ if (desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1 != t.cell_count() * sizeof(r_Char))
+ {
+ RMInit::logOut << "r_Conv_TOR::convertFrom the supplied data is " << desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1 << " bytes, but " << t.cell_count() << " bytes were expected" << std::endl;
+ throw r_Error();
+ }
+ get_limits(&tc, min, max);
+ get_limits(&tu, minu, maxu);
+ for(int i=0; i < x; i++)
+ {
+ for(int j=0; j < y; j++)
+ {
+ if (rescale)
+ array[i * x + j] = ((r_Octet*)desc.src)[j * x + i] / max * maxu;
+ else
+ array[i * x + j] = ((r_Octet*)desc.src)[j * x + i];
+ }
+ }
+ break;
+ case ctype_uint16:
+ if (desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1 != t.cell_count() * sizeof(r_UShort))
+ {
+ RMInit::logOut << "r_Conv_TOR::convertFrom the supplied data is " << desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1 << " bytes, but " << t.cell_count() << " bytes were expected" << std::endl;
+ throw r_Error();
+ }
+ for(int i=0; i < x; i++)
+ {
+ for(int j=0; j < y; j++)
+ {
+ array[i * x + j] = ((r_UShort*)desc.src)[j * x + i];
+ }
+ }
+ break;
+ default:
+ RMInit::logOut << "r_Conv_TOR unknown base type!" << std::endl;
+ throw r_Error();
+ }
+ if (swap)
+ {
+ r_UShort* temp = (r_UShort*)mystore.storage_alloc(x * y * sizeof(r_UShort));
+ r_Endian::swap_array(x * y * sizeof(r_UShort), array, temp);
+ mystore.storage_free(array);
+ array = temp;
+ }
+
+ desc.dest = (char*)array;
+ desc.destInterv = t;
+ desc.destType = new r_Primitive_Type("UShort", r_Type::USHORT);
+ return desc;
+ }
+
+r_convDesc&
+r_Conv_TOR::convertTo(const char* options) throw (r_Error)
+ {
+ int swap = 0;
+ int rescale = 0;
+ params->add("swapendianness", &swap, r_Parse_Params::param_type_int);
+ params->add("rescale", &rescale, r_Parse_Params::param_type_int);
+ params->process(options);
+ if (desc.srcInterv.dimension() != 2)
+ {
+ RMInit::logOut << "r_Conv_TOR::convertFrom domain in options string must have 2 dimensions" << std::endl;
+ throw r_Error();
+ }
+ r_Range x = desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1;
+ r_Range y = desc.srcInterv[1].high() - desc.srcInterv[1].low() + 1;
+ r_UShort* array = (r_UShort*)mystore.storage_alloc(x * y * sizeof(r_UShort));
+ double max = 0;
+ double min = 0;
+ r_Char tc;
+ double maxu = 0;
+ double minu = 0;
+ r_UShort tu;
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ case ctype_char:
+ case ctype_uint8:
+ get_limits(&tc, min, max);
+ get_limits(&tu, minu, maxu);
+ for(int i=0; i < x; i++)
+ {
+ for(int j=0; j < y; j++)
+ {
+ if (rescale)
+ array[i * x + j] = ((r_Octet*)desc.src)[j * x + i] / max * maxu;
+ else
+ array[i * x + j] = ((r_Octet*)desc.src)[j * x + i];
+ }
+ }
+ break;
+ case ctype_uint16:
+ for(int i=0; i < x; i++)
+ {
+ for(int j=0; j < y; j++)
+ {
+ array[i * x + j] = ((r_UShort*)desc.src)[j * x + i];
+ }
+ }
+ break;
+ default:
+ RMInit::logOut << "r_Conv_TOR unknown base type!" << std::endl;
+ throw r_Error();
+ }
+ if (swap)
+ {
+ r_UShort* temp =(r_UShort*)mystore.storage_alloc(x * y * sizeof(r_UShort));
+ r_Endian::swap_array(x * y * sizeof(r_UShort), array, temp);
+ mystore.storage_free(array);
+ array = temp;
+ }
+
+ desc.dest = (char*)array;
+ r_Minterval td(1);
+ td << r_Sinterval((r_Range)0, (r_Range)(desc.srcInterv.cell_count() * sizeof(r_UShort) - 1));
+ desc.destInterv = td;
+ desc.destType = new r_Primitive_Type("Char", r_Type::CHAR);
+ return desc;
+ }
+
+const char*
+r_Conv_TOR::get_name() const
+ {
+ return get_name_from_data_format(r_TOR);
+ }
+
+r_Data_Format
+r_Conv_TOR::get_data_format() const
+ {
+ return r_TOR;
+ }
+
+r_Convertor*
+r_Conv_TOR::clone() const
+ {
+ return new r_Conv_TOR(desc.src, desc.srcInterv, desc.srcType);
+ }
+
diff --git a/conversion/tor.hh b/conversion/tor.hh
new file mode 100644
index 0000000..d7bd189
--- /dev/null
+++ b/conversion/tor.hh
@@ -0,0 +1,82 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: tor.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_TOR
+ *
+ * COMMENTS:
+ *
+ * Provides interface to convert data from/to TOR to/from r_Array
+ *
+*/
+
+#ifndef _R_CONV_TOR_HH_
+#define _R_CONV_TOR_HH_
+#include "conversion/convertor.hh"
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ TOR convertor class.
+
+ Supported parameters are
+
+ \begin{tabular}{lcl}
+ {\tt swapendianness} && int && flag for swapendianness, default 0\\
+ {\tt rescale} && int && flag for rescale, default 0\\
+ {\tt domain} && string && domain string of TOR file\\
+ \end{tabular}
+
+ The "swapendianness" parameter is a flag for endianness change operation.
+ The "rescale" parameter is a flag for rescale operation.
+*/
+
+
+class r_Conv_TOR : public r_Convertor
+ {
+ public:
+ r_Conv_TOR(const char* source, const r_Minterval& lengthordomain, const r_Type* tp) throw(r_Error);
+
+ r_Conv_TOR(const char* source, const r_Minterval& lengthordomain, int tp) throw(r_Error);
+
+ r_convDesc& convertFrom(const char* options = NULL) throw (r_Error);
+
+ r_convDesc& convertTo(const char* options = NULL) throw (r_Error);
+
+ const char* get_name() const;
+
+ r_Data_Format get_data_format() const;
+
+ r_Convertor* clone() const;
+
+
+ private:
+ void initTOR();
+
+ };
+
+#endif
+
diff --git a/conversion/utilities.cc b/conversion/utilities.cc
new file mode 100644
index 0000000..7b8df84
--- /dev/null
+++ b/conversion/utilities.cc
@@ -0,0 +1,109 @@
+/*
+* 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>.
+*/
+
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <sys/types.h>
+#include <unistd.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "utilities.h"
+
+using namespace std;
+using namespace RasNITF;
+
+long RasNITF::read_verify(std::istream &fNITF, char *destination, long length, char *sErrorMessage, bool nullify)
+
+{
+ long rc;
+
+ fNITF.read(destination, length);
+ rc = fNITF.gcount();
+
+ if (!fNITF.good()){
+ cout<<sErrorMessage<<endl;
+ exit(1);
+ }
+
+ if (rc != length) {
+ cout<<sErrorMessage<<endl;
+ exit(1);
+ }
+
+ if (nullify)
+ destination[length] = '\0';
+
+ return rc;
+}
+
+long RasNITF::read_verify2(std::istream &fNITF, char *destination, long length)
+
+{
+ long rc;
+
+ fNITF.read(destination, length);
+ rc = fNITF.gcount();
+
+ if (!fNITF.good()){
+ exit(3);
+ }
+
+ if (rc != length) {
+ exit(4);
+ }
+
+ return rc;
+}
+
+
+int RasNITF::charptrtoint(const char *str, int length){
+
+ int num;
+ string temp;
+
+ if (length > 5) {
+
+ cout << "WARNING LOSING DATA from long to int conversion" << endl;
+
+ }
+
+
+ temp.assign(str, length);
+ num = atoi(temp.c_str());
+
+ return num;
+}
+
+long RasNITF::charptrtolong(const char *str, int length){
+
+ long num;
+ string temp;
+
+ temp.assign(str, length);
+ num = atol(temp.c_str());
+
+ return num;
+}
diff --git a/conversion/utilities.h b/conversion/utilities.h
new file mode 100644
index 0000000..3b74a38
--- /dev/null
+++ b/conversion/utilities.h
@@ -0,0 +1,35 @@
+/*
+* 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>.
+*/
+
+#ifndef __UTILITIES_H_INCLUDED
+#define __UTILITIES_H_INCLUDED
+
+namespace RasNITF {
+
+ long read_verify(std::istream &fNITF, char *destination, long length, char *sErrorMessage, bool nullify);
+ long read_verify2(std::istream &fNITF, char *destination, long length);
+ int charptrtoint(const char *str, int length);
+ long charptrtolong(const char *str, int length);
+
+}
+#endif
diff --git a/conversion/vff.cc b/conversion/vff.cc
new file mode 100644
index 0000000..25b58f7
--- /dev/null
+++ b/conversion/vff.cc
@@ -0,0 +1,797 @@
+/*
+* 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>.
+/
+/**
+ * FILE: vff.cc
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_VFF
+ *
+ * COMMENTS:
+ *
+ * Provides interface to convert data to VFF and back.
+ *
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <iostream>
+#include <strstream>
+
+#include "raslib/rminit.hh"
+#include "raslib/endian.hh"
+#include "raslib/miterd.hh"
+#include "raslib/odmgtypes.hh"
+#include "raslib/parseparams.hh"
+#include "conversion/vff.hh"
+
+
+// file magic
+const char *r_Conv_VFF::fileMagic = "ncaa";
+
+// keyword enumerators, must be kept in sync with keywords
+enum vff_keyword_e {
+ vffkey_rank = 0,
+ vffkey_type,
+ vffkey_format,
+ vffkey_size,
+ vffkey_origin,
+ vffkey_extent,
+ vffkey_aspect,
+ vffkey_bands,
+ vffkey_bits,
+ vffkey_value,
+ vffkey_endian,
+ vffkey_dorder,
+ vffkey_NUMBER
+};
+
+// Keywords
+const char *r_Conv_VFF::keywords[] = {
+ // mandatory
+ "rank",
+ "type",
+ "format",
+ "size",
+ "origin",
+ "extent",
+ "aspect",
+ "bands",
+ "bits",
+ // optional
+ "value",
+ "endianness",
+ "data_order"
+};
+
+// values
+const char *r_Conv_VFF::kval_Raster = "raster";
+const char *r_Conv_VFF::kval_Slice = "slice";
+const char *r_Conv_VFF::kval_LEndian = "little_endian";
+const char *r_Conv_VFF::kval_BEndian = "big_endian";
+
+// default data order
+const char *r_Conv_VFF::dfltDataOrder2 = "xy";
+const char *r_Conv_VFF::dfltDataOrder3 = "yzx";
+
+// default dimension order
+const char *r_Conv_VFF::dfltDimOrder2 = "xy";
+const char *r_Conv_VFF::dfltDimOrder3 = "yzx";
+
+// end of header
+const char r_Conv_VFF::endOfHeader = 0x0c;
+
+// method names
+const char *r_Conv_VFF::method_convTo = "r_Conv_VFF::convertTo()";
+const char *r_Conv_VFF::method_convFrom = "r_Conv_VFF::convertFrom()";
+
+
+r_Conv_VFF::r_Conv_VFF( const char *src, const r_Minterval &interv, int tp ) throw(r_Error)
+: r_Convertor(src, interv, tp)
+{
+ initVFF();
+}
+
+
+r_Conv_VFF::r_Conv_VFF( const char *src, const r_Minterval &interv, const r_Type *tp ) throw(r_Error)
+: r_Convertor(src, interv, tp, true)
+{
+ initVFF();
+}
+
+
+r_Conv_VFF::~r_Conv_VFF( void )
+{
+ if (dorderParam != NULL)
+ delete [] dorderParam;
+ if (dimOrderParam != NULL)
+ delete [] dimOrderParam;
+}
+
+
+void r_Conv_VFF::initVFF( void )
+{
+ dorderParam = NULL;
+ dimOrderParam = NULL;
+ dfltEndianness = 0; // big endian
+
+ if (params == NULL)
+ params = new r_Parse_Params;
+
+ params->add("dorder", &dorderParam, r_Parse_Params::param_type_string);
+ params->add("dimorder", &dimOrderParam, r_Parse_Params::param_type_string);
+ params->add("vffendian", &dfltEndianness, r_Parse_Params::param_type_int);
+}
+
+
+void r_Conv_VFF::skip_white( const char *&str )
+{
+ while ((*str != endOfHeader) && (isspace((unsigned int)(*str)))) str++;
+}
+
+void r_Conv_VFF::write_interval( const char *keyname, std::ostream &str, const r_Minterval &iv, const unsigned int *order, r_Range inc )
+{
+ r_Dimension i;
+ str << keyname << '=' << (iv[order[0]].high() - iv[order[0]].low() + inc);
+ for (i=1; i<iv.dimension(); i++)
+ str << ' ' << (iv[order[i]].high() - iv[order[i]].low() + inc);
+ str << ";\n";
+}
+
+void r_Conv_VFF::write_origin( const char *keyname, std::ostream &str, const r_Minterval &iv, const unsigned int *order )
+{
+ r_Dimension i;
+ str << keyname << '=' << iv[order[0]].low();
+ for (i=1; i<iv.dimension(); i++)
+ str << ' ' << iv[order[i]].low();
+ str << ";\n";
+}
+
+const char *r_Conv_VFF::read_vector( r_Dimension dim, const char *str, double *&vec )
+{
+ if (dim == 0)
+ return NULL;
+
+ vec = new double[dim];
+ r_Dimension i;
+
+ for (i=0; i<dim; i++)
+ {
+ const char *rest;
+ vec[i] = strtod(str, (char**)&rest);
+ if (str == rest)
+ break;
+ str = rest;
+ }
+ if (i < dim)
+ {
+ delete [] vec;
+ vec = NULL;
+ return NULL;
+ }
+ return str;
+}
+
+const char *r_Conv_VFF::read_string( const char *str, char *dest, bool allowSpace )
+{
+ const char *d = str;
+ char *b = dest;
+
+ while (*d != ';')
+ {
+ if ((allowSpace == 1) && (isspace((unsigned int)(*d))))
+ break;
+ *b++ = *d++;
+ }
+ *b++ = '\0';
+ return d;
+}
+
+const char *r_Conv_VFF::get_endian_id( void )
+{
+ return ((r_Endian::get_endianness() == r_Endian::r_Endian_Big) ? kval_BEndian : kval_LEndian);
+}
+
+
+const char *r_Conv_VFF::get_default_order( r_Dimension dim )
+{
+ return (dim == 2) ? dfltDataOrder2 : dfltDataOrder3;
+}
+
+
+const char *r_Conv_VFF::get_default_dim_order( r_Dimension dim )
+{
+ return (dim == 2) ? dfltDimOrder2 : dfltDimOrder3;
+}
+
+
+int r_Conv_VFF::parse_data_order( r_Dimension dim, const char *dstr, unsigned int *order )
+{
+ unsigned char *mapped = new unsigned char[dim];
+ unsigned int i;
+
+ memset(mapped, 0, dim);
+ for (i=0; i<dim; i++)
+ {
+ unsigned int map;
+
+ switch (dstr[i])
+ {
+ case 'x':
+ map = 1; break;
+ case 'y':
+ map = 2; break;
+ case 'z':
+ map = 3; break;
+ default:
+ map = 0; break;
+ }
+
+ if ((map == 0) || (mapped[map-1] != 0))
+ break;
+
+ order[i] = map-1;
+ mapped[map-1] = 1;
+ //cout << order[i] << endl;
+ }
+
+ delete [] mapped;
+
+ if (i < dim)
+ {
+ RMInit::logOut << "r_Conv_VFF::parse_data_order(): descriptor " << dstr
+ << " inconsistent, revert to defaults" << endl;
+
+ return parse_data_order(dim, get_default_order(dim), order);
+ }
+
+ return 0;
+}
+
+
+unsigned int *r_Conv_VFF::get_dimension_order( r_Dimension dim ) const
+{
+ unsigned int *order = new unsigned int[dim];
+ char dimOrder[8];
+
+ // Anders Ledberg: Karolinska reader _always_ uses yzx as dimension order
+ if (dimOrderParam == NULL)
+ strncpy(dimOrder, get_default_dim_order(dim), 8);
+ else
+ strncpy(dimOrder, dimOrderParam, 8);
+
+ dimOrder[7] = '\0';
+ parse_data_order(dim, dimOrder, order);
+
+ return order;
+}
+
+
+const char *r_Conv_VFF::get_default_endianness( void ) const
+{
+ return (dfltEndianness == 0) ? kval_BEndian : kval_LEndian;
+}
+
+
+r_convDesc &r_Conv_VFF::convertTo( const char *options ) throw(r_Error)
+{
+ r_Dimension dim;
+ int bits, typeSize;
+ char header[1024]; // and ``640k should be enough for everyone''...
+ char dataOrder[8];
+
+ dim = desc.srcInterv.dimension();
+ if ((dim < 2) || (dim > 3))
+ {
+ r_Error err(r_Error::r_Error_General);
+ throw(err);
+ }
+
+ switch (desc.baseType)
+ {
+ case ctype_bool:
+ case ctype_char:
+ case ctype_int8:
+ case ctype_uint8:
+ bits = 8; typeSize = 1; break;
+ case ctype_int16:
+ case ctype_uint16:
+ bits = 16; typeSize = 2; break;
+ case ctype_int32:
+ case ctype_uint32:
+ bits = 32; typeSize = 4; break;
+ default:
+ r_Error err(r_Error::r_Error_General);
+ throw(err);
+ break;
+ }
+ //cout << "TYPE " << desc.baseType << ", SIZE " << typeSize << endl;
+
+ if (options != NULL)
+ params->process(options);
+
+ if (dorderParam != NULL)
+ strcpy(dataOrder, dorderParam);
+ else
+ strcpy(dataOrder, get_default_order(dim));
+
+ std::ostrstream memstr(header, 1024);
+
+ // order of dimensions in vectors
+ unsigned int *dimOrder = get_dimension_order(dim);
+
+ // write header
+ memstr << fileMagic << '\n';
+ memstr << keywords[vffkey_rank] << '=' << dim << ";\n";
+ memstr << keywords[vffkey_type] << '=' << kval_Raster << ";\n";
+ memstr << keywords[vffkey_format] << '=' << kval_Slice << ";\n";
+ // the dimensions are still ordered like in the VFF file, only the internal
+ // linearization differs!
+ write_interval(keywords[vffkey_size], memstr, desc.srcInterv, dimOrder, 1);
+ write_origin(keywords[vffkey_origin], memstr, desc.srcInterv, dimOrder);
+ write_interval(keywords[vffkey_extent], memstr, desc.srcInterv, dimOrder);
+ if (dim == 2)
+ {
+ // FIXME, aspect should be modelled too
+ memstr << keywords[vffkey_aspect] << "=1.0 1.0;\n";
+ }
+ else
+ {
+ // FIXME, ditto
+ memstr << keywords[vffkey_aspect] << "=1.0 1.0 1.0;\n";
+ }
+
+ // only suypport one band ATM
+ memstr << keywords[vffkey_bands] << "=1;\n";
+ memstr << keywords[vffkey_bits] << '=' << bits << ";\n";
+ memstr << keywords[vffkey_endian] << '=' << get_endian_id() << ";\n";
+ memstr << keywords[vffkey_dorder] << '=' << dataOrder << ";\n";
+ memstr << '\n' << endOfHeader << '\n' << '\0';
+
+ unsigned long headerSize, dataSize, totalSize;
+
+ headerSize = strlen(header);
+ dataSize = desc.srcInterv.cell_count() * typeSize;
+ totalSize = headerSize + dataSize;
+
+ if ((desc.dest = (char*)mystore.storage_alloc(headerSize + dataSize)) == NULL)
+ {
+ r_Error err(r_Error::r_Error_General);
+ throw(err);
+ }
+ memcpy(desc.dest, header, headerSize);
+
+ // treat all dimensions alike thanks to generic iterators
+
+ // source iterator, iterate in user order
+ r_MiterDirect iter((void*)desc.src, desc.srcInterv, desc.srcInterv, typeSize, 1);
+ unsigned int *order, *steps;
+
+ order = new unsigned int[dim];
+ steps = new unsigned int[dim];
+
+ for (unsigned int i=0; i<dim; i++)
+ steps[i] = 1;
+
+ parse_data_order(dim, dataOrder, order);
+
+ // note: dest may not be aligned to a position conforming to its base type,
+ // so copy byte-wise.
+ unsigned char *dptr = (unsigned char*)(desc.dest + headerSize);
+ switch (typeSize)
+ {
+ case 1:
+ {
+ while (iter.isDone() == 0)
+ {
+ *dptr = *((const unsigned char*)iter.getData(order));
+ iter.iterateUserOrder(order, steps);
+ dptr++;
+ }
+ }
+ break;
+ case 2:
+ {
+ while (iter.isDone() == 0)
+ {
+ const unsigned char *sptr = (const unsigned char*)iter.getData(order);
+ dptr[0] = sptr[0];
+ dptr[1] = sptr[1];
+ //cout << iter << ':' << (long)((const char*)sptr-desc.src) << ':' << (unsigned short)((sptr[0] << 8) | (sptr[1])) << ' ';
+ iter.iterateUserOrder(order, steps);
+ dptr+=2;
+ }
+ }
+ break;
+ case 4:
+ {
+ while (iter.isDone() == 0)
+ {
+ const unsigned char *sptr = (const unsigned char*)iter.getData(order);
+ dptr[0] = sptr[0];
+ dptr[1] = sptr[1];
+ dptr[2] = sptr[2];
+ dptr[3] = sptr[3];
+ iter.iterateUserOrder(order, steps);
+ dptr+=4;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ delete [] steps;
+ delete [] order;
+ delete [] dimOrder;
+
+ desc.destInterv = r_Minterval(1);
+ desc.destInterv << r_Sinterval((r_Range)0, (r_Range)totalSize-1);
+ desc.destType = r_Type::get_any_type("char");
+
+ return desc;
+}
+
+
+r_convDesc &r_Conv_VFF::convertFrom( const char *options ) throw(r_Error)
+{
+ const char *header = desc.src;
+ unsigned char *keysRead;
+ unsigned int i;
+ r_Dimension dim=0;
+ int bits, bands;
+ double *vecSize, *vecOrigin, *vecValue;
+ char endian[32];
+ char dataOrder[8];
+
+ if (strncmp(header, fileMagic, strlen(fileMagic)) != 0)
+ {
+ r_Error err(r_Error::r_Error_General);
+ throw(err);
+ }
+
+ keysRead = new unsigned char[vffkey_NUMBER];
+ memset(keysRead, 0, vffkey_NUMBER);
+
+ header += strlen(fileMagic);
+ skip_white(header);
+
+ vecSize = NULL;
+ vecOrigin = NULL;
+ vecValue = NULL;
+
+ strcpy(endian, get_default_endianness());
+
+ if (options != NULL)
+ params->process(options);
+
+ // no order -- check later if one was defined and init it _after_ we know the rank
+ dataOrder[0] = '\0';
+
+ do
+ {
+ if (*header != endOfHeader);
+ {
+ const char *rest;
+ double *vecTemp;
+
+ for (i=0; i<(unsigned int)vffkey_NUMBER; i++)
+ {
+ if (strncmp(header, keywords[i], strlen(keywords[i])) == 0)
+ break;
+ }
+
+ if (i == vffkey_NUMBER)
+ {
+ // skip unknown keywords
+ while ((*header != ';') && (*header != endOfHeader))
+ header++;
+ if (*header == ';')
+ header++;
+ }
+ else
+ {
+ //cout << "KEY " << keywords[i] << endl;
+
+ keysRead[i] = 1;
+
+ header += strlen(keywords[i]);
+ skip_white(header);
+
+ if (*header != '=')
+ break;
+
+ header++;
+ skip_white(header);
+
+ rest = header;
+ switch ((vff_keyword_e)i)
+ {
+ case vffkey_rank:
+ dim = strtol(header, (char**)&rest, 10);
+ if ((rest == header) || (dim < 2) || (dim > 3))
+ {
+ RMInit::logOut << method_convFrom << ": bad rank " << dim << endl;
+ rest = NULL;
+ }
+ break;
+ case vffkey_type:
+ if (strncmp(header, kval_Raster, strlen(kval_Raster)) == 0)
+ rest = header + strlen(kval_Raster);
+ else
+ {
+ RMInit::logOut << method_convFrom << ": bad type" << endl;
+ rest = NULL;
+ }
+ break;
+ case vffkey_format:
+ if (strncmp(header, kval_Slice, strlen(kval_Slice)) == 0)
+ rest = header + strlen(kval_Slice);
+ else
+ {
+ RMInit::logOut << method_convFrom << ": bad format" << endl;
+ rest = NULL;
+ }
+ break;
+ case vffkey_size:
+ rest = read_vector(dim, header, vecSize);
+ break;
+ case vffkey_origin:
+ rest = read_vector(dim, header, vecOrigin);
+ break;
+ case vffkey_extent:
+ // extent just parsed, otherwise ignored
+ rest = read_vector(dim, header, vecTemp);
+ delete [] vecTemp;
+ break;
+ case vffkey_aspect:
+ // FIXME: aspect ignored
+ rest = read_vector(dim, header, vecTemp);
+ delete [] vecTemp;
+ break;
+ case vffkey_bands:
+ bands = strtol(header, (char**)&rest, 10);
+ if ((rest == header) || (bands != 1))
+ {
+ RMInit::logOut << method_convFrom << ": bad number of bands " << bands << endl;
+ rest = NULL;
+ }
+ break;
+ case vffkey_bits:
+ bits = strtol(header, (char**)&rest, 10);
+ if ((rest == header) || ((bits != 8) && (bits != 16) && (bits != 32)))
+ {
+ RMInit::logOut << method_convFrom << ": bad number of bits " << bits << endl;
+ rest = NULL;
+ }
+ break;
+ case vffkey_value:
+ // FIXME: values ignored
+ rest = read_vector(2, header, vecValue);
+ break;
+ case vffkey_endian:
+ rest = read_string(header, endian);
+ break;
+ case vffkey_dorder:
+ rest = read_string(header, dataOrder);
+ break;
+ default:
+ break;
+ }
+ if (rest == NULL)
+ break;
+
+ header = rest;
+ skip_white(header);
+ if (*header == ';')
+ header++;
+ }
+ }
+ skip_white(header);
+ }
+ while (*header != endOfHeader);
+
+ // was there a data order? no ==> init either used-defined or default
+ if (dataOrder[0] == '\0')
+ {
+ if (dorderParam != NULL)
+ strcpy(dataOrder, dorderParam);
+ else
+ strcpy(dataOrder, get_default_order(dim));
+ }
+
+ //cout << "RANK " << dim << ", BANDS " << bands << ", BITS " << bits << endl;
+
+ // check whether all mandatory keywords are present
+ for (i=0; i<(unsigned int)vffkey_value; i++)
+ {
+ if (keysRead[i] == 0)
+ {
+ header = NULL;
+ break;
+ }
+ }
+
+ if ((header == NULL) || (*header != endOfHeader))
+ {
+ // parse error
+ RMInit::logOut << method_convFrom << ": PARSE ERROR" << endl;
+
+ delete [] keysRead;
+
+ if (vecSize != NULL)
+ delete [] vecSize;
+ if (vecOrigin != NULL)
+ delete [] vecOrigin;
+ if (vecValue != NULL)
+ delete [] vecValue;
+
+ r_Error err(r_Error::r_Error_General);
+ throw(err);
+ }
+
+ // after this instruction, header points to the linefeed
+ header++;
+ // after this instruction, header points to the data
+ header++;
+
+ desc.destInterv = r_Minterval(dim);
+
+ // order of dimensions in vectors
+ unsigned int *dimOrder = get_dimension_order(dim);
+
+ // the order of the dimensions is the same, only the linearization differs
+ for (i=0; i<dim; i++)
+ {
+ // the old method didn't work for high<0 (wrong rounding direction)
+ r_Range low, width;
+ low = (r_Range)(vecOrigin[i]);
+ width = (r_Range)(vecSize[i]);
+ //cout << "SIZE " << dimOrder[i] << ": " << width << ", ORG " << low << endl;
+ desc.destInterv[dimOrder[i]] = r_Sinterval(low, low+width-1);
+ }
+ //cout << desc.destInterv << endl;
+
+ delete [] vecOrigin;
+ delete [] vecSize;
+
+ int typeSize = (bits>>3);
+ unsigned long dataSize = desc.destInterv.cell_count() * typeSize;
+ //cout << "Type size " << typeSize << ", dim " << dim << endl;
+
+ if ((desc.dest = (char*)mystore.storage_alloc(dataSize)) == NULL)
+ {
+ delete [] keysRead;
+
+ if (vecValue != NULL)
+ delete [] vecValue;
+
+ r_Error err(r_Error::r_Error_General);
+ throw(err);
+ }
+
+ // treat all dimensions alike
+
+ // must copy byte-by-byte because the source data may not be aligned!
+ r_MiterDirect iter(desc.dest, desc.destInterv, desc.destInterv, typeSize, 1);
+ unsigned int *order, *steps;
+ const unsigned char *sptr = (const unsigned char *)header;
+
+ order = new unsigned int[dim];
+ steps = new unsigned int[dim];
+
+ for (i=0; i<dim; i++)
+ steps[i] = 1;
+
+ parse_data_order(dim, dataOrder, order);
+
+ switch (typeSize)
+ {
+ case 1:
+ while (iter.isDone() == 0)
+ {
+ *((r_Char*)iter.getData(order)) = *sptr;
+ iter.iterateUserOrder(order, steps);
+ sptr++;
+ }
+ break;
+ case 2:
+ while (iter.isDone() == 0)
+ {
+ unsigned char *dptr = (unsigned char*)iter.getData(order);
+ dptr[0] = sptr[0];
+ dptr[1] = sptr[1];
+ //cout << iter << ':' << (long)((char*)dptr - desc.dest) << ':' << (long)((char*)sptr - header) << ':' << (unsigned short)((sptr[0] << 8) | sptr[1]) << ' ';
+ iter.iterateUserOrder(order, steps);
+ sptr+=2;
+ }
+ break;
+ case 4:
+ while (iter.isDone() == 0)
+ {
+ unsigned char *dptr = (unsigned char*)iter.getData(order);
+ dptr[0] = sptr[0];
+ dptr[1] = sptr[1];
+ dptr[2] = sptr[2];
+ dptr[3] = sptr[3];
+ iter.iterateUserOrder(order, steps);
+ sptr+=4;
+ }
+ break;
+ default:
+ break;
+ }
+
+ delete [] order;
+ delete [] steps;
+ delete [] dimOrder;
+
+ switch (typeSize)
+ {
+ case 1:
+ desc.destType = get_external_type(ctype_char);
+ break;
+ case 2:
+ desc.destType = get_external_type(ctype_uint16);
+ if (strcmp(endian, get_endian_id()) != 0)
+ r_Endian::swap_array(dataSize, (const r_UShort*)desc.dest, (r_UShort*)desc.dest);
+ break;
+ case 4:
+ desc.destType = get_external_type(ctype_uint32);
+ if (strcmp(endian, get_endian_id()) != 0)
+ r_Endian::swap_array(dataSize, (const r_ULong*)desc.dest, (r_ULong*)desc.dest);
+ break;
+ default:
+ break;
+ }
+
+ //desc.destType->print_status();
+
+ if (vecValue != NULL)
+ delete [] vecValue;
+
+ delete [] keysRead;
+
+ return desc;
+}
+
+
+const char *r_Conv_VFF::get_name( void ) const
+{
+ return format_name_vff;
+}
+
+
+r_Data_Format r_Conv_VFF::get_data_format( void ) const
+{
+ return r_VFF;
+}
+
+
+r_Convertor *r_Conv_VFF::clone( void ) const
+{
+ return new r_Conv_VFF(desc.src, desc.srcInterv, desc.baseType);
+}
diff --git a/conversion/vff.hh b/conversion/vff.hh
new file mode 100644
index 0000000..f1829b5
--- /dev/null
+++ b/conversion/vff.hh
@@ -0,0 +1,138 @@
+/*
+* 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>.
+/
+/**
+ * FILE: vff.hh
+ *
+ * MODULE: conversion
+ *
+ * CLASSES: r_Conv_VFF
+ *
+ * COMMENTS:
+ *
+ * Provides interface to convert data to VFF and back.
+ *
+*/
+
+#ifndef _R_CONV_VFF_HH_
+#define _R_CONV_VFF_HH_
+
+#include "conversion/convertor.hh"
+
+
+
+//@ManMemo: Module {\bf conversion}
+
+/*@Doc:
+ VFF convertor class.
+
+ Supported parameters are
+
+ \begin{tabular}{rcl}
+ dorder && string && data order to read/write in 3D mode; permutations of "xyz"\\
+ dimorder && string && dimension order for vectors (size, origin, ...)\\
+ vffendian && int && default endianness, 0 for big endian, 1 for little\\
+ \end{tabular}
+
+*/
+
+class r_Conv_VFF : public r_Convertor
+{
+ public:
+ /// constructor using an r_Type object
+ r_Conv_VFF( const char *src, const r_Minterval &interv, const r_Type *tp ) throw(r_Error);
+ /// constructor using a convert_type_e shortcut
+ r_Conv_VFF( const char *src, const r_Minterval &interv, int tp ) throw(r_Error);
+ /// destructor
+ ~r_Conv_VFF( void );
+
+ /// convert to VFF
+ virtual r_convDesc &convertTo( const char *options=NULL ) throw(r_Error);
+ /// convert from VFF
+ virtual r_convDesc &convertFrom( const char *options=NULL ) throw(r_Error);
+ /// cloning
+ virtual r_Convertor *clone( void ) const;
+ /// identification
+ virtual const char *get_name( void ) const;
+ virtual r_Data_Format get_data_format( void ) const;
+
+
+ private:
+ /// shared init code
+ void initVFF( void );
+ /// skip whitespace when parsing the header
+ static void skip_white( const char *&str );
+ /// read a floating point vector from the header and return pointer to rest
+ static const char *read_vector( r_Dimension dim, const char *str, double *&vec );
+ /// read a string from the header and return pointer to rest
+ static const char *read_string( const char *str, char *dest, bool allowSpace=0 );
+ /// write an interval to a stream
+ static void write_interval( const char *keyname, std::ostream &str, const r_Minterval &iv,
+ const unsigned int *order, r_Range inc=0 );
+ /// write an origin to a stream
+ static void write_origin( const char *keyname, std::ostream &str, const r_Minterval &iv,
+ const unsigned int *order );
+ /// get the VFF-endian id for the host machine's
+ static const char *get_endian_id( void );
+ /// parse data order string, revert to default if failed
+ static int parse_data_order( r_Dimension dim, const char *dstr, unsigned int *order );
+ /// get default data order for a dimensionality
+ static const char *get_default_order( r_Dimension dim );
+ /// get default dimension order for a dimensionality
+ static const char *get_default_dim_order( r_Dimension dim );
+
+ /// get dimension order in newly allocated array
+ unsigned int *get_dimension_order( r_Dimension dim ) const;
+ /// get the default endianness
+ const char *get_default_endianness( void ) const;
+
+ /// data order parameter
+ char *dorderParam;
+ /// dimension order parameter
+ char *dimOrderParam;
+ /// default endianness parameter
+ int dfltEndianness;
+
+ /// identifier (ncaa) in header
+ static const char *fileMagic;
+ /// keyword names
+ static const char *keywords[];
+ /// special key values
+ static const char *kval_Raster;
+ static const char *kval_Slice;
+ static const char *kval_LEndian;
+ static const char *kval_BEndian;
+ /// default data order for 2D/3D
+ static const char *dfltDataOrder2;
+ static const char *dfltDataOrder3;
+ /// default dimension order fo 2D/3D
+ static const char *dfltDimOrder2;
+ static const char *dfltDimOrder3;
+ /// end-of-header marker
+ static const char endOfHeader;
+ /// name of convertTo() method
+ static const char *method_convTo;
+ /// name of convertFrom() method
+ static const char *method_convFrom;
+};
+
+#endif