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-11-21 22:18:42 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             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_port.h"
      14             : #include "rdataset.h"
      15             : 
      16             : #include <cstdio>
      17             : #include <cstring>
      18             : #include <string>
      19             : 
      20             : #include "cpl_conv.h"
      21             : #include "cpl_error.h"
      22             : #include "cpl_progress.h"
      23             : #include "cpl_string.h"
      24             : #include "cpl_vsi.h"
      25             : #include "gdal.h"
      26             : #include "gdal_pam.h"
      27             : #include "gdal_priv.h"
      28             : 
      29             : GDALDataset *RCreateCopy(const char *pszFilename, GDALDataset *poSrcDS,
      30             :                          int bStrict, char **papszOptions,
      31             :                          GDALProgressFunc pfnProgress, void *pProgressData);
      32             : 
      33             : /************************************************************************/
      34             : /* ==================================================================== */
      35             : /*                        Writer Implementation                         */
      36             : /* ==================================================================== */
      37             : /************************************************************************/
      38             : 
      39             : /************************************************************************/
      40             : /*                           RWriteInteger()                            */
      41             : /************************************************************************/
      42             : 
      43         360 : static void RWriteInteger(VSILFILE *fp, int bASCII, int nValue)
      44             : 
      45             : {
      46         360 :     if (bASCII)
      47             :     {
      48          20 :         char szOutput[50] = {'\0'};
      49          20 :         snprintf(szOutput, sizeof(szOutput), "%d\n", nValue);
      50          20 :         VSIFWriteL(szOutput, 1, strlen(szOutput), fp);
      51             :     }
      52             :     else
      53             :     {
      54         340 :         CPL_MSBPTR32(&nValue);
      55         340 :         VSIFWriteL(&nValue, 4, 1, fp);
      56             :     }
      57         360 : }
      58             : 
      59             : /************************************************************************/
      60             : /*                            RWriteString()                            */
      61             : /************************************************************************/
      62             : 
      63          36 : static void RWriteString(VSILFILE *fp, int bASCII, const char *pszValue)
      64             : 
      65             : {
      66          36 :     RWriteInteger(fp, bASCII, 4105);
      67          36 :     RWriteInteger(fp, bASCII, static_cast<int>(strlen(pszValue)));
      68             : 
      69          36 :     if (bASCII)
      70             :     {
      71           2 :         VSIFWriteL(pszValue, 1, strlen(pszValue), fp);
      72           2 :         VSIFWriteL("\n", 1, 1, fp);
      73             :     }
      74             :     else
      75             :     {
      76          34 :         VSIFWriteL(pszValue, 1, static_cast<int>(strlen(pszValue)), fp);
      77             :     }
      78          36 : }
      79             : 
      80             : /************************************************************************/
      81             : /*                            RCreateCopy()                             */
      82             : /************************************************************************/
      83             : 
      84          20 : GDALDataset *RCreateCopy(const char *pszFilename, GDALDataset *poSrcDS,
      85             :                          CPL_UNUSED int bStrict, char **papszOptions,
      86             :                          GDALProgressFunc pfnProgress, void *pProgressData)
      87             : {
      88          20 :     const int nBands = poSrcDS->GetRasterCount();
      89          20 :     const int nXSize = poSrcDS->GetRasterXSize();
      90          20 :     const int nYSize = poSrcDS->GetRasterYSize();
      91          20 :     const bool bASCII = CPLFetchBool(papszOptions, "ASCII", false);
      92          20 :     const bool bCompressed = CPLFetchBool(papszOptions, "COMPRESS", !bASCII);
      93             : 
      94          20 :     vsi_l_offset nSize = static_cast<vsi_l_offset>(nBands) * nXSize * nYSize;
      95          20 :     if (nSize > static_cast<vsi_l_offset>(INT_MAX))
      96             :     {
      97           0 :         CPLError(CE_Failure, CPLE_NotSupported, "Too big raster");
      98           0 :         return nullptr;
      99             :     }
     100             : 
     101             :     // Some some rudimentary checks.
     102             : 
     103             :     // Setup the filename to actually use.  We prefix with
     104             :     // /vsigzip/ if we want compressed output.
     105             :     const CPLString osAdjustedFilename =
     106          60 :         std::string(bCompressed ? "/vsigzip/" : "") + pszFilename;
     107             : 
     108             :     // Create the file.
     109          20 :     VSILFILE *fp = VSIFOpenL(osAdjustedFilename, "wb");
     110          20 :     if (fp == nullptr)
     111             :     {
     112           2 :         CPLError(CE_Failure, CPLE_OpenFailed, "Unable to create file %s.",
     113             :                  pszFilename);
     114           2 :         return nullptr;
     115             :     }
     116             : 
     117             :     // Write header with version, etc.
     118          18 :     if (bASCII)
     119             :     {
     120           1 :         const char *pszHeader = "RDA2\nA\n";
     121           1 :         VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp);
     122             :     }
     123             :     else
     124             :     {
     125          17 :         const char *pszHeader = "RDX2\nX\n";
     126          17 :         VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp);
     127             :     }
     128             : 
     129          18 :     RWriteInteger(fp, bASCII, 2);
     130          18 :     RWriteInteger(fp, bASCII, 133377);
     131          18 :     RWriteInteger(fp, bASCII, 131840);
     132             : 
     133             :     // Establish the primary pairlist with one component object.
     134          18 :     RWriteInteger(fp, bASCII, 1026);
     135          18 :     RWriteInteger(fp, bASCII, 1);
     136             : 
     137             :     // Write the object name.  Eventually we should derive this
     138             :     // from the filename, possible with override by a creation option.
     139          18 :     RWriteString(fp, bASCII, "gg");
     140             : 
     141             :     // For now we write the raster as a numeric array with attributes (526).
     142          18 :     RWriteInteger(fp, bASCII, 526);
     143          18 :     RWriteInteger(fp, bASCII, nXSize * nYSize * nBands);
     144             : 
     145             :     // Write the raster data.
     146          18 :     CPLErr eErr = CE_None;
     147             : 
     148             :     double *padfScanline =
     149          18 :         static_cast<double *>(CPLMalloc(nXSize * sizeof(double)));
     150             : 
     151          45 :     for (int iBand = 0; iBand < nBands; iBand++)
     152             :     {
     153          27 :         GDALRasterBand *poBand = poSrcDS->GetRasterBand(iBand + 1);
     154             : 
     155         317 :         for (int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++)
     156             :         {
     157         290 :             eErr = poBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfScanline,
     158             :                                     nXSize, 1, GDT_Float64, sizeof(double), 0,
     159             :                                     nullptr);
     160             : 
     161         290 :             if (bASCII)
     162             :             {
     163         420 :                 for (int iValue = 0; iValue < nXSize; iValue++)
     164             :                 {
     165         400 :                     char szValue[128] = {'\0'};
     166         400 :                     CPLsnprintf(szValue, sizeof(szValue), "%.16g\n",
     167         400 :                                 padfScanline[iValue]);
     168         400 :                     VSIFWriteL(szValue, 1, strlen(szValue), fp);
     169             :                 }
     170             :             }
     171             :             else
     172             :             {
     173        3170 :                 for (int iValue = 0; iValue < nXSize; iValue++)
     174        2900 :                     CPL_MSBPTR64(padfScanline + iValue);
     175             : 
     176         270 :                 VSIFWriteL(padfScanline, 8, nXSize, fp);
     177             :             }
     178             : 
     179         580 :             if (eErr == CE_None &&
     180         290 :                 !pfnProgress((iLine + 1) / static_cast<double>(nYSize), nullptr,
     181             :                              pProgressData))
     182             :             {
     183           0 :                 eErr = CE_Failure;
     184           0 :                 CPLError(CE_Failure, CPLE_UserInterrupt,
     185             :                          "User terminated CreateCopy()");
     186             :             }
     187             :         }
     188             :     }
     189             : 
     190          18 :     CPLFree(padfScanline);
     191             : 
     192             :     // Write out the dims attribute.
     193          18 :     RWriteInteger(fp, bASCII, 1026);
     194          18 :     RWriteInteger(fp, bASCII, 1);
     195             : 
     196          18 :     RWriteString(fp, bASCII, "dim");
     197             : 
     198          18 :     RWriteInteger(fp, bASCII, 13);
     199          18 :     RWriteInteger(fp, bASCII, 3);
     200          18 :     RWriteInteger(fp, bASCII, nXSize);
     201          18 :     RWriteInteger(fp, bASCII, nYSize);
     202          18 :     RWriteInteger(fp, bASCII, nBands);
     203             : 
     204          18 :     RWriteInteger(fp, bASCII, 254);
     205             : 
     206             :     // Terminate overall pairlist.
     207          18 :     RWriteInteger(fp, bASCII, 254);
     208             : 
     209             :     // Cleanup.
     210          18 :     VSIFCloseL(fp);
     211             : 
     212          18 :     if (eErr != CE_None)
     213           0 :         return nullptr;
     214             : 
     215             :     // Re-open dataset, and copy any auxiliary pam information.
     216             :     GDALPamDataset *poDS =
     217          18 :         static_cast<GDALPamDataset *>(GDALOpen(pszFilename, GA_ReadOnly));
     218             : 
     219          18 :     if (poDS)
     220           2 :         poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT);
     221             : 
     222          18 :     return poDS;
     223             : }

Generated by: LCOV version 1.14