Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Utilities
4 : * Purpose: GDAL Image Translator Program
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 1998, 2002, Frank Warmerdam
9 : * Copyright (c) 2007-2014, Even Rouault <even dot rouault at spatialys.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 "cpl_string.h"
31 : #include "gdal_version.h"
32 : #include "gdal_priv.h"
33 : #include "ogr_spatialref.h"
34 : #include "commonutils.h"
35 : #include "gdal_utils_priv.h"
36 :
37 : /* ******************************************************************* */
38 : /* Usage() */
39 : /* ******************************************************************** */
40 :
41 3 : static void Usage()
42 : {
43 3 : fprintf(stderr, "%s\n", GDALTranslateGetParserUsage().c_str());
44 :
45 3 : exit(1);
46 : }
47 :
48 : /************************************************************************/
49 : /* main() */
50 : /************************************************************************/
51 :
52 164 : MAIN_START(argc, argv)
53 :
54 : {
55 : /* Check strict compilation and runtime library version as we use C++ API */
56 164 : if (!GDAL_CHECK_VERSION(argv[0]))
57 0 : exit(1);
58 :
59 164 : EarlySetConfigOptions(argc, argv);
60 :
61 : /* -------------------------------------------------------------------- */
62 : /* Register standard GDAL drivers, and process generic GDAL */
63 : /* command options. */
64 : /* -------------------------------------------------------------------- */
65 164 : GDALAllRegister();
66 164 : argc = GDALGeneralCmdLineProcessor(argc, &argv, 0);
67 164 : if (argc < 1)
68 0 : exit(-argc);
69 :
70 : /* -------------------------------------------------------------------- */
71 : /* Set optimal setting for best performance with huge input VRT. */
72 : /* The rationale for 450 is that typical Linux process allow */
73 : /* only 1024 file descriptors per process and we need to keep some */
74 : /* spare for shared libraries, etc. so let's go down to 900. */
75 : /* And some datasets may need 2 file descriptors, so divide by 2 */
76 : /* for security. */
77 : /* -------------------------------------------------------------------- */
78 164 : if (CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", nullptr) == nullptr)
79 : {
80 : #if defined(__MACH__) && defined(__APPLE__)
81 : // On Mach, the default limit is 256 files per process
82 : // TODO We should eventually dynamically query the limit for all OS
83 : CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "100");
84 : #else
85 164 : CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450");
86 : #endif
87 : }
88 :
89 317 : GDALTranslateOptionsForBinary sOptionsForBinary;
90 : GDALTranslateOptions *psOptions =
91 164 : GDALTranslateOptionsNew(argv + 1, &sOptionsForBinary);
92 161 : CSLDestroy(argv);
93 :
94 161 : if (psOptions == nullptr)
95 : {
96 3 : Usage();
97 : }
98 :
99 158 : if (sOptionsForBinary.osDest == "/vsistdout/")
100 : {
101 0 : sOptionsForBinary.bQuiet = true;
102 : }
103 :
104 158 : if (!(sOptionsForBinary.bQuiet))
105 : {
106 147 : GDALTranslateOptionsSetProgress(psOptions, GDALTermProgress, nullptr);
107 : }
108 :
109 158 : if (!sOptionsForBinary.osFormat.empty())
110 : {
111 : GDALDriverH hDriver =
112 101 : GDALGetDriverByName(sOptionsForBinary.osFormat.c_str());
113 101 : if (hDriver == nullptr)
114 : {
115 0 : fprintf(stderr, "Output driver `%s' not recognised.\n",
116 : sOptionsForBinary.osFormat.c_str());
117 0 : fprintf(stderr, "The following format drivers are configured and "
118 : "support output:\n");
119 0 : for (int iDr = 0; iDr < GDALGetDriverCount(); iDr++)
120 : {
121 0 : hDriver = GDALGetDriver(iDr);
122 :
123 0 : if (GDALGetMetadataItem(hDriver, GDAL_DCAP_RASTER, nullptr) !=
124 0 : nullptr &&
125 0 : (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, nullptr) !=
126 0 : nullptr ||
127 0 : GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATECOPY,
128 : nullptr) != nullptr))
129 : {
130 0 : fprintf(stderr, " %s: %s\n",
131 : GDALGetDriverShortName(hDriver),
132 : GDALGetDriverLongName(hDriver));
133 : }
134 : }
135 :
136 0 : GDALTranslateOptionsFree(psOptions);
137 :
138 0 : GDALDestroyDriverManager();
139 0 : exit(1);
140 : }
141 : }
142 :
143 : /* -------------------------------------------------------------------- */
144 : /* Attempt to open source file. */
145 : /* -------------------------------------------------------------------- */
146 :
147 : GDALDatasetH hDataset =
148 158 : GDALOpenEx(sOptionsForBinary.osSource.c_str(),
149 : GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR,
150 158 : sOptionsForBinary.aosAllowedInputDrivers.List(),
151 158 : sOptionsForBinary.aosOpenOptions.List(), nullptr);
152 :
153 158 : if (hDataset == nullptr)
154 : {
155 5 : GDALDestroyDriverManager();
156 5 : exit(1);
157 : }
158 :
159 : /* -------------------------------------------------------------------- */
160 : /* Handle subdatasets. */
161 : /* -------------------------------------------------------------------- */
162 458 : if (!sOptionsForBinary.bCopySubDatasets &&
163 153 : GDALGetRasterCount(hDataset) == 0 &&
164 0 : CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0)
165 : {
166 0 : fprintf(stderr, "Input file contains subdatasets. Please, select one "
167 : "of them for reading.\n");
168 0 : GDALClose(hDataset);
169 0 : GDALDestroyDriverManager();
170 0 : exit(1);
171 : }
172 :
173 153 : int bUsageError = FALSE;
174 153 : GDALDatasetH hOutDS = nullptr;
175 153 : GDALDriverH hOutDriver = nullptr;
176 :
177 153 : if (sOptionsForBinary.osFormat.empty())
178 : {
179 52 : hOutDriver = GDALGetDriverByName(
180 104 : GetOutputDriverForRaster(sOptionsForBinary.osDest.c_str()));
181 : }
182 : else
183 : {
184 101 : hOutDriver = GDALGetDriverByName(sOptionsForBinary.osFormat.c_str());
185 : }
186 :
187 153 : if (hOutDriver == nullptr)
188 : {
189 0 : fprintf(stderr, "Output driver not found.\n");
190 0 : GDALClose(hDataset);
191 0 : GDALDestroyDriverManager();
192 0 : exit(1);
193 : }
194 :
195 : bool bCopyCreateSubDatasets =
196 153 : (GDALGetMetadataItem(hOutDriver, GDAL_DCAP_SUBCREATECOPY, nullptr) !=
197 153 : nullptr);
198 :
199 154 : if (sOptionsForBinary.bCopySubDatasets &&
200 1 : CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0)
201 : {
202 1 : if (bCopyCreateSubDatasets)
203 : {
204 : // GDAL sets the size of the dataset with subdatasets to 512x512
205 : // this removes the srcwin function from this operation
206 0 : hOutDS = GDALTranslate(sOptionsForBinary.osDest.c_str(), hDataset,
207 : psOptions, &bUsageError);
208 0 : GDALClose(hOutDS);
209 : }
210 : else
211 : {
212 1 : char **papszSubdatasets = GDALGetMetadata(hDataset, "SUBDATASETS");
213 : char *pszSubDest = static_cast<char *>(
214 1 : CPLMalloc(strlen(sOptionsForBinary.osDest.c_str()) + 32));
215 :
216 2 : CPLString osPath = CPLGetPath(sOptionsForBinary.osDest.c_str());
217 : CPLString osBasename =
218 2 : CPLGetBasename(sOptionsForBinary.osDest.c_str());
219 : CPLString osExtension =
220 2 : CPLGetExtension(sOptionsForBinary.osDest.c_str());
221 2 : CPLString osTemp;
222 :
223 1 : const char *pszFormat = nullptr;
224 1 : if (CSLCount(papszSubdatasets) / 2 < 10)
225 : {
226 1 : pszFormat = "%s_%d";
227 : }
228 0 : else if (CSLCount(papszSubdatasets) / 2 < 100)
229 : {
230 0 : pszFormat = "%s_%002d";
231 : }
232 : else
233 : {
234 0 : pszFormat = "%s_%003d";
235 : }
236 :
237 1 : const char *pszDest = pszSubDest;
238 :
239 2 : for (int i = 0; papszSubdatasets[i] != nullptr; i += 2)
240 : {
241 : char *pszSource =
242 1 : CPLStrdup(strstr(papszSubdatasets[i], "=") + 1);
243 1 : osTemp = CPLSPrintf(pszFormat, osBasename.c_str(), i / 2 + 1);
244 1 : osTemp = CPLFormFilename(osPath, osTemp, osExtension);
245 1 : strcpy(pszSubDest, osTemp.c_str());
246 1 : hDataset = GDALOpenEx(pszSource, GDAL_OF_RASTER, nullptr,
247 1 : sOptionsForBinary.aosOpenOptions.List(),
248 : nullptr);
249 1 : CPLFree(pszSource);
250 1 : if (!sOptionsForBinary.bQuiet)
251 1 : printf("Input file size is %d, %d\n",
252 : GDALGetRasterXSize(hDataset),
253 : GDALGetRasterYSize(hDataset));
254 : hOutDS =
255 1 : GDALTranslate(pszDest, hDataset, psOptions, &bUsageError);
256 1 : if (hOutDS == nullptr)
257 0 : break;
258 1 : GDALClose(hOutDS);
259 : }
260 :
261 1 : CPLFree(pszSubDest);
262 : }
263 :
264 1 : if (bUsageError == TRUE)
265 0 : Usage();
266 1 : GDALClose(hDataset);
267 1 : GDALTranslateOptionsFree(psOptions);
268 :
269 1 : GDALDestroy();
270 1 : return 0;
271 : }
272 :
273 152 : if (!sOptionsForBinary.bQuiet)
274 143 : printf("Input file size is %d, %d\n", GDALGetRasterXSize(hDataset),
275 : GDALGetRasterYSize(hDataset));
276 :
277 152 : hOutDS = GDALTranslate(sOptionsForBinary.osDest.c_str(), hDataset,
278 : psOptions, &bUsageError);
279 152 : if (bUsageError == TRUE)
280 0 : Usage();
281 152 : int nRetCode = hOutDS ? 0 : 1;
282 :
283 : /* Close hOutDS before hDataset for the -f VRT case */
284 152 : if (GDALClose(hOutDS) != CE_None)
285 : {
286 0 : nRetCode = 1;
287 0 : if (CPLGetLastErrorType() == CE_None)
288 : {
289 0 : CPLError(CE_Failure, CPLE_AppDefined,
290 : "Unknown error occurred in GDALClose()");
291 : }
292 : }
293 152 : GDALClose(hDataset);
294 152 : GDALTranslateOptionsFree(psOptions);
295 :
296 152 : GDALDestroy();
297 :
298 152 : return nRetCode;
299 : }
300 :
301 0 : MAIN_END
|