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 : }
|