diff options
Diffstat (limited to 'conversion/hdf.cc')
-rw-r--r-- | conversion/hdf.cc | 386 |
1 files changed, 386 insertions, 0 deletions
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); +} |