LCOV - code coverage report
Current view: top level - frmts/r - rcreatecopy.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 76 81 93.8 %
Date: 2024-05-02 22:57:13 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  R Format Driver
       4             :  * Purpose:  CreateCopy() implementation for R stats package object format.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "cpl_port.h"
      30             : #include "rdataset.h"
      31             : 
      32             : #include <cstdio>
      33             : #include <cstring>
      34             : #include <string>
      35             : 
      36             : #include "cpl_conv.h"
      37             : #include "cpl_error.h"
      38             : #include "cpl_progress.h"
      39             : #include "cpl_string.h"
      40             : #include "cpl_vsi.h"
      41             : #include "gdal.h"
      42             : #include "gdal_pam.h"
      43             : #include "gdal_priv.h"
      44             : 
      45             : GDALDataset *RCreateCopy(const char *pszFilename, GDALDataset *poSrcDS,
      46             :                          int bStrict, char **papszOptions,
      47             :                          GDALProgressFunc pfnProgress, void *pProgressData);
      48             : 
      49             : /************************************************************************/
      50             : /* ==================================================================== */
      51             : /*                        Writer Implementation                         */
      52             : /* ==================================================================== */
      53             : /************************************************************************/
      54             : 
      55             : /************************************************************************/
      56             : /*                           RWriteInteger()                            */
      57             : /************************************************************************/
      58             : 
      59         360 : static void RWriteInteger(VSILFILE *fp, int bASCII, int nValue)
      60             : 
      61             : {
      62         360 :     if (bASCII)
      63             :     {
      64          20 :         char szOutput[50] = {'\0'};
      65          20 :         snprintf(szOutput, sizeof(szOutput), "%d\n", nValue);
      66          20 :         VSIFWriteL(szOutput, 1, strlen(szOutput), fp);
      67             :     }
      68             :     else
      69             :     {
      70         340 :         CPL_MSBPTR32(&nValue);
      71         340 :         VSIFWriteL(&nValue, 4, 1, fp);
      72             :     }
      73         360 : }
      74             : 
      75             : /************************************************************************/
      76             : /*                            RWriteString()                            */
      77             : /************************************************************************/
      78             : 
      79          36 : static void RWriteString(VSILFILE *fp, int bASCII, const char *pszValue)
      80             : 
      81             : {
      82          36 :     RWriteInteger(fp, bASCII, 4105);
      83          36 :     RWriteInteger(fp, bASCII, static_cast<int>(strlen(pszValue)));
      84             : 
      85          36 :     if (bASCII)
      86             :     {
      87           2 :         VSIFWriteL(pszValue, 1, strlen(pszValue), fp);
      88           2 :         VSIFWriteL("\n", 1, 1, fp);
      89             :     }
      90             :     else
      91             :     {
      92          34 :         VSIFWriteL(pszValue, 1, static_cast<int>(strlen(pszValue)), fp);
      93             :     }
      94          36 : }
      95             : 
      96             : /************************************************************************/
      97             : /*                            RCreateCopy()                             */
      98             : /************************************************************************/
      99             : 
     100          20 : GDALDataset *RCreateCopy(const char *pszFilename, GDALDataset *poSrcDS,
     101             :                          CPL_UNUSED int bStrict, char **papszOptions,
     102             :                          GDALProgressFunc pfnProgress, void *pProgressData)
     103             : {
     104          20 :     const int nBands = poSrcDS->GetRasterCount();
     105          20 :     const int nXSize = poSrcDS->GetRasterXSize();
     106          20 :     const int nYSize = poSrcDS->GetRasterYSize();
     107          20 :     const bool bASCII = CPLFetchBool(papszOptions, "ASCII", false);
     108          20 :     const bool bCompressed = CPLFetchBool(papszOptions, "COMPRESS", !bASCII);
     109             : 
     110          20 :     vsi_l_offset nSize = static_cast<vsi_l_offset>(nBands) * nXSize * nYSize;
     111          20 :     if (nSize > static_cast<vsi_l_offset>(INT_MAX))
     112             :     {
     113           0 :         CPLError(CE_Failure, CPLE_NotSupported, "Too big raster");
     114           0 :         return nullptr;
     115             :     }
     116             : 
     117             :     // Some some rudimentary checks.
     118             : 
     119             :     // Setup the filename to actually use.  We prefix with
     120             :     // /vsigzip/ if we want compressed output.
     121             :     const CPLString osAdjustedFilename =
     122          60 :         std::string(bCompressed ? "/vsigzip/" : "") + pszFilename;
     123             : 
     124             :     // Create the file.
     125          20 :     VSILFILE *fp = VSIFOpenL(osAdjustedFilename, "wb");
     126          20 :     if (fp == nullptr)
     127             :     {
     128           2 :         CPLError(CE_Failure, CPLE_OpenFailed, "Unable to create file %s.",
     129             :                  pszFilename);
     130           2 :         return nullptr;
     131             :     }
     132             : 
     133             :     // Write header with version, etc.
     134          18 :     if (bASCII)
     135             :     {
     136           1 :         const char *pszHeader = "RDA2\nA\n";
     137           1 :         VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp);
     138             :     }
     139             :     else
     140             :     {
     141          17 :         const char *pszHeader = "RDX2\nX\n";
     142          17 :         VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp);
     143             :     }
     144             : 
     145          18 :     RWriteInteger(fp, bASCII, 2);
     146          18 :     RWriteInteger(fp, bASCII, 133377);
     147          18 :     RWriteInteger(fp, bASCII, 131840);
     148             : 
     149             :     // Establish the primary pairlist with one component object.
     150          18 :     RWriteInteger(fp, bASCII, 1026);
     151          18 :     RWriteInteger(fp, bASCII, 1);
     152             : 
     153             :     // Write the object name.  Eventually we should derive this
     154             :     // from the filename, possible with override by a creation option.
     155          18 :     RWriteString(fp, bASCII, "gg");
     156             : 
     157             :     // For now we write the raster as a numeric array with attributes (526).
     158          18 :     RWriteInteger(fp, bASCII, 526);
     159          18 :     RWriteInteger(fp, bASCII, nXSize * nYSize * nBands);
     160             : 
     161             :     // Write the raster data.
     162          18 :     CPLErr eErr = CE_None;
     163             : 
     164             :     double *padfScanline =
     165          18 :         static_cast<double *>(CPLMalloc(nXSize * sizeof(double)));
     166             : 
     167          45 :     for (int iBand = 0; iBand < nBands; iBand++)
     168             :     {
     169          27 :         GDALRasterBand *poBand = poSrcDS->GetRasterBand(iBand + 1);
     170             : 
     171         317 :         for (int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++)
     172             :         {
     173         290 :             eErr = poBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfScanline,
     174             :                                     nXSize, 1, GDT_Float64, sizeof(double), 0,
     175             :                                     nullptr);
     176             : 
     177         290 :             if (bASCII)
     178             :             {
     179         420 :                 for (int iValue = 0; iValue < nXSize; iValue++)
     180             :                 {
     181         400 :                     char szValue[128] = {'\0'};
     182         400 :                     CPLsnprintf(szValue, sizeof(szValue), "%.16g\n",
     183         400 :                                 padfScanline[iValue]);
     184         400 :                     VSIFWriteL(szValue, 1, strlen(szValue), fp);
     185             :                 }
     186             :             }
     187             :             else
     188             :             {
     189        3170 :                 for (int iValue = 0; iValue < nXSize; iValue++)
     190        2900 :                     CPL_MSBPTR64(padfScanline + iValue);
     191             : 
     192         270 :                 VSIFWriteL(padfScanline, 8, nXSize, fp);
     193             :             }
     194             : 
     195         580 :             if (eErr == CE_None &&
     196         290 :                 !pfnProgress((iLine + 1) / static_cast<double>(nYSize), nullptr,
     197             :                              pProgressData))
     198             :             {
     199           0 :                 eErr = CE_Failure;
     200           0 :                 CPLError(CE_Failure, CPLE_UserInterrupt,
     201             :                          "User terminated CreateCopy()");
     202             :             }
     203             :         }
     204             :     }
     205             : 
     206          18 :     CPLFree(padfScanline);
     207             : 
     208             :     // Write out the dims attribute.
     209          18 :     RWriteInteger(fp, bASCII, 1026);
     210          18 :     RWriteInteger(fp, bASCII, 1);
     211             : 
     212          18 :     RWriteString(fp, bASCII, "dim");
     213             : 
     214          18 :     RWriteInteger(fp, bASCII, 13);
     215          18 :     RWriteInteger(fp, bASCII, 3);
     216          18 :     RWriteInteger(fp, bASCII, nXSize);
     217          18 :     RWriteInteger(fp, bASCII, nYSize);
     218          18 :     RWriteInteger(fp, bASCII, nBands);
     219             : 
     220          18 :     RWriteInteger(fp, bASCII, 254);
     221             : 
     222             :     // Terminate overall pairlist.
     223          18 :     RWriteInteger(fp, bASCII, 254);
     224             : 
     225             :     // Cleanup.
     226          18 :     VSIFCloseL(fp);
     227             : 
     228          18 :     if (eErr != CE_None)
     229           0 :         return nullptr;
     230             : 
     231             :     // Re-open dataset, and copy any auxiliary pam information.
     232             :     GDALPamDataset *poDS =
     233          18 :         static_cast<GDALPamDataset *>(GDALOpen(pszFilename, GA_ReadOnly));
     234             : 
     235          18 :     if (poDS)
     236           2 :         poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT);
     237             : 
     238          18 :     return poDS;
     239             : }

Generated by: LCOV version 1.14