LCOV - code coverage report
Current view: directory - frmts/arg - argdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 375 293 78.1 %
Date: 2012-04-28 Functions: 16 12 75.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: argdataset.cpp 24219 2012-04-11 21:02:14Z dzwarg $
       3                 :  *
       4                 :  * Project:  Azavea Raster Grid format driver.
       5                 :  * Purpose:  Implements support for reading and writing Azavea Raster Grid
       6                 :  *           format.
       7                 :  * Author:   David Zwarg <dzwarg@azavea.com>
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2012, David Zwarg <dzwarg@azavea.com>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "rawdataset.h"
      32                 : #include "cpl_string.h"
      33                 : #include "jsonc/json.h"
      34                 : #include "jsonc/json_util.h"
      35                 : #include <ogr_spatialref.h>
      36                 : 
      37                 : CPL_CVSID("$Id: argdataset.cpp 24219 2012-04-11 21:02:14Z dzwarg $");
      38                 : 
      39                 : #define MAX_FILENAME_LEN 4096
      40                 : 
      41                 : #ifndef NAN
      42                 : #  ifdef HUGE_VAL
      43                 : #    define NAN (HUGE_VAL * 0.0)
      44                 : #  else
      45                 : 
      46                 : static float CPLNaN(void)
      47                 : {
      48                 :     float fNan;
      49                 :     int nNan = 0x7FC00000;
      50                 :     memcpy(&fNan, &nNan, 4);
      51                 :     return fNan;
      52                 : }
      53                 : 
      54                 : #    define NAN CPLNaN()
      55                 : #  endif
      56                 : #endif
      57                 : 
      58                 : /************************************************************************/
      59                 : /* ==================================================================== */
      60                 : /*        ARGDataset                                        */
      61                 : /* ==================================================================== */
      62                 : /************************************************************************/
      63                 : 
      64                 : class ARGDataset : public RawDataset
      65                 : {
      66                 :         VSILFILE  *fpImage; // image data file.
      67                 :     
      68                 :         double  adfGeoTransform[6];
      69                 :         char * pszFilename;
      70                 : 
      71                 :     public:
      72                 :         ARGDataset();
      73                 :         ~ARGDataset();
      74                 : 
      75                 :         CPLErr  GetGeoTransform( double * padfTransform );
      76                 :    
      77                 :         static int Identify( GDALOpenInfo * );
      78                 :         static GDALDataset *Open( GDALOpenInfo * );
      79                 :         static GDALDataset *CreateCopy( const char *, GDALDataset *, int, 
      80                 :             char **, GDALProgressFunc, void *);
      81                 :         virtual char ** GetFileList(void);
      82                 : }; 
      83                 : 
      84                 : /************************************************************************/
      85                 : /*                            ARGDataset()                              */
      86                 : /************************************************************************/
      87                 : 
      88              62 : ARGDataset::ARGDataset()
      89                 : {
      90              62 :     adfGeoTransform[0] = 0.0;
      91              62 :     adfGeoTransform[1] = 1.0;
      92              62 :     adfGeoTransform[2] = 0.0;
      93              62 :     adfGeoTransform[3] = 0.0;
      94              62 :     adfGeoTransform[4] = 0.0;
      95              62 :     adfGeoTransform[5] = 1.0;
      96              62 :     fpImage = NULL;
      97              62 : }
      98                 : 
      99                 : /************************************************************************/
     100                 : /*                            ~ARGDataset()                             */
     101                 : /************************************************************************/
     102                 : 
     103              62 : ARGDataset::~ARGDataset()
     104                 : 
     105                 : {
     106              62 :     CPLFree(pszFilename);
     107                 : 
     108              62 :     FlushCache();
     109              62 :     if( fpImage != NULL )
     110              60 :         VSIFCloseL( fpImage );
     111              62 : }
     112                 : 
     113                 : /************************************************************************/
     114                 : /*                          GetGeoTransform()                           */
     115                 : /************************************************************************/
     116                 : 
     117              18 : CPLErr ARGDataset::GetGeoTransform( double * padfTransform )
     118                 : 
     119                 : {
     120              18 :     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     121                 : 
     122              18 :     return CE_None;
     123                 : }
     124                 : 
     125                 : /************************************************************************/
     126                 : /*                         GetJsonFilename()                            */
     127                 : /************************************************************************/
     128             174 : CPLString GetJsonFilename(CPLString pszFilename) 
     129                 : {
     130             174 :     return CPLSPrintf( "%s/%s.json", CPLGetDirname(pszFilename), CPLGetBasename(pszFilename) );
     131                 : }
     132                 : 
     133                 : /************************************************************************/
     134                 : /*                           GetJsonObject()                            */
     135                 : /************************************************************************/
     136             152 : json_object * GetJsonObject(CPLString pszFilename) 
     137                 : {
     138             152 :     json_object * pJSONObject = NULL;
     139             152 :     CPLString pszJSONFilename = GetJsonFilename(pszFilename);
     140                 : 
     141             152 :     pJSONObject = json_object_from_file((char *)pszJSONFilename.c_str());
     142             152 :     if (is_error(pJSONObject) || pJSONObject == NULL) {
     143                 :         CPLDebug("ARGDataset", "GetJsonObject(): "
     144               2 :             "Could not parse JSON file.");
     145               2 :         return NULL;
     146                 :     }
     147                 : 
     148             150 :     return pJSONObject;
     149                 : }
     150                 : 
     151                 : /************************************************************************/
     152                 : /*                          GetJsonValueStr()                           */
     153                 : /************************************************************************/
     154             892 : const char * GetJsonValueStr(json_object * pJSONObject, CPLString pszKey) 
     155                 : {
     156             892 :     json_object * pJSONItem = json_object_object_get(pJSONObject, pszKey.c_str());
     157             892 :     if (pJSONItem == NULL) {
     158                 :         CPLDebug("ARGDataset", "GetJsonValueStr(): "
     159             162 :             "Could not find '%s' in JSON.", pszKey.c_str());
     160             162 :         return NULL;
     161                 :     }
     162                 : 
     163             730 :     return json_object_get_string(pJSONItem);
     164                 : }
     165                 : 
     166                 : /************************************************************************/
     167                 : /*                          GetJsonValueDbl()                           */
     168                 : /************************************************************************/
     169             682 : double GetJsonValueDbl(json_object * pJSONObject, CPLString pszKey) 
     170                 : {
     171             682 :     const char *pszJSONStr = GetJsonValueStr(pJSONObject, pszKey.c_str());
     172                 :     char *pszTmp;
     173                 :     double fTmp;
     174             682 :     if (pszJSONStr == NULL) {
     175             162 :         return NAN;
     176                 :     }
     177             520 :     pszTmp = (char *)pszJSONStr;
     178             520 :     fTmp = CPLStrtod(pszJSONStr, &pszTmp);
     179             520 :     if (pszTmp == pszJSONStr) {
     180                 :         CPLDebug("ARGDataset", "GetJsonValueDbl(): "
     181               0 :             "Key value is not a numeric value: %s:%s", pszKey.c_str(), pszTmp);
     182               0 :         return NAN;
     183                 :     }
     184                 : 
     185             520 :     return fTmp;
     186                 : }
     187                 : 
     188                 : /************************************************************************/
     189                 : /*                           GetJsonValueInt()                          */
     190                 : /************************************************************************/
     191             186 : int GetJsonValueInt(json_object * pJSONObject, CPLString pszKey) 
     192                 : {
     193             186 :     double fTmp = GetJsonValueDbl(pJSONObject, pszKey.c_str());
     194             186 :     if (CPLIsNan(fTmp)) {
     195              54 :         return -1;
     196                 :     }
     197                 : 
     198             132 :     return (int)fTmp;
     199                 : }
     200                 : 
     201                 : /************************************************************************/
     202                 : /*                            GetFileList()                             */
     203                 : /************************************************************************/
     204               0 : char ** ARGDataset::GetFileList()
     205                 : {
     206               0 :     char **papszFileList = GDALPamDataset::GetFileList();
     207               0 :     CPLString pszJSONFilename = GetJsonFilename(pszFilename);
     208                 : 
     209               0 :     papszFileList = CSLAddString( papszFileList, pszJSONFilename );
     210                 : 
     211               0 :     return papszFileList;
     212                 : }
     213                 : 
     214                 : /************************************************************************/
     215                 : /*                              Identify()                              */
     216                 : /************************************************************************/
     217                 : 
     218           22420 : int ARGDataset::Identify( GDALOpenInfo *poOpenInfo )
     219                 : {
     220                 :     json_object * pJSONObject;
     221           22420 :     if (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "arg")) {
     222           22342 :         return FALSE;
     223                 :     }
     224                 : 
     225              78 :     pJSONObject = GetJsonObject(poOpenInfo->pszFilename);
     226              78 :     if (pJSONObject == NULL) {
     227               2 :         return FALSE;
     228                 :     }
     229                 : 
     230              76 :     if (is_error(pJSONObject)) {
     231               0 :         json_object_put(pJSONObject);
     232               0 :         pJSONObject = NULL;
     233                 : 
     234               0 :         return FALSE;
     235                 :     }
     236                 : 
     237              76 :     json_object_put(pJSONObject);
     238              76 :     pJSONObject = NULL;
     239                 : 
     240              76 :     return TRUE;
     241                 : }
     242                 : 
     243                 : /************************************************************************/
     244                 : /*                                Open()                                */
     245                 : /************************************************************************/
     246            3510 : GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
     247                 : {
     248                 :     json_object * pJSONObject;
     249                 :     const char * pszJSONStr;
     250                 :     char * pszLayer;
     251                 :     /***** items from the json metadata *****/
     252            3510 :     GDALDataType eType = GDT_Unknown;
     253            3510 :     double fXmin = 0.0;
     254            3510 :     double fYmin = 0.0;
     255            3510 :     double fXmax = 0.0;
     256            3510 :     double fYmax = 0.0;
     257            3510 :     double fCellwidth = 1.0;
     258            3510 :     double fCellheight = 1.0;
     259            3510 :     double fXSkew = 0.0;
     260            3510 :     double fYSkew = 0.0;
     261            3510 :     int nRows = 0;
     262            3510 :     int nCols = 0;
     263            3510 :     int nSrs = 3857;
     264                 :     /***** items from the json metadata *****/
     265            3510 :     int nPixelOffset = 0;
     266            3510 :     double fNoDataValue = NAN;
     267                 : 
     268            3510 :     char * pszWKT = NULL;
     269            3510 :     OGRSpatialReference oSRS;
     270            3510 :     OGRErr nErr = OGRERR_NONE;
     271                 : 
     272            3510 :     if ( !Identify( poOpenInfo ) )
     273            3436 :         return NULL;
     274                 : 
     275                 : /* -------------------------------------------------------------------- */
     276                 : /*      Check metadata settings in JSON.                                */
     277                 : /* -------------------------------------------------------------------- */
     278                 : 
     279              74 :     pJSONObject = GetJsonObject(poOpenInfo->pszFilename);
     280                 : 
     281              74 :     if (is_error(pJSONObject)) {
     282               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Error parsing JSON.");
     283               0 :         json_object_put(pJSONObject);
     284               0 :         pJSONObject = NULL;
     285               0 :         return NULL;
     286                 :     }
     287                 : 
     288                 :     // get the type (always 'arg')
     289              74 :     pszJSONStr = GetJsonValueStr(pJSONObject, "type");
     290              74 :     if (pszJSONStr == NULL ) {
     291                 :         CPLError(CE_Failure, CPLE_AppDefined,
     292               0 :             "The ARG 'type' is missing from the JSON file.");
     293               0 :         json_object_put(pJSONObject);
     294               0 :         pJSONObject = NULL;
     295               0 :         return NULL;
     296                 :     }
     297              74 :     else if (!EQUAL(pszJSONStr, "arg")) {
     298                 :         CPLError(CE_Failure, CPLE_AppDefined,
     299               0 :             "The ARG 'type' is not recognized: '%s'.", pszJSONStr);
     300               0 :         json_object_put(pJSONObject);
     301               0 :         pJSONObject = NULL;
     302               0 :         return NULL;
     303                 :     }
     304                 : 
     305                 :     // get the datatype
     306              74 :     pszJSONStr = GetJsonValueStr(pJSONObject, "datatype");
     307              74 :     if (pszJSONStr == NULL) {
     308                 :         CPLError(CE_Failure, CPLE_AppDefined,
     309               0 :             "The ARG 'datatype' is missing from the JSON file.");
     310               0 :         json_object_put(pJSONObject);
     311               0 :         pJSONObject = NULL;
     312               0 :         return NULL;
     313                 :     }
     314              74 :     else if (EQUAL(pszJSONStr, "int8")) {
     315                 :         CPLDebug("ARGDataset", "Open(): "
     316               8 :             "int8 data is not supported in GDAL -- mapped to uint8");
     317               8 :         eType = GDT_Byte; 
     318               8 :         nPixelOffset = 1;
     319               8 :         fNoDataValue = 128;
     320                 :     }
     321              66 :     else if (EQUAL(pszJSONStr, "int16")) {
     322              15 :         eType = GDT_Int16;
     323              15 :         nPixelOffset = 2;
     324              15 :         fNoDataValue = -32767;
     325                 :     }
     326              51 :     else if (EQUAL(pszJSONStr, "int32")) {
     327               6 :         eType = GDT_Int32;
     328               6 :         nPixelOffset = 4;
     329               6 :         fNoDataValue = -2e31;
     330                 :     }
     331              45 :     else if (EQUAL(pszJSONStr, "uint8")) {
     332               9 :         eType = GDT_Byte; 
     333               9 :         nPixelOffset = 1;
     334               9 :         fNoDataValue = 255;
     335                 :     }
     336              36 :     else if (EQUAL(pszJSONStr, "uint16")) {
     337               6 :         eType = GDT_UInt16;
     338               6 :         nPixelOffset = 2;
     339               6 :         fNoDataValue = 65535;
     340                 :     }
     341              30 :     else if (EQUAL(pszJSONStr, "uint32")) {
     342               6 :         eType = GDT_UInt32;
     343               6 :         nPixelOffset = 4;
     344               6 :         fNoDataValue = -2e31;
     345                 :     }
     346              24 :     else if (EQUAL(pszJSONStr, "float32")) {
     347               6 :         eType = GDT_Float32;
     348               6 :         nPixelOffset = 4;
     349               6 :         fNoDataValue = NAN;
     350                 :     }
     351              18 :     else if (EQUAL(pszJSONStr, "float64")) { 
     352               6 :         eType = GDT_Float64;
     353               6 :         nPixelOffset = 8;
     354               6 :         fNoDataValue = NAN;
     355                 :     }
     356                 :     else {
     357              24 :         if (EQUAL(pszJSONStr, "int64") ||
     358                 :             EQUAL(pszJSONStr, "uint64")) {
     359                 :             CPLError(CE_Failure, CPLE_AppDefined,
     360              12 :                 "The ARG 'datatype' is unsupported in GDAL: '%s'.", pszJSONStr);
     361                 :         }
     362                 :         else {
     363                 :             CPLError(CE_Failure, CPLE_AppDefined,
     364               0 :                 "The ARG 'datatype' is unknown: '%s'.", pszJSONStr);
     365                 :         }
     366              12 :         json_object_put(pJSONObject);
     367              12 :         pJSONObject = NULL;
     368              12 :         return NULL;
     369                 :     }
     370                 : 
     371                 :     // get the xmin of the bounding box
     372              62 :     fXmin = GetJsonValueDbl(pJSONObject, "xmin");
     373              62 :     if (CPLIsNan(fXmin)) {
     374                 :         CPLError(CE_Failure, CPLE_AppDefined,
     375               0 :             "The ARG 'xmin' is missing or invalid.");
     376               0 :         json_object_put(pJSONObject);
     377               0 :         pJSONObject = NULL;
     378               0 :         return NULL;
     379                 :     }
     380                 :     
     381                 :     // get the ymin of the bounding box
     382              62 :     fYmin = GetJsonValueDbl(pJSONObject, "ymin");
     383              62 :     if (CPLIsNan(fYmin)) {
     384                 :         CPLError(CE_Failure, CPLE_AppDefined,
     385               0 :             "The ARG 'ymin' is missing or invalid.");
     386               0 :         json_object_put(pJSONObject);
     387               0 :         pJSONObject = NULL;
     388               0 :         return NULL;
     389                 :     }
     390                 : 
     391                 :     // get the xmax of the bounding box
     392              62 :     fXmax = GetJsonValueDbl(pJSONObject, "xmax");
     393              62 :     if (CPLIsNan(fXmax)) {
     394                 :         CPLError(CE_Failure, CPLE_AppDefined,
     395               0 :             "The ARG 'xmax' is missing or invalid.");
     396               0 :         json_object_put(pJSONObject);
     397               0 :         pJSONObject = NULL;
     398               0 :         return NULL;
     399                 :     }
     400                 : 
     401                 :     // get the ymax of the bounding box
     402              62 :     fYmax = GetJsonValueDbl(pJSONObject, "ymax");
     403              62 :     if (CPLIsNan(fYmax)) {
     404                 :         CPLError(CE_Failure, CPLE_AppDefined,
     405               0 :             "The ARG 'ymax' is missing or invalid.");
     406               0 :         json_object_put(pJSONObject);
     407               0 :         pJSONObject = NULL;
     408               0 :         return NULL;
     409                 :     }
     410                 : 
     411                 :     // get the cell width
     412              62 :     fCellwidth = GetJsonValueDbl(pJSONObject, "cellwidth");
     413              62 :     if (CPLIsNan(fCellwidth)) {
     414                 :         CPLError(CE_Failure, CPLE_AppDefined,
     415               0 :             "The ARG 'cellwidth' is missing or invalid.");
     416               0 :         json_object_put(pJSONObject);
     417               0 :         pJSONObject = NULL;
     418               0 :         return NULL;
     419                 :     }
     420                 : 
     421                 :     // get the cell height
     422              62 :     fCellheight = GetJsonValueDbl(pJSONObject, "cellheight");
     423              62 :     if (CPLIsNan(fCellheight)) {
     424                 :         CPLError(CE_Failure, CPLE_AppDefined,
     425               0 :             "The ARG 'cellheight' is missing or invalid.");
     426               0 :         json_object_put(pJSONObject);
     427               0 :         pJSONObject = NULL;
     428               0 :         return NULL;
     429                 :     }
     430                 : 
     431              62 :     fXSkew = GetJsonValueDbl(pJSONObject, "xskew");
     432              62 :     if (CPLIsNan(fXSkew)) {
     433                 :         // not an error -- default to 0.0
     434              54 :         fXSkew = 0.0f;
     435                 :     }
     436                 : 
     437              62 :     fYSkew = GetJsonValueDbl(pJSONObject, "yskew");
     438              62 :     if (CPLIsNan(fYSkew)) {
     439                 :         // not an error -- default to 0.0
     440              54 :         fYSkew = 0.0f;
     441                 :     }
     442                 : 
     443                 :     // get the rows
     444              62 :     nRows = GetJsonValueInt(pJSONObject, "rows");
     445              62 :     if (nRows < 0) {
     446                 :         CPLError(CE_Failure, CPLE_AppDefined,
     447               0 :             "The ARG 'rows' is missing or invalid.");
     448               0 :         json_object_put(pJSONObject);
     449               0 :         pJSONObject = NULL;
     450               0 :         return NULL;
     451                 :     }
     452                 : 
     453                 :     // get the columns
     454              62 :     nCols = GetJsonValueInt(pJSONObject, "cols");
     455              62 :     if (nCols < 0) {
     456                 :         CPLError(CE_Failure, CPLE_AppDefined,
     457               0 :             "The ARG 'cols' is missing or invalid.");
     458               0 :         json_object_put(pJSONObject);
     459               0 :         pJSONObject = NULL;
     460               0 :         return NULL;
     461                 :     }
     462                 : 
     463              62 :     nSrs = GetJsonValueInt(pJSONObject, "epsg");
     464              62 :     if (nSrs < 0) {
     465                 :         // not an error -- default to web mercator
     466              54 :         nSrs = 3857;
     467                 :     }
     468                 : 
     469              62 :     nErr = oSRS.importFromEPSG(nSrs);
     470              62 :     if (nErr != OGRERR_NONE) {
     471               0 :         nErr = oSRS.importFromEPSG(3857);
     472                 : 
     473               0 :         if (nErr == OGRERR_NONE) {
     474                 :             CPLDebug("ARGDataset", "Open(): "
     475               0 :                 "The EPSG provided did not import cleanly. Defaulting to EPSG:3857");
     476                 :         }
     477                 :         else {
     478                 :             CPLError(CE_Failure, CPLE_AppDefined,
     479                 :                 "The 'epsg' value did not transate to a known spatial reference."
     480               0 :                 " Please check the 'epsg' value and try again.");
     481                 : 
     482               0 :             json_object_put(pJSONObject);
     483               0 :             pJSONObject = NULL;
     484                 : 
     485               0 :             return NULL;
     486                 :         }
     487                 :     }
     488                 : 
     489              62 :     nErr = oSRS.exportToWkt(&pszWKT);
     490              62 :     if (nErr != OGRERR_NONE) {
     491                 :         CPLError(CE_Failure, CPLE_AppDefined,
     492                 :             "The spatial reference is known, but could not be set on the "
     493               0 :             "dataset. Please check the 'epsg' value and try again.");
     494                 : 
     495               0 :         json_object_put(pJSONObject);
     496               0 :         pJSONObject = NULL;
     497                 : 
     498               0 :         return NULL;
     499                 :     }
     500                 : 
     501                 :     // get the layer (always the file basename)
     502              62 :     pszJSONStr = GetJsonValueStr(pJSONObject, "layer");
     503              62 :     if (pszJSONStr == NULL) {
     504                 :         CPLError(CE_Failure, CPLE_AppDefined,
     505               0 :             "The ARG 'layer' is missing from the JSON file.");
     506               0 :         json_object_put(pJSONObject);
     507               0 :         pJSONObject = NULL;
     508               0 :         return NULL;
     509                 :     }
     510                 : 
     511              62 :     pszLayer = CPLStrdup(pszJSONStr);
     512                 : 
     513                 :     // done with the json object now
     514              62 :     json_object_put(pJSONObject);
     515              62 :     pJSONObject = NULL;
     516                 : 
     517                 : /* -------------------------------------------------------------------- */
     518                 : /*      Create a corresponding GDALDataset.                             */
     519                 : /* -------------------------------------------------------------------- */
     520                 :     ARGDataset *poDS;
     521                 : 
     522              62 :     poDS = new ARGDataset();
     523                 : 
     524             124 :     poDS->pszFilename = CPLStrdup(poOpenInfo->pszFilename);
     525              62 :     poDS->SetMetadataItem("LAYER",pszLayer,NULL);
     526              62 :     poDS->nRasterXSize = nCols;
     527              62 :     poDS->nRasterYSize = nRows;
     528              62 :     poDS->SetProjection( pszWKT );
     529                 : 
     530                 :     // done with the projection string
     531              62 :     CPLFree(pszWKT);
     532              62 :     CPLFree(pszLayer);
     533                 : 
     534                 : /* -------------------------------------------------------------------- */
     535                 : /*      Assume ownership of the file handled from the GDALOpenInfo.     */
     536                 : /* -------------------------------------------------------------------- */
     537              62 :     poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     538              62 :     if (poDS->fpImage == NULL)
     539                 :     {
     540               2 :         delete poDS;
     541                 :         CPLError(CE_Failure, CPLE_AppDefined,
     542               2 :             "Could not open dataset '%s'", poOpenInfo->pszFilename);
     543               2 :         return NULL;
     544                 :     }
     545                 : 
     546              60 :     poDS->adfGeoTransform[0] = fXmin;
     547              60 :     poDS->adfGeoTransform[1] = fCellwidth;
     548              60 :     poDS->adfGeoTransform[2] = fXSkew;
     549              60 :     poDS->adfGeoTransform[3] = fYmax;
     550              60 :     poDS->adfGeoTransform[4] = fYSkew;
     551              60 :     poDS->adfGeoTransform[5] = -fCellheight;
     552                 :     
     553                 : /* -------------------------------------------------------------------- */
     554                 : /*      Create band information objects.                                */
     555                 : /* -------------------------------------------------------------------- */
     556                 :     RawRasterBand *poBand;
     557                 : #ifdef CPL_LSB
     558              60 :     int bNative = TRUE;
     559                 : #else
     560                 :     int bNative = FALSE;
     561                 : #endif
     562                 : 
     563                 :     poBand = new RawRasterBand( poDS, 1, poDS->fpImage,
     564                 :                                 0, nPixelOffset, nPixelOffset * nCols,
     565              60 :                                 eType, bNative, TRUE );
     566              60 :     poDS->SetBand( 1, poBand );
     567                 : 
     568              60 :     poBand->SetNoDataValue( fNoDataValue );
     569                 : 
     570                 : /* -------------------------------------------------------------------- */
     571                 : /*      Initialize any PAM information.                                 */
     572                 : /* -------------------------------------------------------------------- */
     573              60 :     poDS->SetDescription( poOpenInfo->pszFilename );
     574              60 :     poDS->TryLoadXML();
     575                 :     
     576                 : /* -------------------------------------------------------------------- */
     577                 : /*      Check for overviews.                                            */
     578                 : /* -------------------------------------------------------------------- */
     579              60 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     580                 : 
     581              60 :     return( poDS );
     582                 : }
     583                 : 
     584                 : /************************************************************************/
     585                 : /*                          CreateCopy()                                */
     586                 : /************************************************************************/
     587              40 : GDALDataset * ARGDataset::CreateCopy( const char * pszFilename, 
     588                 :     GDALDataset * poSrcDS, int bStrict, char ** papszOptions, 
     589                 :     GDALProgressFunc pfnProgress, void * pProgressData ) 
     590                 : {
     591              40 :     int nBands = poSrcDS->GetRasterCount();
     592              40 :     int nXSize = poSrcDS->GetRasterXSize();
     593              40 :     int nYSize = poSrcDS->GetRasterYSize();
     594                 :     int nXBlockSize, nYBlockSize, nPixelOffset;
     595                 :     GDALDataType eType;
     596              40 :     CPLString pszJSONFilename;
     597              40 :     CPLString pszDataType;
     598              40 :     json_object * poJSONObject = NULL;
     599                 :     double adfTransform[6];
     600              40 :     VSILFILE * fpImage = NULL;
     601              40 :     GDALRasterBand * poBand = NULL;
     602                 :     GByte * pabyData;
     603              40 :     OGRSpatialReference oSRS;
     604              40 :     char * pszWKT = NULL;
     605              40 :     char ** pszTokens = NULL;
     606              40 :     const char * pszLayer = NULL;
     607              40 :     int nSrs = 0;
     608              40 :     OGRErr nErr = OGRERR_NONE;
     609                 : 
     610              40 :     if( nBands != 1 )
     611                 :     {
     612                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     613              10 :               "ARG driver doesn't support %d bands.  Must be 1 band.", nBands );
     614              10 :         return NULL;
     615                 :     }
     616                 : 
     617              30 :     eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     618              30 :     if( eType == GDT_Unknown || 
     619                 :         eType == GDT_CInt16 || 
     620                 :         eType == GDT_CInt32 ||
     621                 :         eType == GDT_CFloat32 || 
     622                 :         eType == GDT_CFloat64 )
     623                 :     {
     624                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     625                 :                   "ARG driver doesn't support data type %s.",
     626               8 :                   GDALGetDataTypeName(eType) );
     627               8 :         return NULL;
     628                 :     }
     629              22 :     else if (eType == GDT_Int16) {
     630               4 :         pszDataType = "int16";
     631               4 :         nPixelOffset = 2;
     632                 :     }
     633              18 :     else if (eType == GDT_Int32) {
     634               2 :         pszDataType = "int32";
     635               2 :         nPixelOffset = 4;
     636                 :     }
     637              16 :     else if (eType == GDT_Byte) {
     638               8 :         pszDataType = "uint8";
     639               8 :         nPixelOffset = 1;
     640                 :     }
     641               8 :     else if (eType == GDT_UInt16) {
     642               2 :         pszDataType = "uint16";
     643               2 :         nPixelOffset = 2;
     644                 :     }
     645               6 :     else if (eType == GDT_UInt32) {
     646               2 :         pszDataType = "uint32";
     647               2 :         nPixelOffset = 4;
     648                 :     }
     649               4 :     else if (eType == GDT_Float32) {
     650               2 :         pszDataType = "float32";
     651               2 :         nPixelOffset = 4;
     652                 :     }
     653               2 :     else if (eType == GDT_Float64) {
     654               2 :         pszDataType = "float64";
     655               2 :         nPixelOffset = 8;
     656                 :     }
     657                 : 
     658              22 :     poSrcDS->GetGeoTransform( adfTransform );
     659                 : 
     660              22 :     pszWKT = (char *)poSrcDS->GetProjectionRef();
     661              22 :     nErr = oSRS.importFromWkt(&pszWKT);
     662              22 :     if (nErr != OGRERR_NONE) {
     663                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     664               0 :               "Cannot import spatial reference WKT from source dataset.");
     665               0 :         return NULL;
     666                 :     }
     667                 : 
     668              22 :     if (oSRS.GetAuthorityCode("PROJCS") != NULL) {
     669               4 :         nSrs = atoi(oSRS.GetAuthorityCode("PROJCS"));
     670                 :     }
     671              18 :     else if (oSRS.GetAuthorityCode("GEOGCS") != NULL) {
     672              14 :         nSrs = atoi(oSRS.GetAuthorityCode("GEOGCS"));
     673                 :     }
     674                 :     else {
     675                 :         // could not determine projected or geographic code
     676                 :         // default to EPSG:3857 if no code could be found
     677               4 :         nSrs = 3857;
     678                 :     }
     679                 : 
     680                 :     /********************************************************************/
     681                 :     /* Create JSON companion file.                                      */
     682                 :     /********************************************************************/
     683              22 :     pszJSONFilename = GetJsonFilename(pszFilename);
     684              22 :     if (pszJSONFilename == NULL) {
     685                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     686               0 :                   "ARG driver can't determine filename for companion file.");
     687               0 :         return NULL;
     688                 :     }
     689                 : 
     690              22 :     poJSONObject = json_object_new_object();
     691                 : 
     692              22 :     pszTokens = poSrcDS->GetMetadata();
     693              22 :     pszLayer = CSLFetchNameValue(pszTokens, "LAYER");
     694                 : 
     695              22 :     if ( pszLayer == NULL) {
     696                 :         // Set the layer
     697                 :         json_object_object_add(poJSONObject, "layer", json_object_new_string(
     698                 :             CPLGetBasename(pszJSONFilename)
     699              20 :         ));
     700                 :     }
     701                 :     else {
     702                 :         // Set the layer
     703                 :         json_object_object_add(poJSONObject, "layer", json_object_new_string(
     704                 :             pszLayer
     705               2 :         ));
     706                 :     }
     707                 : 
     708                 :     // Set the type
     709              22 :     json_object_object_add(poJSONObject, "type", json_object_new_string("arg"));
     710                 :     // Set the datatype
     711              22 :     json_object_object_add(poJSONObject, "datatype", json_object_new_string(pszDataType));
     712                 :     // Set the number of rows
     713              22 :     json_object_object_add(poJSONObject, "rows", json_object_new_int(nXSize));
     714                 :     // Set the number of columns
     715              22 :     json_object_object_add(poJSONObject, "cols", json_object_new_int(nYSize));
     716                 :     // Set the xmin
     717              22 :     json_object_object_add(poJSONObject, "xmin", json_object_new_double(adfTransform[0]));
     718                 :     // Set the ymax
     719              22 :     json_object_object_add(poJSONObject, "ymax", json_object_new_double(adfTransform[3]));
     720                 :     // Set the cellwidth
     721              22 :     json_object_object_add(poJSONObject, "cellwidth", json_object_new_double(adfTransform[1]));
     722                 :     // Set the cellheight
     723              22 :     json_object_object_add(poJSONObject, "cellheight", json_object_new_double(-adfTransform[5]));
     724                 :     // Set the xmax
     725              22 :     json_object_object_add(poJSONObject, "xmax", json_object_new_double(adfTransform[0] + nXSize * adfTransform[1]));
     726                 :     // Set the ymin
     727              22 :     json_object_object_add(poJSONObject, "ymin", json_object_new_double(adfTransform[3] + nYSize * adfTransform[5]));
     728                 :     // Set the xskew
     729              22 :     json_object_object_add(poJSONObject, "xskew", json_object_new_double(adfTransform[2]));
     730                 :     // Set the yskew
     731              22 :     json_object_object_add(poJSONObject, "yskew", json_object_new_double(adfTransform[4]));
     732              22 :     if (nSrs > 0) {
     733                 :         // Set the epsg
     734              22 :         json_object_object_add(poJSONObject, "epsg", json_object_new_int(nSrs));
     735                 :     }
     736                 : 
     737              22 :     if (json_object_to_file((char *)pszJSONFilename.c_str(), poJSONObject) < 0) {
     738                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     739               4 :                   "ARG driver can't write companion file.");
     740                 : 
     741               4 :         json_object_put(poJSONObject);
     742               4 :         poJSONObject = NULL;
     743                 : 
     744               4 :         return NULL;
     745                 :     }
     746                 : 
     747              18 :     json_object_put(poJSONObject);
     748              18 :     poJSONObject = NULL;
     749                 : 
     750              18 :     fpImage = VSIFOpenL(pszFilename, "wb");
     751              18 :     if (fpImage == NULL)
     752                 :     {
     753                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     754               0 :               "ARG driver can't create data file %s.", pszFilename);
     755                 : 
     756                 :         // remove JSON file
     757               0 :         VSIUnlink( pszJSONFilename.c_str() );
     758                 : 
     759               0 :         return NULL;
     760                 :     }
     761                 : 
     762                 :     // only 1 raster band
     763              18 :     poBand = poSrcDS->GetRasterBand( 1 );
     764                 : 
     765              18 :     poBand->GetBlockSize(&nXBlockSize, &nYBlockSize);
     766                 : 
     767              18 :     pabyData = (GByte *) CPLMalloc(nXBlockSize * nYBlockSize * nPixelOffset);
     768                 : 
     769                 :     // convert any blocks into scanlines
     770              78 :     for (int nYBlock = 0; nYBlock * nYBlockSize < nYSize; nYBlock++) {
     771            1254 :         for (int nYScanline = 0; nYScanline < nYBlockSize; nYScanline++) {
     772            1194 :             if ((nYScanline+1) + nYBlock * nYBlockSize > poBand->GetYSize() ) {
     773              26 :                 continue;
     774                 :             }
     775                 : 
     776            2336 :             for (int nXBlock = 0; nXBlock * nXBlockSize < nXSize; nXBlock++) {
     777                 :                 int nXValid;
     778                 : 
     779            1168 :                 poBand->ReadBlock(nXBlock, nYBlock, pabyData);
     780                 : 
     781            1168 :                 if( (nXBlock+1) * nXBlockSize > poBand->GetXSize() )
     782               0 :                     nXValid = poBand->GetXSize() - nXBlock * nXBlockSize;
     783                 :                 else
     784            1168 :                     nXValid = nXBlockSize;
     785                 : 
     786            1168 :                 VSIFWriteL( pabyData + (nYScanline * nXBlockSize * nPixelOffset), nPixelOffset, nXValid, fpImage );
     787                 :             }
     788                 :         }
     789                 :     }
     790                 : 
     791              18 :     CPLFree( pabyData );
     792              18 :     VSIFCloseL( fpImage );
     793                 : 
     794              18 :     return (GDALDataset *)GDALOpen( pszFilename, GA_ReadOnly );
     795                 : }
     796                 : 
     797                 : /************************************************************************/
     798                 : /*                          GDALRegister_ARG()                          */
     799                 : /************************************************************************/
     800                 : 
     801            1135 : void GDALRegister_ARG()
     802                 : {
     803                 :     GDALDriver  *poDriver;
     804                 : 
     805            1135 :     if( GDALGetDriverByName( "ARG" ) == NULL )
     806                 :     {
     807            1093 :         poDriver = new GDALDriver();
     808                 :         
     809            1093 :         poDriver->SetDescription( "ARG" );
     810                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     811            1093 :                                    "Azavea Raster Grid format" );
     812                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     813            1093 :                                    "frmt_various.html#ARG" );
     814            1093 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     815                 : 
     816            1093 :         poDriver->pfnIdentify = ARGDataset::Identify;
     817            1093 :         poDriver->pfnOpen = ARGDataset::Open;
     818            1093 :         poDriver->pfnCreateCopy = ARGDataset::CreateCopy;
     819                 : 
     820            1093 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     821                 :     }
     822            1135 : }
     823                 : 

Generated by: LCOV version 1.7