Exemplo n.º 1
0
/* test value scale on compatibility CSF version 1 and 2
 * RvalueScaleIs tests if the map's value scale is compatible
 * with a certain value scale. Here is list of compatible but
 * different value scales: 
 *   
 * VS_NOTDETERMINED: always returns 0
 *
 * VS_CLASSIFIED: VS_NOTDETERMINED
 *
 * VS_CONTINUOUS: VS_NOTDETERMINED
 *
 * VS_BOOLEAN: VS_CLASSIFIED, VS_NOTDETERMINED
 *
 * VS_NOMINAL: VS_CLASSIFIED, VS_NOTDETERMINED
 *
 * VS_ORDINAL: VS_CLASSIFIED, VS_NOTDETERMINED
 *
 * VS_LDD:  VS_CLASSIFIED, VS_NOTDETERMINED (only if cell representation is
 * UINT1 or INT2)
 *
 * VS_SCALAR:  VS_CONTINUOUS, VS_NOTDETERMINED
 *
 * VS_DIRECTION: none 
 *
 * returns
 * 0 if not compatible or if vs argument is VS_NOTDETERMINED or in case of
 * error, nonzero if 
 * compatible.
 *
 * Merrno
 * BAD_VALUESCALE
 *
 * EXAMPLE
 * .so examples/maskdump.tr
 */
int RvalueScaleIs(
	const MAP *m, /* a version 1 map handle */
	CSF_VS     vs) /* a version 2 value scale that is compatible with map's value
	               * scale yes or no?
	               */
{
	CSF_VS mapsVS = RgetValueScale(m);
	
	if (vs == VS_NOTDETERMINED)
		return 0;

	if (vs == mapsVS)
		return 1;

	switch(vs) {
	  case VS_CLASSIFIED: return mapsVS == VS_NOTDETERMINED;
	  case VS_CONTINUOUS: return mapsVS == VS_NOTDETERMINED;
	  case VS_LDD: 
	                { CSF_CR cr = RgetCellRepr(m);
	                  if (cr !=  CR_UINT1 && cr != CR_INT2)
	                   return 0;
	                } /* fall through */
	 case VS_BOOLEAN:
	 case VS_NOMINAL:
	 case VS_ORDINAL:  return mapsVS == VS_CLASSIFIED 
			    || mapsVS == VS_NOTDETERMINED;
	 case VS_SCALAR:   return mapsVS == VS_CONTINUOUS
	                    || mapsVS == VS_NOTDETERMINED;
	/* direction isn't compatible with anything */
	 case VS_DIRECTION: return 0;
	 default          : M_ERROR(BAD_VALUESCALE);
	                    return 0;
      }
}
Exemplo n.º 2
0
/* read a stream of cells
 * RgetSomeCells views a raster as one linear stream of
 * cells, with row i+1 placed after row i. 
 * In this stream any sequence can be read by specifying an
 * offset and the number of cells to be read
 * returns the number of cells read, just as fread
 *
 * example
 * .so examples/somecell.tr
 */
size_t RgetSomeCells(
	MAP *map,	/* map handle */
	size_t offset,   /* offset from pixel (row,col) = (0,0) */
	size_t nrCells,  /* number of cells to be read */
	void *buf)/* write-only. Buffer large enough to
                   * hold nrCells cells in the in-file cell representation
                   * or the in-app cell representation.
                   */
{

	CSF_FADDR  readAt;
	size_t cellsRead;
	UINT2  inFileCR = RgetCellRepr(map);

	offset <<= LOG_CELLSIZE(inFileCR);
	readAt = ADDR_DATA + (CSF_FADDR)offset;
	fseek(map->fp, (long)readAt, SEEK_SET);
	cellsRead = map->read(buf, (size_t)CELLSIZE(inFileCR),
	(size_t)nrCells, map->fp);

	PRECOND(map->file2app != NULL);
	map->file2app(nrCells, buf);

	return(cellsRead);
}
Exemplo n.º 3
0
/* allocate dynamic memory large enough to hold in-file and app cells
 * Rmalloc allocates memory to hold  nrOfCells 
 * cells in both the in-file and app cell representation. Allocation
 * is done by malloc for other users. Our own (utrecht university) applications
 * calls ChkMalloc. Freeing memory allocated by Rmalloc is done by free (or Free).
 *
 * NOTE
 * Note that a possible RuseAs call must be done BEFORE Rmalloc.
 *
 * returns
 * a pointer the allocated memory or
 * NULL
 * if the request fails
 *
 * example
 * .so examples/_row.tr
 */
