diff options
author | Constantin Jucovschi <cj@ubuntu.localdomain> | 2009-04-24 07:20:22 -0400 |
---|---|---|
committer | Constantin Jucovschi <cj@ubuntu.localdomain> | 2009-04-24 07:20:22 -0400 |
commit | 8f27e65bddd7d4b8515ce620fb485fdd78fcdf89 (patch) | |
tree | bd328a4dd4f92d32202241b5e3a7f36177792c5f /applications/rview/rviewMDD.cpp | |
download | rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.gz rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.xz rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.zip |
Initial commitv8.0
Diffstat (limited to 'applications/rview/rviewMDD.cpp')
-rw-r--r-- | applications/rview/rviewMDD.cpp | 1006 |
1 files changed, 1006 insertions, 0 deletions
diff --git a/applications/rview/rviewMDD.cpp b/applications/rview/rviewMDD.cpp new file mode 100644 index 0000000..4f175fc --- /dev/null +++ b/applications/rview/rviewMDD.cpp @@ -0,0 +1,1006 @@ +/* +* 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>. +/ + +/** + * PURPOSE: + * + * The rviewMDD module encapsulates various generic operations on + * MDD objects; it relies heavily on templates for this. All functions + * provided here are a) completely independent from the rest of rView + * and b) work on any kind of MDD, i.e. no restrictions whatsoever on + * dimensionality or base type. Most functions utilize + * mdd_objectFunctionType() for this which iterates over the MDD object + * basetype first and calls functions provided in the mdd_function_pointers + * structure which perform the required operation on each of the primitive + * basetypes. + * + * Functions provided are: + * + * - mdd_objectRange(): return the minimum and maximum cell values. + * - mdd_createSubcube(): creates a new MDD object by copying a subcube + * (or all of) a source MDD object; optionally persistent. + * - mdd_objectScaleInter(): creates new object by resampling (part of) + * the source object using n-linear interpolation. Use for upsampling. + * - mdd_objectScaleAverage(): creates new object by resampling (part of) + * the source object using averaging. Use for downsampling. + * - mdd_objectScaleSimple(): creates new object by scaling (part of) + * the source object using simple nearest neighbour. Fast but blocky. + * - mdd_objectChangeEndianness(): creates a new object where the + * endianness is inverted compared to the source object, or changes + * the object itself. + * + * COMMENTS: + * No comments + */ + + + +// For early templates +#ifndef _RVIEW_MDD_CPP_ +#define _RVIEW_MDD_CPP_ + + + +#ifdef __GNUG__ +#pragma implementation +#endif + + + +#include <limits.h> +#include <float.h> +#include <string.h> + + + +// Was this file included from rviewMDD.hh? +#ifdef EARLY_TEMPLATE +#ifndef __EXECUTABLE__ +#define __EXECUTABLE__ +#define _RVIEW_MDD_EXECUTABLE_ +#endif +#endif + +#include "rasodmg/transaction.hh" +#include "raslib/primitivetype.hh" +#include "raslib/structuretype.hh" +#include "raslib/endian.hh" +#include "rasodmg/alignedtiling.hh" +#include "rasodmg/storagelayout.hh" +#include "rviewMDD.hh" +#include "rviewTypes.hh" + +#ifdef _RVIEW_MDD_EXECUTABLE_ +#undef __EXECUTABLE__ +#endif + + + + +#define MDD_FIXPREC 16 + + + + + +// auxData interpreted as double[2] containing min, max, initialised externally +template<class T> +int objectRange_temp(T *dest, const T *src, const mdd_function_desc *mfd, int dim, int datastep, void *auxData) +{ + long *pos; + char *srcdata; + T **srcptr; + int i, j; + double min, max, val; + + pos = new long[dim]; srcptr = new T *[dim]; + + srcdata = objectCalcStart((const char *)src, mfd, dim); + + for (i=0; i<dim; i++) + { + pos[i] = mfd[i].useLow; srcptr[i] = (T*)srcdata; + } + + min = ((double*)auxData)[0]; max = ((double*)auxData)[1]; + + do + { + val = (double)(*srcptr[dim-1]); + if (val < min) min = val; + if (val > max) max = val; + i = dim-1; + while (i >= 0) + { + pos[i]++; srcptr[i] = (T*)(((char*)(srcptr[i])) + mfd[i].srcoff); + if (pos[i] <= mfd[i].useHigh) break; + pos[i] = mfd[i].useLow; i--; + } + if (i >= 0) + { + for (j=i+1; j<dim; j++) srcptr[j] = srcptr[i]; + } + } + while (i >= 0); + + ((double*)auxData)[0] = min; ((double*)auxData)[1] = max; + + delete [] srcptr; delete [] pos; + + return 1; +} + + +// Additional template code for objectScaleInter template +inline void objectScaleInterICore(double *srcf, double *destf, double pos, int idx1, int idx2) +{ + destf[idx1] = srcf[idx1] + pos * (srcf[idx2] - srcf[idx1]); +} + +template<class T> +int objectScaleInter_temp(T *dest, const T *src, const mdd_function_desc *mfd, int dim, int datastep, void *auxData) +{ + double *pos, *f, *fwork; + long *lastpos; + long *ipos; + long *dp; + char **srcptr; + char *srcbase; + long offset; + int i, j, k; + int slowOffset; + T *srcdata, *destdata; + long *cubeoff = (long*)auxData; + + f = new double[(1<<dim)]; fwork = new double[(1<<dim)]; + pos = new double[dim]; ipos = new long[dim]; lastpos = new long[dim]; srcptr = new char*[dim]; + dp = new long[dim]; + + // Calculate the starting point + srcbase = objectCalcStart((const char*)src, mfd, dim); + + for (i=0; i<dim; i++) + { + pos[i] = (double)(mfd[i].useLow); lastpos[i] = mfd[i].useLow; + srcptr[i] = srcbase; dp[i] = mfd[i].newLow; + } + + destdata = dest; + + // Main loop: iterate over all dimensions except for the last which is handled separately + // in its own loop for efficiency reasons. + do + { + pos[dim-1] = (double)(mfd[dim-1].useLow); dp[dim-1] = mfd[dim-1].newLow; + + // slowOffset determines whether the fast table-lookup offset or the slower dimension looping + // offset calculation can be used. Table-lookup is always possible as long as the current + // position in the cube is not at the cube's boundary. In the innermost loop slowOffset only + // has to be updated, not recalculated, because there is only a (new) overflow possible in the + // innermost loop-dimension. + slowOffset = 0; + for (i=0; i<dim; i++) + { + ipos[i] = (long)(pos[i]); + // Check for high rather than useHigh because we only get problems if its > high. + if (ipos[i] >= mfd[i].high) {ipos[i] = mfd[i].useHigh; slowOffset = 1;} + } + + srcbase = srcptr[dim-1]; + + if (slowOffset != 0) + { + for (i=0; i<(1<<dim); i++) + { + offset = 0; + for (j=0; j<dim; j++) + { + // Check against high, not useHigh (see above) + if (((i & (1<<j)) != 0) && (ipos[j] < mfd[j].high)) offset += mfd[j].srcoff; + } + srcdata = (T*)(srcbase + offset); + f[i] = (double)(*srcdata); + //if (srcdata+offset >= srchigh) cout << "Overflow1" << endl; + } + } + else + { + for (i=0; i<(1<<dim); i++) + { + srcdata = (T*)(srcbase + cubeoff[i]); + f[i] = (double)(*srcdata); + } + } + + lastpos[dim-1] = (long)(pos[dim-1]); + // Innermost loop + for (k = mfd[dim-1].newHigh - mfd[dim-1].newLow + 1; k>0; k--) + { + // n-linear interpolation + for (j=0; j<(1<<dim); j+=2) + { + objectScaleInterICore(f, fwork, (double)(pos[0] - ipos[0]), j, j+1); + } + for (i=1; i<dim; i++) + { + for (j=0; j<(1<<dim); j+=(1<<(i+1))) + { + objectScaleInterICore(fwork, fwork, (double)(pos[i] - ipos[i]), j, j + (1<<i)); + } + } + // We go in sequential order (highest coordinate first) + *destdata = (T)(fwork[0]); + destdata = (T*)(((char*)destdata) + datastep); + + // end of innermost loop + pos[dim-1] += mfd[dim-1].step; offset = (long)(pos[dim-1]); + if (offset != lastpos[dim-1]) + { + offset -= lastpos[dim-1]; lastpos[dim-1] = (long)(pos[dim-1]); + // Check against high, not useHigh + if (lastpos[dim-1] <= mfd[dim-1].high) + { + srcbase += offset*mfd[dim-1].srcoff; ipos[dim-1] = lastpos[dim-1]; + } + // high, not useHigh + if (lastpos[dim-1] >= mfd[dim-1].high) slowOffset = 1; + offset = (1<<(dim-1)); + memcpy(f, f + offset, offset*sizeof(double)); + + if (slowOffset != 0) + { + for (i=(1<<(dim-1)); i<(1<<dim); i++) + { + offset = 0; + for (j=0; j<dim-1; j++) + { + // high, not useHigh + if (((i & (1<<j)) != 0) && (ipos[j] < mfd[j].high)) offset += mfd[j].srcoff; + } + srcdata = (T*)(srcbase + offset); + f[i] = (double)(*srcdata); + //if (srcdata+offset >= srchigh) cout << "Overflow2" << endl; + } + } + else + { + for (i=(1<<(dim-1)); i<(1<<dim); i++) + { + srcdata = (T*)(srcbase + cubeoff[i - (1<<(dim-1))]); + f[i] = (double)(*srcdata); + } + } + } + } + i = dim-2; + while (i >= 0) + { + dp[i]++; + pos[i] += mfd[i].step; offset = (long)(pos[i]); + if (offset != lastpos[i]) + { + offset -= lastpos[i]; lastpos[i] = (long)(pos[i]); + // high, not useHigh + if (lastpos[i] <= mfd[i].high) + { + srcptr[i] += offset*mfd[i].srcoff; ipos[i] = lastpos[i]; + } + } + if (dp[i] <= mfd[i].newHigh) break; + dp[i] = mfd[i].newLow; pos[i] = (double)(mfd[i].useLow); lastpos[i] = mfd[i].useLow; i--; + } + if (i >= 0) + { + for (j=i+1; j<dim; j++) srcptr[j] = srcptr[i]; + } + } + while (i >= 0); + + delete [] pos; delete [] f; delete [] fwork; + delete [] ipos; delete [] lastpos; delete [] dp; delete [] srcptr; + + return 1; +} + + + + +template<class T> +int objectScaleAverage_temp(T *dest, const T *src, const mdd_function_desc *mfd, int dim, int datastep, void *aux) +{ + long *pos, *subpos, *dp; + T **srcptr, **subptr; + long lastpos, number; + double avg; + int i, j; + T *destdata; + char *srcdata; + + pos = new long[dim]; subpos = new long[dim]; dp = new long[dim]; + srcptr = new T*[dim]; subptr = new T*[dim]; + + srcdata = objectCalcStart((const char*)src, mfd, dim); + + for (i=0; i<dim; i++) + { + pos[i] = (mfd[i].useLow << MDD_FIXPREC); + dp[i] = mfd[i].newLow; srcptr[i] = (T*)srcdata; + } + + destdata = dest; + // Iterate over all cells in the destination object + do + { + //for (i=0; i<dim; i++) cout << (pos[i]>>MDD_FIXPREC) << ':' << (void*)(srcptr[i]) << ' '; cout << endl; + // start averaging over a subcube + avg = 0; number = 0; + // init subcube iteration + for (i=0; i<dim; i++) + { + subpos[i] = pos[i]; subptr[i] = srcptr[dim-1]; // no mistake! + } + do + { + avg += (double)(*(subptr[dim-1])); number++; + i = dim-1; + while (i >= 0) + { + subpos[i] += (1<<MDD_FIXPREC); + subptr[i] = (T*)(((char*)(subptr[i])) + mfd[i].srcoff); + if ((subpos[i] >> MDD_FIXPREC) < ((pos[i] + mfd[i].lstep) >> MDD_FIXPREC)) break; + subpos[i] = pos[i]; + i--; + } + if (i >= 0) + { + for (j=i+1; j<dim; j++) subptr[j] = subptr[i]; + } + } + while (i >= 0); + + *destdata = (T)(avg/number); + destdata = (T*)(((char*)destdata) + datastep); + + i = dim-1; + do + { + dp[i]++; lastpos = (pos[i] >> MDD_FIXPREC); pos[i] += mfd[i].lstep; + srcptr[i] = (T*)(((char*)(srcptr[i])) + ((pos[i] >> MDD_FIXPREC) - lastpos) * mfd[i].srcoff); + if (dp[i] <= mfd[i].newHigh) break; + dp[i] = mfd[i].newLow; pos[i] = (mfd[i].useLow << MDD_FIXPREC); + i--; + } + while (i >= 0); + if (i >= 0) + { + for (j=i+1; j<dim; j++) srcptr[j] = srcptr[i]; + } + } + while (i >= 0); + + delete [] subptr; delete [] srcptr; + delete [] dp; delete [] subpos; delete [] pos; + + return 1; +} + + + +template<class T> +int objectScaleSimple_temp(T *dest, const T *src, const mdd_function_desc *mfd, int dim, int datastep, void *aux) +{ + long *pos, *dp; + long lastpos; + T **srcptr; + T *destdata; + char *srcdata; + int i, j; + + pos = new long[dim]; dp = new long[dim]; srcptr = new T*[dim]; + + srcdata = objectCalcStart((const char*)src, mfd, dim); + + for (i=0; i<dim; i++) + { + pos[i] = (mfd[i].useLow << MDD_FIXPREC); dp[i] = mfd[i].newLow; + srcptr[i] = (T*)srcdata; + } + destdata = dest; + + do + { + *destdata = *(srcptr[dim-1]); + destdata = (T*)(((char*)destdata) + datastep); + i=dim-1; + while (i >= 0) + { + dp[i]++; lastpos = (pos[i] >> MDD_FIXPREC); pos[i] += mfd[i].lstep; + srcptr[i] = (T*)(((char*)srcptr[i]) + ((pos[i] >> MDD_FIXPREC) - lastpos)*mfd[i].srcoff); + if (dp[i] <= mfd[i].newHigh) break; + dp[i] = mfd[i].newLow; pos[i] = (mfd[i].useLow << MDD_FIXPREC); + i--; + } + if (i >= 0) + { + for (j=i+1; j<dim; j++) srcptr[j] = srcptr[i]; + } + } + while (i >= 0); + + delete [] srcptr; delete [] dp; delete [] pos; + + return 1; +} + + + +/* Must not compile non-template code when this file was just included */ +#ifndef __EXECUTABLE__ + +// in raslib/odmgtypes.hh there are the following typedefs: +// typedef unsigned char r_Boolean; +// typedef unsigned char r_Char; +// so the template instantiation is done twice for the same type. gcc 2.95.2 doesn't +// like this. + +// Sadly, this is necessary with VisualC... +#define DECLARE_MDD_FUNC(f) \ +// template int f<r_Boolean> MDD_FUNCTION_SIGNATURE(r_Boolean); \ + template int f<r_Char> MDD_FUNCTION_SIGNATURE(r_Char); \ + template int f<r_Octet> MDD_FUNCTION_SIGNATURE(r_Octet); \ + template int f<r_Short> MDD_FUNCTION_SIGNATURE(r_Short); \ + template int f<r_UShort> MDD_FUNCTION_SIGNATURE(r_UShort); \ + template int f<r_Long> MDD_FUNCTION_SIGNATURE(r_Long); \ + template int f<r_ULong> MDD_FUNCTION_SIGNATURE(r_ULong); \ + template int f<r_Float> MDD_FUNCTION_SIGNATURE(r_Float); \ + template int f<r_Double> MDD_FUNCTION_SIGNATURE(r_Double); + +DECLARE_MDD_FUNC(objectScaleInter_temp); +DECLARE_MDD_FUNC(objectScaleAverage_temp); +DECLARE_MDD_FUNC(objectScaleSimple_temp); +DECLARE_MDD_FUNC(objectRange_temp); + + + +// Calculate the starting point in the source cube +char *objectCalcStart(const char *src, const mdd_function_desc *mfd, int dim) +{ + int i; + char *d; + + d = (char*)src; + for (i=0; i<dim; i++) + { + d += (mfd[i].useLow - mfd[i].low) * mfd[i].srcoff; + } + return d; +} + + +/* + * Wrapper functions for those templates + */ + +#define CAST_MDDPTR(t, src) \ + r_Ref<r_Marray<t> > mddPtr = (r_Ref<r_Marray<t> >)(src) + + +int mdd_createSubcube(r_Ref<r_GMarray> srcMdd, r_Ref<r_GMarray> &newMdd, r_Minterval *domain, r_Database *db) +{ + r_Dimension dim; + char *destdata, *srcdata; + r_Ref<r_GMarray> newMddPtr; + r_Minterval interv; + r_Minterval newInterv; + int tpsize; + int i, j; + long length; + mdd_function_desc *mfd; + long *pos; + char **srcptr; + + interv = srcMdd->spatial_domain(); dim = interv.dimension(); + + if (dim < 1) return 0; + + tpsize = srcMdd->get_type_length(); + + newInterv = r_Minterval(dim); + for (i=0; i<(int)dim; i++) + { + if (domain == NULL) + { + newInterv << interv[i]; + } + else + { + newInterv << (*domain)[i]; + } + } + + if ((destdata = mdd_objectFunctionInitMdd(srcMdd, newMddPtr, newInterv, tpsize, dim, db)) == NULL) + { + cerr << "Couldn't create new MDD object" << endl; + return 0; + } + + mfd = mdd_objectFunctionInitData(interv, newInterv, newInterv, tpsize, MDD_OBJECT_INIT_NEWIV); + + srcdata = objectCalcStart(srcMdd->get_array(), mfd, (int)dim); + + pos = new long[dim]; srcptr = new char *[dim]; + + for (i=0; i<(int)dim; i++) + { + pos[i] = mfd[i].useLow; srcptr[i] = srcdata; + } + + // Lenght of one strip of data to copy + length = (mfd[dim-1].useHigh - mfd[dim-1].useLow + 1) * tpsize; + do + { + memcpy(destdata, srcptr[dim-1], length); + destdata += length; + i = (int)dim-2; + while (i >= 0) + { + pos[i]++; srcptr[i] += mfd[i].srcoff; + if (pos[i] <= mfd[i].useHigh) break; + pos[i] = mfd[i].useLow; i--; + } + if (i >= 0) + { + for (j=i+1; j<(int)dim; j++) srcptr[j] = srcptr[i]; + } + } + while (i >= 0); + + delete [] srcptr; delete [] pos; + delete [] mfd; + + newMdd = newMddPtr; + + return 1; +} + + + +// Support functions for (recursive) member-by-member resampling of a data cube via interpolation +int mdd_objectFunctionPrim(const mdd_function_pointers *mfp, r_Primitive_Type *primType, const char *src, char *dest, const mdd_function_desc *mfd, int dim, int tpsize, void *auxData) +{ + switch (primType->type_id()) + { + case r_Primitive_Type::BOOL: + if (mfp->mddf_bool != NULL) + mfp->mddf_bool((r_Boolean*)dest, (const r_Boolean *)src, mfd, dim, tpsize, auxData); + break; + case r_Primitive_Type::CHAR: + if (mfp->mddf_char != NULL) + mfp->mddf_char((r_Char*)dest, (const r_Char *)src, mfd, dim, tpsize, auxData); + break; + case r_Primitive_Type::OCTET: + if (mfp->mddf_octet != NULL) + mfp->mddf_octet((r_Octet *)dest, (const r_Octet*)src, mfd, dim, tpsize, auxData); + break; + case r_Primitive_Type::SHORT: + if (mfp->mddf_short != NULL) + mfp->mddf_short((r_Short *)dest, (const r_Short*)src, mfd, dim, tpsize, auxData); + break; + case r_Primitive_Type::USHORT: + if (mfp->mddf_ushort != NULL) + mfp->mddf_ushort((r_UShort *)dest, (const r_UShort*)src, mfd, dim, tpsize, auxData); + break; + case r_Primitive_Type::LONG: + if (mfp->mddf_long != NULL) + mfp->mddf_long((r_Long *)dest, (const r_Long*)src, mfd, dim, tpsize, auxData); + break; + case r_Primitive_Type::ULONG: + if (mfp->mddf_ulong != NULL) + mfp->mddf_ulong((r_ULong *)dest, (const r_ULong*)src, mfd, dim, tpsize, auxData); + break; + case r_Primitive_Type::FLOAT: + if (mfp->mddf_float != NULL) + mfp->mddf_float((r_Float *)dest, (const r_Float*)src, mfd, dim, tpsize, auxData); + break; + case r_Primitive_Type::DOUBLE: + if (mfp->mddf_double != NULL) + mfp->mddf_double((r_Double *)dest, (const r_Double*)src, mfd, dim, tpsize, auxData); + break; + default: return 0; + } + return 1; +} + + +// Support functions for (recursive) member-by-member resampling of a data cube via interpolation +int mdd_objectFunctionStruct(const mdd_function_pointers *mfp, r_Structure_Type *structType, const char *src, char *dest, const mdd_function_desc *mfd, int dim, int tpsize, void *auxData) +{ + r_Type *newType; + unsigned long offset; + char *inc, *outc; + + r_Structure_Type::attribute_iterator iter(structType->defines_attribute_begin()); + while (iter != structType->defines_attribute_end()) + { + newType = (*iter).type_of().clone(); + offset = (*iter).offset(); + inc = (char*)src + offset; outc = (char*)dest + offset; + + if (newType->isStructType()) + { + r_Structure_Type *newStructType = (r_Structure_Type*)newType; + mdd_objectFunctionStruct(mfp, newStructType, inc, outc, mfd, dim, tpsize, auxData); + } + else + { + r_Primitive_Type *newPrimType = (r_Primitive_Type*)newType; + mdd_objectFunctionPrim(mfp, newPrimType, inc, outc, mfd, dim, tpsize, auxData); + } + delete newType; + iter++; + } + return 1; +} + + +int mdd_objectFunctionType(const mdd_function_pointers *mfp, const r_Type *baseType, const char *src, char *dest, const mdd_function_desc *mfd, int dim, int tpsize, void *auxData) +{ + if (((r_Type*)baseType)->isStructType()) + { + r_Structure_Type *structType = (r_Structure_Type*)baseType; + return mdd_objectFunctionStruct(mfp, structType, src, dest, mfd, dim, tpsize, auxData); + } + else + { + r_Primitive_Type *primType = (r_Primitive_Type*)baseType; + return mdd_objectFunctionPrim(mfp, primType, src, dest, mfd, dim, tpsize, auxData); + } +} + + +char *mdd_objectFunctionInitMdd(r_Ref<r_GMarray> mddPtr, r_Ref<r_GMarray> &newMddPtr, r_Minterval &newInterv, int tpsize, r_Dimension dim, r_Database *db) +{ + char *destdata; + const char *b; + r_Storage_Layout *store; + + if (mddPtr->get_storage_layout() != NULL) + { + store = new r_Storage_Layout(*(mddPtr->get_storage_layout())); + } + else + { + r_Minterval tileInterv(dim); + r_Aligned_Tiling *dfltTiling; + int dim, i; + + dim = newInterv.dimension(); + for (i=0; i<dim; i++) + { + tileInterv << r_Sinterval((r_Range)0, (r_Range)256); + } + dfltTiling = new r_Aligned_Tiling(tileInterv, tpsize * tileInterv.cell_count()); + store = new r_Storage_Layout(dfltTiling); + } + + if (db == NULL) + { + newMddPtr = new r_GMarray(newInterv, tpsize, store); + } + else + { + newMddPtr = new (db) r_GMarray(newInterv, tpsize, store); + } + + destdata = newMddPtr->get_array(); + newMddPtr->set_current_format(mddPtr->get_current_format()); + if ((b = mddPtr->get_type_name()) != NULL) newMddPtr->set_type_by_name(b); + if ((b = mddPtr->get_type_structure()) != NULL) newMddPtr->set_type_structure(b); + + return destdata; +} + + +mdd_function_desc *mdd_objectFunctionInitData(r_Minterval &interv, r_Minterval &useInterv, r_Minterval &newInterv, int tpsize, unsigned int flags) +{ + int i, offset; + r_Dimension dim; + mdd_function_desc *mfd; + + dim = interv.dimension(); + mfd = new mdd_function_desc[dim]; + + // Calculate scaling factors + for (i=0; i<(int)dim; i++) + { + mfd[i].low = interv[i].low(); mfd[i].high = interv[i].high(); + mfd[i].useLow = useInterv[i].low(); mfd[i].useHigh = useInterv[i].high(); + if ((flags & MDD_OBJECT_INIT_NEWIV) != 0) + { + mfd[i].newLow = newInterv[i].low(); mfd[i].newHigh = newInterv[i].high(); + if ((flags & MDD_OBJECT_INIT_FPSTEP) == MDD_OBJECT_INIT_FPSTEP) + { + // In order to avoid doubling right-boundary pixels we have to use (h-l), not (h-l+1) + // as nominator + mfd[i].step = ((double)(mfd[i].useHigh - mfd[i].useLow)) / (mfd[i].newHigh - mfd[i].newLow + 1); + } + else + { + double h = ((double)(mfd[i].useHigh - mfd[i].useLow + 1)) / (mfd[i].newHigh - mfd[i].newLow + 1); + mfd[i].lstep = (long)(h * (1<<MDD_FIXPREC)); + } + } + } + + offset = tpsize; + for (i=(int)dim-1; i>=0; i--) + { + mfd[i].srcoff = offset; + offset *= (mfd[i].high - mfd[i].low + 1); + } + + return mfd; +} + + + +int mdd_objectRange(r_Ref<r_GMarray> mddPtr, r_Minterval &useInterv, double &min, double &max) +{ + r_Dimension dim; + double minmax[2]; + r_Ref<r_GMarray> newMddPtr; // Dummy... + r_Minterval newInterv; // Dummy... + r_Minterval interv; + const r_Type *baseType; + int tpsize; + mdd_function_desc *mfd; + mdd_function_pointers mfp; + + interv = mddPtr->spatial_domain(); dim = interv.dimension(); + + if (dim < 1) return 0; + + if ((baseType = mddPtr->get_base_type_schema()) == NULL) + { + cerr << "No schema information available!" << endl; + return 0; + } + + tpsize = mddPtr->get_type_length(); + + MDD_INIT_FUNCTIONS(mfp, objectRange_temp); + + mfd = mdd_objectFunctionInitData(interv, useInterv, newInterv, tpsize, 0); + + minmax[0] = DBL_MAX; minmax[1] = -DBL_MAX; // these are unsigned!!! + + mdd_objectFunctionType(&mfp, baseType, mddPtr->get_array(), NULL, mfd, (int)dim, tpsize, (void*)minmax); + + min = minmax[0]; max = minmax[1]; + + delete [] mfd; + + return 1; +} + + + +// Scale an object using n-linear interpolation (recommended for magnification) +int mdd_objectScaleInter(r_Ref<r_GMarray> mddPtr, r_Minterval &useInterv, r_Ref<r_GMarray> &newMdd, r_Minterval &newInterv) +{ + r_Dimension dim; + r_Minterval interv; + r_Ref<r_GMarray> newMddPtr; + mdd_function_desc *mfd; + int i, j; + long *cubeoff; + char *srcdata, *destdata; + int tpsize; + long offset; + const r_Type *baseType; + mdd_function_pointers mfp; + + interv = mddPtr->spatial_domain(); + dim = interv.dimension(); + if ((dim < 1) || (dim != newInterv.dimension())) return 0; + + // Type information available? + if ((baseType = mddPtr->get_base_type_schema()) == NULL) + { + cerr << "No schema information available!" << endl; + return 0; + } + + tpsize = mddPtr->get_type_length(); + + if ((destdata = mdd_objectFunctionInitMdd(mddPtr, newMddPtr, newInterv, tpsize, dim)) == NULL) + return 0; + + MDD_INIT_FUNCTIONS(mfp, objectScaleInter_temp); + + // create temporary arrays + mfd = mdd_objectFunctionInitData(interv, useInterv, newInterv, tpsize, MDD_OBJECT_INIT_FPSTEP); + cubeoff = new long[(1<<dim)]; + + // Debugging + /*T *srchigh; + offset=1; + for (i=0; i<dim; i++) offset *= (interv[i].high() - interv[i].low() + 1); + srchigh = (T*)(mddPtr->get_array()) + offset;*/ + + srcdata = (char*)(mddPtr->get_array()); + + // Precalculate cube-offsets for more speed in inner loop + for (i=0; i<(1<<dim); i++) + { + offset = 0; + for (j=0; j<(int)dim; j++) + { + if ((i & (1<<j)) != 0) offset += mfd[j].srcoff; + } + cubeoff[i] = offset; + } + + mdd_objectFunctionType(&mfp, baseType, srcdata, destdata, mfd, (int)dim, tpsize, (void*)cubeoff); + + delete [] cubeoff; delete [] mfd; + + newMdd = newMddPtr; + + return 1; +} + + +// Scale an object by averaging cell values -- recommended for scaling down +int mdd_objectScaleAverage(r_Ref<r_GMarray> mddPtr, r_Minterval &useInterv, r_Ref<r_GMarray> &newMdd, r_Minterval &newInterv) +{ + r_Dimension dim; + r_Minterval interv; + r_Ref<r_GMarray> newMddPtr; + mdd_function_desc *mfd; + char *srcdata, *destdata; + int tpsize; + const r_Type *baseType; + mdd_function_pointers mfp; + + interv = mddPtr->spatial_domain(); + dim = interv.dimension(); + + if ((dim < 1) || (dim != newInterv.dimension())) return 0; + + if ((baseType = mddPtr->get_base_type_schema()) == NULL) + { + cerr << "No schema information available!" << endl; + return 0; + } + + tpsize = mddPtr->get_type_length(); + + if ((destdata = mdd_objectFunctionInitMdd(mddPtr, newMddPtr, newInterv, tpsize, dim)) == NULL) + return 0; + + MDD_INIT_FUNCTIONS(mfp, objectScaleAverage_temp); + + mfd = mdd_objectFunctionInitData(interv, useInterv, newInterv, tpsize, MDD_OBJECT_INIT_NEWIV); + + srcdata = mddPtr->get_array(); + + mdd_objectFunctionType(&mfp, baseType, srcdata, destdata, mfd, (int)dim, tpsize, NULL); + + delete [] mfd; + + newMdd = (r_Ref<r_GMarray>)newMddPtr; + + return 1; +} + + +int mdd_objectScaleSimple(r_Ref<r_GMarray> mddPtr, r_Minterval &useInterv, r_Ref<r_GMarray> &newMdd, r_Minterval &newInterv) +{ + r_Dimension dim; + r_Minterval interv; + r_Ref<r_GMarray> newMddPtr; + mdd_function_desc *mfd; + char *srcdata, *destdata; + int tpsize; + const r_Type *baseType; + mdd_function_pointers mfp; + + interv = mddPtr->spatial_domain(); + dim = interv.dimension(); + + if ((dim < 1) || (dim != newInterv.dimension())) return 0; + + if ((baseType = mddPtr->get_base_type_schema()) == NULL) + { + cerr << "No schema information available!" << endl; + return 0; + } + + tpsize = mddPtr->get_type_length(); + + if ((destdata = mdd_objectFunctionInitMdd(mddPtr, newMddPtr, newInterv, tpsize, dim)) == NULL) + return 0; + + MDD_INIT_FUNCTIONS(mfp, objectScaleSimple_temp); + + mfd = mdd_objectFunctionInitData(interv, useInterv, newInterv, tpsize, MDD_OBJECT_INIT_NEWIV); + + srcdata = mddPtr->get_array(); + + mdd_objectFunctionType(&mfp, baseType, srcdata, destdata, mfd, (int)dim, tpsize, NULL); + + newMdd = (r_Ref<r_GMarray>)newMddPtr; + + delete [] mfd; + + return 1; +} + + +int mdd_objectChangeEndianness(r_Ref<r_GMarray> mddPtr, r_Minterval &useInterv, r_Ref<r_GMarray> *newMdd, r_Minterval *newInterv) +{ + char *srcdata; + const r_Base_Type *baseType; + r_Ref<r_GMarray> newMddPtr; // only used in "new" mode + r_Minterval dom, *iterDom; + int tpsize; + + if ((baseType = (r_Base_Type*)(mddPtr->get_base_type_schema())) == NULL) + { + cerr << "No schema information available!" << endl; + return 0; + } + + tpsize = mddPtr->get_type_length(); + + srcdata = mddPtr->get_array(); + + dom = mddPtr->spatial_domain(); + + if (newMdd == NULL) + { + r_Endian::swap_array( baseType, dom, dom, srcdata, srcdata ); + } + else + { + void *destdata; + r_Dimension dim = dom.dimension(); + + if ((destdata = mdd_objectFunctionInitMdd(mddPtr, newMddPtr, *newInterv, tpsize, dim)) == NULL) + return 0; + + r_Endian::swap_array( baseType, dom, *newInterv, *newInterv, *newInterv, srcdata, destdata ); + } + + if (newMdd != NULL) + { + *newMdd = newMddPtr; + } + + return 1; +} + +#endif + +#endif |