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