void *Rmalloc(
	const MAP *m,      /* map handle */
	size_t nrOfCells)   /* number of cells allocated memory must hold */
{
	CSF_CR inFileCR = RgetCellRepr(m);
	CSF_CR largestCellRepr = 
		LOG_CELLSIZE(m->appCR) > LOG_CELLSIZE(inFileCR) 
		 ?  m->appCR : inFileCR;

	return CSF_MALLOC((size_t)CSFSIZEOF(nrOfCells, largestCellRepr));
}
Exemplo n.º 4
0
/* make all cells missing value in map
 * RputAllMV writes a missing values to all the cells in a
 * map. For this is allocates a buffer to hold one row at a
 * time.
 * returns 1 if succesfull, 0 in case of an error
 */
int RputAllMV(
	MAP *m)
{
	size_t i,nc,nr;
	void *buffer;
	CSF_CR cr;

	CHECKHANDLE_GOTO(m, error);
	if(! WRITE_ENABLE(m))
	{
		M_ERROR(NOACCESS);
		goto error;
	}

	cr = RgetCellRepr(m);
	nc = RgetNrCols(m);

	buffer = Rmalloc(m,nc);
	if(buffer == NULL)
	{
		M_ERROR(NOCORE);
		goto error;
	}

	/*  Fill buffer with determined Missingvalue*/
	SetMemMV(buffer, nc, cr);

	nr = RgetNrRows(m);
	for(i = 0 ; i < nr; i++)
	 if (RputRow(m, i, buffer) != nc)
	 {
	    M_ERROR(WRITE_ERROR);
	    goto error_f;
	 }
	CSF_FREE(buffer);

	CsfSetVarTypeMV( &(m->raster.minVal), cr);
	CsfSetVarTypeMV( &(m->raster.maxVal), cr);

	return(1);
error_f:  
	CSF_FREE(buffer);
error:
	return(0);
}
Exemplo n.º 5
0
void RputMinVal(
	MAP *map, /* map handle */
	const void *minVal)   /* New minimum value */
{
	/* use buffer that can hold largest 
	 * cell representation
	 */
	CSF_VAR_TYPE buf_1;
	void *buf = (void *)(&buf_1);

	CHECKHANDLE(map);

	/* make a copy */
	CsfGetVarType(buf, minVal, map->appCR);

	/* convert */
	map->app2file(1, buf);

	/* set */
	CsfGetVarType( (void *)&(map->raster.minVal), buf, RgetCellRepr(map));

	map->minMaxStatus = MM_DONTKEEPTRACK;
}
Exemplo n.º 6
0
static int ReadAttr(
       ATTRIBUTES *a,
       MAP *m,
       BOOL readOnly) /* are the attribute only used for teh PRINT op
                       */
{
       DefaultAttr(a);
       if (RuseAs(m, CR_REAL8))
              goto failure;
        RgetMinVal(m, &(a->minVal));
        RgetMaxVal(m, &(a->maxVal));
        a->projection = MgetProjection(m);
        a->xUL = RgetXUL(m);
        a->yUL = RgetYUL(m);
       a->nrRows = RgetNrRows(m);
       a->nrCols = RgetNrCols(m);
       a->cellSize = RgetCellSize(m);
        a->version    = MgetVersion(m);
       a->gisFileId = MgetGisFileId(m);
       a->byteOrder = m->main.byteOrder;
       a->attrTable = m->main.attrTable;
       if (Merrno)
              goto failure;
       if (a->version == 2 || readOnly)
       { /* otherwise use defaults */
          a->valueScale = RgetValueScale(m);
          a->cellRepr = RgetCellRepr(m);
         a->angle = RgetAngle(m);
         if (a->angle < 0)
             a->angle = -Rad2Deg(-a->angle);
         else
             a->angle = Rad2Deg(a->angle);
       }
       return 0;
failure:
       return 1;
}
Exemplo n.º 7
0
int RuseAs(
	MAP *m,          /* map handle */
	CSF_CR useType)   /* CR_UINT1,CR_INT4, CR_REAL4, CR_REAL8, VS_BOOLEAN or VS_LDD */
{ 

  CSF_CR inFileCR = RgetCellRepr(m);
  CSF_VS inFileVS = RgetValueScale(m);
  int hasInFileCellReprType2 =  HasInFileCellReprType2(inFileCR);

  /* it is very unconvenient that both, VS and CR are taken as arguments
   * for this function, and previously were used in the switch statement
   * now, at least 'special conversions' handled first
   */
  if((int)useType == VS_BOOLEAN){
    switch(inFileVS) {
      case VS_LDD:
      case VS_DIRECTION: {
        M_ERROR(CANT_USE_AS_BOOLEAN);
        return 1;
      }
      case VS_BOOLEAN: {
        POSTCOND(inFileCR == CR_UINT1);
        m->appCR = CR_UINT1;
        m->file2app = same;
        m->app2file = same;
        return 0;
      }
      default: {
        if((!hasInFileCellReprType2) && WRITE_ENABLE(m)) {
          /* cellrepr is old one, we can't write that */
          M_ERROR(CANT_USE_WRITE_BOOLEAN);
          return 1;
        }
        m->appCR = CR_UINT1;
        m->file2app  = ConvFuncBool(inFileCR);
        m->app2file = ConvFunc(inFileCR, CR_UINT1);
        return 0;
      }
    }
  }
  else if ((int)useType == VS_LDD){
    switch(inFileVS) {
      case VS_LDD: {
        POSTCOND(inFileCR == CR_UINT1);
        m->appCR = CR_UINT1;
        m->file2app = same;
        m->app2file = same;
        return 0;
      }
      case VS_CLASSIFIED: 
      case VS_NOTDETERMINED: {
        switch(inFileCR) {
          case CR_UINT1: {
            m->appCR = CR_UINT1;
            m->file2app  = UINT1tLdd;
            m->app2file = same;
            return 0;
          }
          case CR_INT2: {
            if(WRITE_ENABLE(m)) {
              M_ERROR(CANT_USE_WRITE_LDD);
              return 1;
            }
            m->appCR = CR_UINT1;
            m->file2app  = INT2tLdd;
            m->app2file = illegal;
            return 0;
          }
          default: {
            /* This should never happen.
             * Shut up compiler.
             */
            assert(0);
          }
        }
      }
      default: {
        M_ERROR(CANT_USE_AS_LDD);
        return 1;
      }
    }
  }

  switch(useType) {
    case CR_UINT1:
    case CR_INT4 :
    case CR_REAL4:
    case CR_REAL8: {
      if((!hasInFileCellReprType2) && WRITE_ENABLE(m)) {
        /* cellrepr is old one, we can't write that */
        M_ERROR(CANT_USE_WRITE_OLDCR);
        return 1;
      }
      m->appCR = useType;
      m->file2app  = ConvFunc(useType, inFileCR);
      m->app2file = ConvFunc(inFileCR, useType);
      POSTCOND(m->file2app != NULL);
      return 0;
    }
    default: {
      M_ERROR(ILLEGAL_USE_TYPE);
      return 1;
    }
  }
  /* NOTREACHED */
}
Exemplo n.º 8
0
int main(int argc, char *argv[]) {
    MAP *out, *clone = NULL;
    int c;
    size_t colNr[3] = {0 /*X*/, 1 /*Y*/, 2 /*V*/}; /* internal indices */
    const char *mv = "1e31";
    char *cloneFileName;
    COMP_CELL compCell = NOTHING;
    CSF_CR cellRepr;
    CSF_VS valueScale = VS_UNDEFINED;
    int parseVal;
    int sepChar = ',';

    if (InstallArgs(argc, argv, "x#y#v#m*(BLNOSDV)(atHM)(hl)s*", "col2map", __DATE__))
        goto failure;
    while ((c = GetOpt()) != 0)
        switch (c) {
        case 'x':
            parseVal = (*((const int *)OptArg)) - 1;
            if (parseVal < 0) {
                Error("-x: x column should be greater than 0");
                goto failure;
            }
            colNr[POS_X] = (size_t)parseVal;
            break;
        case 'y':
            parseVal = (*((const int *)OptArg)) - 1;
            if (parseVal < 0) {
                Error("-y: y column should be greater than 0");
                goto failure;
            }
            colNr[POS_Y] = (size_t)parseVal;
            break;
        case 'v':
            parseVal = (*((const int *)OptArg)) - 1;
            if (parseVal < 0) {
                Error("-v: value column should be greater than 0");
                goto failure;
            }
            colNr[POS_V] = (size_t)parseVal;
            break;
        case 'm':
            mv = (const char *)OptArg;
            break;
        case 'a':
            compCell = AVERAGE;
            break;
        case 'H':
            compCell = HIGHEST;
            break;
        case 'h':
            compCell = MAJORITY;
            break;
        case 'M':
            compCell = LOWEST;
            break;
        case 'l':
            compCell = MINORITY;
            break;
        case 't':
            compCell = TOTAL;
            break;
        case 's':
            sepChar = ((const char *)OptArg)[0];
            if (isdigit(sepChar)) {
                Error("-s: separator must be a non-digit (not [0-9])");
                goto failure;
            }
            break;
#include "case_vs.h"
        }

    argv = ArgArguments(&argc);
    if (argv == NULL)
        goto failure;
    if (AppArgCountCheck(argc, 3, 3, USAGE))
        goto failure;
    if (AppInputTest(argv[1]))
        goto failure;

    /* open the clone map */
    clone = AppOpenClone(&cloneFileName, NULL);
    if (clone == NULL)
        goto failure;

    if (valueScale == VS_UNDEFINED) {
        valueScale = RgetValueScale(clone);
        cellRepr = RgetCellRepr(clone);
    } else
        cellRepr = AppDefaultCellRepr(valueScale);

    if (!RvalueScale2(valueScale)) {
        Error("clone map '%s' has an illegal value scale", cloneFileName);
        goto failure2;
    }

    if (compCell == NOTHING) { /* defaults */
        switch (valueScale) {
        case VS_SCALAR:
            compCell = AVERAGE;
            break;
        case VS_DIRECTION:
            compCell = DIR_AVERAGE;
            break;
        default:
            compCell = MAJORITY;
            break;
        }
    } else {
        BOOL conflict = FALSE;
        CSF_VS vs = valueScale;
        switch (compCell) {
        case AVERAGE:
            conflict = (vs != VS_SCALAR && vs != VS_DIRECTION);
            if (vs == VS_DIRECTION)
                compCell = DIR_AVERAGE;
            break;
        case LOWEST:
        case HIGHEST:
            conflict = (vs != VS_SCALAR && vs != VS_ORDINAL);
            break;
        case MAJORITY:
        case MINORITY:
            conflict = (vs == VS_SCALAR || vs == VS_DIRECTION);
            break;
        case TOTAL:
            conflict = vs != VS_SCALAR;
            break;
        default:
            POSTCOND(FALSE);
        }
        if (conflict) {
            CompCellError(compCell, vs);
            goto failure2;
        }
    }

    out = Rdup(argv[2], clone, cellRepr, valueScale);
    if (out == NULL) {
        Error("output map '%s' can not be created", argv[2]);
        goto failure2;
    }
    Mclose(clone);
    clone = NULL;
    RuseAs(out, CR_REAL8);

    if (Col2Map(out, argv[1], compCell, mv, colNr, sepChar)) {
        Mclose(out);
        (void)remove(argv[2]);
        goto failure;
    }

    Mclose(out);
    AppEnd();
    exit(0);
    return 0;

failure2:
    if (clone == NULL)
        Mclose(clone);
failure:
    AppEnd();
    exit(1);
    return 1;
} /* main */
Exemplo n.º 9
0
/* seek to space for attribute  (LIBRARY_INTERNAL)
 * CsfSeekAttrSpace seeks to the a point in the file where
 * the attribute must be stored and update the attribute control
 * blocks accordingly.
 * Writing can still fail since there is no check if that space is really
 * avalaible on the device. After this call returns the file is already
 * seeked to the point the functions returns.
 * returns the file position or 0 in case of error.
 *
 * Merrno
 * ATTRDUPL
 * NOACCESS
 * WRITE_ERROR
 */
