/*! \warning The source raster must have only 1 band. Currently, the values in the source raster must be stored in one of the supported cell representations (CR_UINT1, CR_INT4, CR_REAL4, CR_REAL8). The meta data item PCRASTER_VALUESCALE will be checked to see what value scale to use. Otherwise a value scale is determined using GDALType2ValueScale(GDALDataType). This function always writes rasters using CR_UINT1, CR_INT4 or CR_REAL4 cell representations. */ GDALDataset* PCRasterDataset::createCopy( char const* filename, GDALDataset* source, CPL_UNUSED int strict, CPL_UNUSED char** options, GDALProgressFunc progress, void* progressData) { // Checks. int nrBands = source->GetRasterCount(); if(nrBands != 1) { CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver: Too many bands ('%d'): must be 1 band", nrBands); return 0; } GDALRasterBand* raster = source->GetRasterBand(1); // Create PCRaster raster. Determine properties of raster to create. size_t nrRows = raster->GetYSize(); size_t nrCols = raster->GetXSize(); std::string string; // The in-file type of the cells. CSF_CR fileCellRepresentation = GDALType2CellRepresentation( raster->GetRasterDataType(), false); if(fileCellRepresentation == CR_UNDEFINED) { CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver: Cannot determine a valid cell representation"); return 0; } // The value scale of the values. CSF_VS valueScale = VS_UNDEFINED; if(source->GetMetadataItem("PCRASTER_VALUESCALE")) { string = source->GetMetadataItem("PCRASTER_VALUESCALE"); } valueScale = !string.empty() ? string2ValueScale(string) : GDALType2ValueScale(raster->GetRasterDataType()); if(valueScale == VS_UNDEFINED) { CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver: Cannot determine a valid value scale"); return 0; } CSF_PT const projection = PT_YDECT2B; REAL8 const angle = 0.0; REAL8 west = 0.0; REAL8 north = 0.0; REAL8 cellSize = 1.0; double transform[6]; if(source->GetGeoTransform(transform) == CE_None) { if(transform[2] == 0.0 && transform[4] == 0.0) { west = static_cast<REAL8>(transform[0]); north = static_cast<REAL8>(transform[3]); cellSize = static_cast<REAL8>(transform[1]); } } // The in-memory type of the cells. CSF_CR appCellRepresentation = CR_UNDEFINED; appCellRepresentation = GDALType2CellRepresentation( raster->GetRasterDataType(), true); if(appCellRepresentation == CR_UNDEFINED) { CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver: Cannot determine a valid cell representation"); return 0; } // Check whether value scale fits the cell representation. Adjust when // needed. valueScale = fitValueScale(valueScale, appCellRepresentation); // Create a raster with the in file cell representation. MAP* map = Rcreate(filename, nrRows, nrCols, fileCellRepresentation, valueScale, projection, west, north, angle, cellSize); if(!map) { CPLError(CE_Failure, CPLE_OpenFailed, "PCRaster driver: Unable to create raster %s", filename); return 0; } // Try to convert in app cell representation to the cell representation // of the file. if(RuseAs(map, appCellRepresentation)) { CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver: Cannot convert cells: %s", MstrError()); Mclose(map); return 0; } int hasMissingValue; double missingValue = raster->GetNoDataValue(&hasMissingValue); // This is needed to get my (KDJ) unit tests running. // I am still uncertain why this is needed. If the input raster has float32 // values and the output int32, than the missing value in the dataset object // is not updated like the values are. if(missingValue == ::missingValue(CR_REAL4) && fileCellRepresentation == CR_INT4) { missingValue = ::missingValue(fileCellRepresentation); } // TODO conversie van INT2 naar INT4 ondersteunen. zie ruseas.c regel 503. // conversie op r 159. // Create buffer for one row of values. void* buffer = Rmalloc(map, nrCols); // Copy values from source to target. CPLErr errorCode = CE_None; for(size_t row = 0; errorCode == CE_None && row < nrRows; ++row) { // Get row from source. if(raster->RasterIO(GF_Read, 0, row, nrCols, 1, buffer, nrCols, 1, raster->GetRasterDataType(), 0, 0, NULL) != CE_None) { CPLError(CE_Failure, CPLE_FileIO, "PCRaster driver: Error reading from source raster"); errorCode = CE_Failure; break; } // Upon reading values are converted to the // right data type. This includes the missing value. If the source // value cannot be represented in the target data type it is set to a // missing value. if(hasMissingValue) { alterToStdMV(buffer, nrCols, appCellRepresentation, missingValue); } if(valueScale == VS_BOOLEAN) { castValuesToBooleanRange(buffer, nrCols, appCellRepresentation); } // Write row in target. RputRow(map, row, buffer); if(!progress((row + 1) / (static_cast<double>(nrRows)), 0, progressData)) { CPLError(CE_Failure, CPLE_UserInterrupt, "PCRaster driver: User terminated CreateCopy()"); errorCode = CE_Failure; break; } } Mclose(map); map = 0; free(buffer); buffer = 0; if( errorCode != CE_None ) return NULL; /* -------------------------------------------------------------------- */ /* Re-open dataset, and copy any auxiliary pam information. */ /* -------------------------------------------------------------------- */ GDALPamDataset *poDS = (GDALPamDataset *) GDALOpen( filename, GA_Update ); if( poDS ) poDS->CloneInfo( source, GCIF_PAM_DEFAULT ); return poDS; }
GDALDataset* PCRasterDataset::create( const char* filename, int nr_cols, int nr_rows, int nrBands, GDALDataType gdalType, char** papszParmList) { // Checks if(nrBands != 1){ CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver : " "attempt to create dataset with too many bands (%d); " "must be 1 band.\n", nrBands); return NULL; } int row_col_max = INT4_MAX - 1; if(nr_cols > row_col_max){ CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver : " "attempt to create dataset with too many columns (%d); " "must be smaller than %d.", nr_cols, row_col_max); return NULL; } if(nr_rows > row_col_max){ CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver : " "attempt to create dataset with too many rows (%d); " "must be smaller than %d.", nr_rows, row_col_max); return NULL; } if(gdalType != GDT_Byte && gdalType != GDT_Int32 && gdalType != GDT_Float32){ CPLError( CE_Failure, CPLE_AppDefined, "PCRaster driver: " "attempt to create dataset with an illegal data type (%s); " "use either Byte, Int32 or Float32.", GDALGetDataTypeName(gdalType)); return NULL; } // value scale must be specified by the user, // determines cell representation const char *valueScale = CSLFetchNameValue( papszParmList,"PCRASTER_VALUESCALE"); if(valueScale == NULL){ CPLError(CE_Failure, CPLE_AppDefined, "PCRaster driver: value scale can not be determined; " "specify PCRASTER_VALUESCALE."); return NULL; } CSF_VS csf_value_scale = string2ValueScale(valueScale); if(csf_value_scale == VS_UNDEFINED){ CPLError( CE_Failure, CPLE_AppDefined, "PCRaster driver: value scale can not be determined (%s); " "use either VS_BOOLEAN, VS_NOMINAL, VS_ORDINAL, VS_SCALAR, " "VS_DIRECTION, VS_LDD", valueScale); return NULL; } CSF_CR csf_cell_representation = GDALType2CellRepresentation(gdalType, false); // default values REAL8 west = 0.0; REAL8 north = 0.0; REAL8 length = 1.0; REAL8 angle = 0.0; CSF_PT projection = PT_YDECT2B; // Create a new raster MAP* map = Rcreate(filename, nr_rows, nr_cols, csf_cell_representation, csf_value_scale, projection, west, north, angle, length); if(!map){ CPLError(CE_Failure, CPLE_OpenFailed, "PCRaster driver: Unable to create raster %s", filename); return NULL; } Mclose(map); map = NULL; /* -------------------------------------------------------------------- */ /* Re-open dataset, and copy any auxiliary pam information. */ /* -------------------------------------------------------------------- */ GDALPamDataset *poDS = (GDALPamDataset *) GDALOpen(filename, GA_Update); return poDS; }
/* 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 */