CSF_FADDR32 CsfSeekAttrSpace(
	MAP *m,       		/* map handle */
	CSF_ATTR_ID id,               /* attribute identification only for check if avalaible */
	size_t size)            /* size to be seeked to */
{
	ATTR_CNTRL_BLOCK b;
	CSF_FADDR32 currBlockPos, prevBlockPos=USED_UNINIT_ZERO, newPos, endBlock, resultPos=0;
	int noPosFound;
	int i;

	if (MattributeAvail(m ,id))
	{
		M_ERROR(ATTRDUPL);
		goto error;
	}

	if (! WRITE_ENABLE(m))
	{
		M_ERROR(NOACCESS);
		goto error;
	}

	currBlockPos = m->main.attrTable;
        noPosFound = 1;
	while (noPosFound)
	{
		if (currBlockPos == 0)
		{
			if (m->main.attrTable == 0)
			{ /* FIRST BLOCK */
				newPos =( (CSF_FADDR)(m->raster.nrRows)*
					   (CSF_FADDR)(m->raster.nrCols)*
					  (CSF_FADDR)(CELLSIZE(RgetCellRepr(m))))
					  + ADDR_DATA;
				m->main.attrTable = newPos;
			}
			else
			{ /* NEW/NEXT BLOCK */
				newPos = b.attrs[LAST_ATTR_IN_BLOCK].attrOffset
					+
					b.attrs[LAST_ATTR_IN_BLOCK].attrSize;
				b.next = newPos;
				if (CsfWriteAttrBlock(m, prevBlockPos, &b))
				{
					M_ERROR(WRITE_ERROR);
					resultPos = 0;
				}
			}
			InitBlock(&b);
			b.attrs[0].attrOffset =
				newPos + SIZE_OF_ATTR_CNTRL_BLOCK;
			currBlockPos = newPos;
			noPosFound = 0;
		}
		else
			CsfReadAttrBlock(m, currBlockPos, &b);
		i = 0; /* this is also the right index if a new block
			   is added ! */
		while (noPosFound  && i < NR_ATTR_IN_BLOCK)
			switch (b.attrs[i].attrId)
			{
				case END_OF_ATTRS:
					POSTCOND(i >= 1);
					/* i >= 1 , no block otherwise */
					b.attrs[i].attrOffset =
						b.attrs[i-1].attrOffset  +
						b.attrs[i-1].attrSize;
					noPosFound = 0;
                                        break;
				case ATTR_NOT_USED:
					if (i == NR_ATTR_IN_BLOCK)
						endBlock = b.next;
					else
						endBlock = b.attrs[i+1].attrOffset;
					if ( (size_t)( endBlock - b.attrs[i].attrOffset) >= size)
						/* this position can
							hold the attr */
						noPosFound = 0;
                                        else
                                            i++;
                                        break;
				 default:
                                            i++;
			} /* switch */
/*		if (b.next == 0)
                     ? When did I change this CW
		       remember this block position since it may be have
		       to rewritten
*/
		prevBlockPos = currBlockPos;
		if (noPosFound)
			currBlockPos = b.next;
 	} /* while */

	b.attrs[i].attrSize = size;
	b.attrs[i].attrId   = id;
	resultPos = b.attrs[i].attrOffset;

	if (CsfWriteAttrBlock(m, currBlockPos, &b))
	{
		M_ERROR(WRITE_ERROR);
		resultPos = 0;
	}
	fseek(m->fp, (long)resultPos, SEEK_SET); /* fsetpos() is better */
error:	return resultPos;
} /* CsfSeekAttrSpace */
Exemplo n.º 10
0
/* Function for resampling  N input maps into 1 output map.
 * Assumes a map "clone.map" and N "input.map"s present. Checks on
 * options for percentage and maximum value. 
 * Determines type and characteristics of output map.
 * Returns nothing, exits with 1 in case of error.
 */
int main(int argc,		/* number of arguments */
	char *argv[])		/* list of arguments */
{
     	MAP 	*clone, *out, *tmp, **in;
     	char 	*outputName, *cloneName;	
     	int 	c, borderval;	
     	size_t  nrMaps,i;
	REAL8 	X0, Y0, cellSize, angleIn, angleOut;
	size_t 	nrRows, nrCols;
	CSF_PT 	projection;
	CSF_CR  cellRepr;
	CSF_VS  valueScale;
	double 	percent = 0, errFactor = 2.5, resampleN = 0.0;
	BOOL	aligned = TRUE;
	BOOL    keepInputMinMax = FALSE;
	REAL8	minAllInput=0, maxAllInput=0;
	BOOL	onlyReal4 = TRUE, contract = FALSE;
	BOOL	onlyUint1 = TRUE;

	if(InstallArgs(argc, argv,"axmp$r$c#b#e$RBCk", "resample", __DATE__))
		exit(1);

     	while((c = GetOpt()) != 0)
     	{
     	    switch(c)
     	    {
     	    	case 'b': opB = TRUE;
     	    		borderval = *((int *) OptArg);
     	    		break;
     	    	case 'B': opB = TRUE;
     	    		borderval = 0;
     	    		break;
     	    	case 'C': opMV = TRUE;
     	    		borderval = 0;
     	    		break;
     	    	case 'c': opMV = TRUE;
     	    		borderval = *((int *) OptArg);
     	    		break;
     	    	case 'a':contract = TRUE;
     	    		break;
     	    	case 'x':contract = FALSE;
     	    		break;
     	    	case 'm':opMax = 1;
     	    		break;
     	    	case 'p':opPer = 1;
     	    		percent = *((double*) OptArg);
     	    		if(percent < 0 || 100 < percent)
     	    		{
     	    			Error("illegal percentage");
     	    			exit(1);
     	    		}
     	    		break;
     	    	case 'R':opR = 1;
     	    		resampleN = 1;
     	    		break;
     	    	case 'r':opR = 1;
     	    		resampleN = *((double*) OptArg);
     	    		break;
     	    	case 'e':optionAcc = 1;
     	    		errFactor = *((double*) OptArg);
     	    		break;
     	    	case 'k': keepInputMinMax = TRUE;
     	    		break;
     	    }
     	}

	argv = ArgArguments(&argc);
	if (AppArgCountCheck(argc,3,-1,USAGE))
		exit(1);

	outputName = argv[argc-1];
  	nrMaps  = argc-2;

	/* Read the desired specifics out of the clone map 
	 * or use first input as clone map
	 */
	cloneName = NO_CLONE_NEEDED ? argv[1] : NULL;
	if ( (clone = AppOpenClone(&cloneName,cloneName)) == NULL)
		exit(1);

	/* Determine the valueScale out of 1st input map */
	tmp = Mopen(argv[1], M_READ);
	if(tmp == NULL)
		MperrorExit(argv[1], 1);

	/* all input maps have same value scale */
	valueScale = RgetValueScale(tmp);
	if(valueScale == VS_LDD && !opMV)
	{
		Error("can not do this type of resampling on map '%s' with type ldd", argv[1]);
		exit(1);
	}
	/* adjust old ones */
	if(valueScale == VS_CLASSIFIED)
		valueScale = VS_ORDINAL;
	if(valueScale == VS_CONTINUOUS)
		valueScale = VS_SCALAR;

	/* get location attributes of clone or of 1st input map */
	projection = MgetProjection(clone);
	nrRows = RgetNrRows(clone);
	nrCols = RgetNrCols(clone);
	X0 = RgetX0(clone);
	Y0 = RgetY0(clone);
	cellRepr = RgetCellRepr(clone);
	angleOut = RgetAngle(clone); 

	/* resample option -> cell size(inputmap) * factor 
	 * Number of rows and columns are divided by resample
	 * factor.
	 */
	if(opR == 1)
	{
		/* setting for unit */
		if(!appUnitTrue)
		{
			cellSize = resampleN;
			resampleN /= (double) RgetCellSize(tmp);
		}
		else
			cellSize = RgetCellSize(tmp) * resampleN;
		if(contract)
		{
			nrRows = floor((double) nrRows / 
					(double) resampleN);
			nrCols = floor((double) nrCols / 
					(double) resampleN);

			/* Prevent an illegal map */
			if(nrRows == 0)
				nrRows = 1;
			if(nrCols == 0)
				nrCols = 1;
		}
		else
		{
			nrRows = ceil((double) nrRows / 
					(double) resampleN);
			nrCols = ceil((double) nrCols / 
					(double) resampleN);
		}
	}
	else
		cellSize = RgetCellSize(clone);

	/* Allocate memory for the input map pointers */
	in = (MAP **)ChkMalloc(sizeof(MAP *) * nrMaps);
	if(in == NULL)
	{
		AppEnd();
		exit(1);
	}

	/* Read all input maps with desired cell representation */
	for(i = 0; i < nrMaps; i++)
	{
		REAL8	tmpMin, tmpMax;

		tmp = Mopen(argv[1 + i], M_READ);
		angleIn = RgetAngle(tmp);
		if(angleIn != 0)
			aligned = FALSE;
		if(tmp == NULL)
			MperrorExit(argv[1 + i], 1);

		if(!RvalueScaleIs(tmp, valueScale))
		{
			Error("%s has illegal data type: '%s'\n",
				argv[1 + i], RstrValueScale(valueScale));
			exit(1);
		}

		in[i] = tmp;

		/* Determine which cell representation should be used */
		onlyReal4 = RgetCellRepr(in[i]) == CR_REAL4;
		onlyUint1 = RgetCellRepr(in[i]) == CR_UINT1;


		RuseAs(in[i], CR_REAL8);
		RgetMinVal(tmp, &tmpMin);
		RgetMaxVal(tmp, &tmpMax);
		if (i==0)
		 {minAllInput = tmpMin; maxAllInput = tmpMax; }
		minAllInput = MIN(minAllInput,tmpMin);
		maxAllInput = MAX(maxAllInput,tmpMax);

		if(AppIsClassified(valueScale))
			RuseAs(in[i], CR_INT4);
		else
			RuseAs(in[i], CR_REAL8);
	}

	if(opB == 1 || opMV == 1)
	{
		if(CheckInputMaps(in, nrMaps, projection, angleIn, cellSize))
		{
			Error("");
			FreeMaps(in, nrMaps);
			exit(1);
		}

		if(opB == 1)
		{
			if(SmallestFittingRectangle(&X0, &Y0, &nrRows,
			  &nrCols, in, borderval, nrMaps,
			  cellSize, angleIn, projection, contract))
			{
				FreeMaps(in, nrMaps);
				AppEnd();
				exit(1);
			}
		}
		else
		{
		  	if(SmallestNonMVRect(&X0, &Y0, &nrRows, &nrCols, in,
		  	borderval, nrMaps, valueScale, cellSize,
		  	angleIn, projection, contract))
			{	
				FreeMaps(in, nrMaps);
				AppEnd();
				exit(1);
			}
		}
	}

	/* Create output map with suitable cell representation */ 
	/* NOTE ! Create map with smallest representation possible */
	out = Rcreate(outputName, nrRows, nrCols, 
	               AppIsClassified(valueScale) ?
		               (onlyUint1 ? CR_UINT1 : CR_INT4) :
		               (onlyReal4 ? CR_REAL4 : CR_REAL8),
		               valueScale, projection, X0, Y0, 
		               angleOut, cellSize);
	if(out == NULL)
	{
		FreeMaps(in, nrMaps);
		Error("can not create output map '%s': %s", 
		      argv[1], MstrError());
		exit(1);
	}
	RuseAs(out, AppIsClassified(valueScale) ? CR_INT4 : CR_REAL8);

	if(angleOut != 0)
		aligned = FALSE;


	/* determine raster size according wanted accuracy */
	if(opB != 1 && opMV != 1)
	{
		if(DetRasterSize(out, in, nrMaps, errFactor))
		{
			Error("Illegal cell size\n");
			exit(1);
		}
	}
	else
		rasterSize = 1;

	if(nrMaps > 1 && percent > 0)
		AppProgress("rasterSize: %d\n", rasterSize);
	else
		AppProgress("No raster used\n");

	/* Call function */
	if(AppIsClassified(valueScale))
	{	/* Call resample function for classified maps */

		if(SampleClass(out, in, percent, nrMaps, nrRows, nrCols,
		   aligned, angleOut))
		{	
			EndResample(in, nrMaps, out);
			exit(1);	/* Memory allocation failed */
		}	
	}		
	else
	{	/* Call resample function for continuous maps */
		if(SampleCont(out, in, percent, nrMaps, nrRows, nrCols,
		   aligned, angleOut))
		{	
			EndResample(in, nrMaps, out);
			exit(1);	/* Memory allocation failed */
		}	
	}		

	/* End of call */
	if (keepInputMinMax) {
		RuseAs(out, CR_REAL8);
		RputMinVal(out, &minAllInput);
		RputMaxVal(out, &maxAllInput);
	}
	EndResample(in, nrMaps, out);
	
	exit(0);  			/* Successful exit */
	return 0; 			/* Never reached */
} /* main */