Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: gdal "raster pipeline" subcommand
5 : * Author: Even Rouault <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "gdalalg_raster_pipeline.h"
14 : #include "gdalalg_external.h"
15 : #include "gdalalg_materialize.h"
16 : #include "gdalalg_raster_read.h"
17 : #include "gdalalg_raster_calc.h"
18 : #include "gdalalg_raster_aspect.h"
19 : #include "gdalalg_raster_blend.h"
20 : #include "gdalalg_raster_clean_collar.h"
21 : #include "gdalalg_raster_clip.h"
22 : #include "gdalalg_raster_color_map.h"
23 : #include "gdalalg_raster_compare.h"
24 : #include "gdalalg_raster_create.h"
25 : #include "gdalalg_raster_edit.h"
26 : #include "gdalalg_raster_fill_nodata.h"
27 : #include "gdalalg_raster_hillshade.h"
28 : #include "gdalalg_raster_info.h"
29 : #include "gdalalg_raster_mosaic.h"
30 : #include "gdalalg_raster_neighbors.h"
31 : #include "gdalalg_raster_nodata_to_alpha.h"
32 : #include "gdalalg_raster_overview.h"
33 : #include "gdalalg_raster_pansharpen.h"
34 : #include "gdalalg_raster_proximity.h"
35 : #include "gdalalg_raster_reclassify.h"
36 : #include "gdalalg_raster_reproject.h"
37 : #include "gdalalg_raster_resize.h"
38 : #include "gdalalg_raster_rgb_to_palette.h"
39 : #include "gdalalg_raster_roughness.h"
40 : #include "gdalalg_raster_scale.h"
41 : #include "gdalalg_raster_select.h"
42 : #include "gdalalg_raster_set_type.h"
43 : #include "gdalalg_raster_shift_longitude.h"
44 : #include "gdalalg_raster_sieve.h"
45 : #include "gdalalg_raster_slope.h"
46 : #include "gdalalg_raster_stack.h"
47 : #include "gdalalg_raster_tile.h"
48 : #include "gdalalg_raster_write.h"
49 : #include "gdalalg_raster_tpi.h"
50 : #include "gdalalg_raster_tri.h"
51 : #include "gdalalg_raster_unscale.h"
52 : #include "gdalalg_raster_update.h"
53 : #include "gdalalg_raster_viewshed.h"
54 : #include "gdalalg_tee.h"
55 :
56 : #include "cpl_conv.h"
57 : #include "cpl_progress.h"
58 : #include "cpl_string.h"
59 : #include "cpl_vsi.h"
60 : #include "gdal_priv.h"
61 : #include "gdal_utils.h"
62 :
63 : #include <algorithm>
64 : #include <array>
65 : #include <cassert>
66 :
67 : //! @cond Doxygen_Suppress
68 :
69 : #ifndef _
70 : #define _(x) (x)
71 : #endif
72 :
73 : GDALRasterAlgorithmStepRegistry::~GDALRasterAlgorithmStepRegistry() = default;
74 :
75 : /************************************************************************/
76 : /* GDALRasterPipelineStepAlgorithm::GDALRasterPipelineStepAlgorithm() */
77 : /************************************************************************/
78 :
79 3064 : GDALRasterPipelineStepAlgorithm::GDALRasterPipelineStepAlgorithm(
80 : const std::string &name, const std::string &description,
81 3064 : const std::string &helpURL, bool standaloneStep)
82 : : GDALRasterPipelineStepAlgorithm(
83 : name, description, helpURL,
84 3064 : ConstructorOptions().SetStandaloneStep(standaloneStep))
85 : {
86 3064 : }
87 :
88 : /************************************************************************/
89 : /* GDALRasterPipelineStepAlgorithm::GDALRasterPipelineStepAlgorithm() */
90 : /************************************************************************/
91 :
92 7153 : GDALRasterPipelineStepAlgorithm::GDALRasterPipelineStepAlgorithm(
93 : const std::string &name, const std::string &description,
94 7153 : const std::string &helpURL, const ConstructorOptions &options)
95 7153 : : GDALPipelineStepAlgorithm(name, description, helpURL, options)
96 : {
97 7153 : if (m_standaloneStep)
98 : {
99 3319 : m_supportsStreamedOutput = true;
100 :
101 3319 : if (m_constructorOptions.addDefaultArguments)
102 : {
103 1457 : AddRasterInputArgs(false, false);
104 1457 : AddProgressArg();
105 1457 : AddRasterOutputArgs(false);
106 : }
107 : }
108 3834 : else if (m_constructorOptions.addDefaultArguments)
109 : {
110 1728 : AddRasterHiddenInputDatasetArg();
111 : }
112 7153 : }
113 :
114 : GDALRasterPipelineStepAlgorithm::~GDALRasterPipelineStepAlgorithm() = default;
115 :
116 : /************************************************************************/
117 : /* GDALRasterPipelineStepAlgorithm::SetOutputVRTCompatible() */
118 : /************************************************************************/
119 :
120 581 : void GDALRasterPipelineStepAlgorithm::SetOutputVRTCompatible(bool b)
121 : {
122 581 : m_outputVRTCompatible = b;
123 581 : if (m_outputFormatArg)
124 : {
125 344 : m_outputFormatArg->AddMetadataItem(GAAMDI_VRT_COMPATIBLE,
126 688 : {b ? "true" : "false"});
127 : }
128 581 : }
129 :
130 : /************************************************************************/
131 : /* GDALRasterPipelineAlgorithm::GDALRasterPipelineAlgorithm() */
132 : /************************************************************************/
133 :
134 196 : GDALRasterPipelineAlgorithm::GDALRasterPipelineAlgorithm(
135 196 : bool openForMixedRasterVector)
136 : : GDALAbstractPipelineAlgorithm(NAME, DESCRIPTION, HELP_URL,
137 0 : ConstructorOptions()
138 196 : .SetAddDefaultArguments(false)
139 196 : .SetInputDatasetRequired(false)
140 196 : .SetInputDatasetPositional(false)
141 392 : .SetInputDatasetMaxCount(INT_MAX))
142 : {
143 196 : m_supportsStreamedOutput = true;
144 :
145 196 : AddRasterInputArgs(openForMixedRasterVector, /* hiddenForCLI = */ true);
146 196 : AddProgressArg();
147 392 : AddArg("pipeline", 0, _("Pipeline string"), &m_pipeline)
148 196 : .SetHiddenForCLI()
149 196 : .SetPositional();
150 196 : AddRasterOutputArgs(/* hiddenForCLI = */ true);
151 :
152 196 : AddOutputStringArg(&m_output).SetHiddenForCLI();
153 196 : AddStdoutArg(&m_stdout);
154 :
155 196 : RegisterAlgorithms(m_stepRegistry, false);
156 196 : }
157 :
158 : /************************************************************************/
159 : /* GDALRasterPipelineAlgorithm::RegisterAlgorithms() */
160 : /************************************************************************/
161 :
162 : /* static */
163 534 : void GDALRasterPipelineAlgorithm::RegisterAlgorithms(
164 : GDALRasterAlgorithmStepRegistry ®istry, bool forMixedPipeline)
165 : {
166 1068 : GDALAlgorithmRegistry::AlgInfo algInfo;
167 :
168 : const auto addSuffixIfNeeded =
169 5340 : [forMixedPipeline](const char *name) -> std::string
170 : {
171 8720 : return forMixedPipeline ? std::string(name).append(RASTER_SUFFIX)
172 14060 : : std::string(name);
173 534 : };
174 :
175 534 : registry.Register<GDALRasterReadAlgorithm>(
176 1068 : addSuffixIfNeeded(GDALRasterReadAlgorithm::NAME));
177 :
178 534 : registry.Register<GDALRasterCalcAlgorithm>();
179 534 : registry.Register<GDALRasterCreateAlgorithm>();
180 :
181 534 : registry.Register<GDALRasterNeighborsAlgorithm>();
182 :
183 534 : registry.Register<GDALRasterWriteAlgorithm>(
184 1068 : addSuffixIfNeeded(GDALRasterWriteAlgorithm::NAME));
185 :
186 534 : registry.Register<GDALRasterInfoAlgorithm>(
187 1068 : addSuffixIfNeeded(GDALRasterInfoAlgorithm::NAME));
188 :
189 534 : registry.Register<GDALRasterAspectAlgorithm>();
190 534 : registry.Register<GDALRasterBlendAlgorithm>();
191 :
192 534 : registry.Register<GDALRasterCleanCollarAlgorithm>();
193 534 : registry.Register<GDALRasterClipAlgorithm>(
194 1068 : addSuffixIfNeeded(GDALRasterClipAlgorithm::NAME));
195 :
196 534 : registry.Register<GDALRasterColorMapAlgorithm>();
197 534 : registry.Register<GDALRasterCompareAlgorithm>();
198 :
199 534 : registry.Register<GDALRasterEditAlgorithm>(
200 1068 : addSuffixIfNeeded(GDALRasterEditAlgorithm::NAME));
201 :
202 534 : registry.Register<GDALRasterNoDataToAlphaAlgorithm>();
203 534 : registry.Register<GDALRasterFillNodataAlgorithm>();
204 534 : registry.Register<GDALRasterHillshadeAlgorithm>();
205 :
206 534 : registry.Register<GDALMaterializeRasterAlgorithm>(
207 1068 : addSuffixIfNeeded(GDALMaterializeRasterAlgorithm::NAME));
208 :
209 534 : registry.Register<GDALRasterMosaicAlgorithm>();
210 534 : registry.Register<GDALRasterOverviewAlgorithm>();
211 534 : registry.Register<GDALRasterPansharpenAlgorithm>();
212 534 : registry.Register<GDALRasterProximityAlgorithm>();
213 534 : registry.Register<GDALRasterReclassifyAlgorithm>();
214 :
215 534 : registry.Register<GDALRasterReprojectAlgorithm>(
216 1068 : addSuffixIfNeeded(GDALRasterReprojectAlgorithm::NAME));
217 :
218 534 : registry.Register<GDALRasterResizeAlgorithm>();
219 534 : registry.Register<GDALRasterRGBToPaletteAlgorithm>();
220 534 : registry.Register<GDALRasterRoughnessAlgorithm>();
221 534 : registry.Register<GDALRasterScaleAlgorithm>();
222 :
223 534 : registry.Register<GDALRasterSelectAlgorithm>(
224 1068 : addSuffixIfNeeded(GDALRasterSelectAlgorithm::NAME));
225 :
226 534 : registry.Register<GDALRasterSetTypeAlgorithm>();
227 534 : registry.Register<GDALRasterShiftLongitudeAlgorithm>();
228 534 : registry.Register<GDALRasterSieveAlgorithm>();
229 534 : registry.Register<GDALRasterSlopeAlgorithm>();
230 534 : registry.Register<GDALRasterStackAlgorithm>();
231 534 : registry.Register<GDALRasterTileAlgorithm>();
232 534 : registry.Register<GDALRasterTPIAlgorithm>();
233 534 : registry.Register<GDALRasterTRIAlgorithm>();
234 534 : registry.Register<GDALRasterUnscaleAlgorithm>();
235 534 : registry.Register<GDALRasterUpdateAlgorithm>(
236 1068 : addSuffixIfNeeded(GDALRasterUpdateAlgorithm::NAME));
237 534 : registry.Register<GDALRasterViewshedAlgorithm>();
238 534 : registry.Register<GDALTeeRasterAlgorithm>(
239 1068 : addSuffixIfNeeded(GDALTeeRasterAlgorithm::NAME));
240 :
241 534 : if (!forMixedPipeline)
242 : {
243 196 : registry.Register<GDALExternalRasterAlgorithm>();
244 : }
245 534 : }
246 :
247 : /************************************************************************/
248 : /* GDALRasterPipelineAlgorithm::GetUsageForCLI() */
249 : /************************************************************************/
250 :
251 8 : std::string GDALRasterPipelineAlgorithm::GetUsageForCLI(
252 : bool shortUsage, const UsageOptions &usageOptions) const
253 : {
254 8 : UsageOptions stepUsageOptions;
255 8 : stepUsageOptions.isPipelineStep = true;
256 :
257 8 : if (!m_helpDocCategory.empty() && m_helpDocCategory != "main")
258 : {
259 4 : auto alg = GetStepAlg(m_helpDocCategory);
260 2 : if (alg)
261 : {
262 2 : alg->SetCallPath({m_helpDocCategory});
263 1 : alg->GetArg("help-doc")->Set(true);
264 1 : return alg->GetUsageForCLI(shortUsage, stepUsageOptions);
265 : }
266 : else
267 : {
268 1 : fprintf(stderr, "ERROR: unknown pipeline step '%s'\n",
269 : m_helpDocCategory.c_str());
270 : return CPLSPrintf("ERROR: unknown pipeline step '%s'\n",
271 1 : m_helpDocCategory.c_str());
272 : }
273 : }
274 :
275 6 : UsageOptions usageOptionsMain(usageOptions);
276 6 : usageOptionsMain.isPipelineMain = true;
277 : std::string ret =
278 12 : GDALAlgorithm::GetUsageForCLI(shortUsage, usageOptionsMain);
279 6 : if (shortUsage)
280 2 : return ret;
281 :
282 : ret += "\n<PIPELINE> is of the form: read|mosaic|stack [READ-OPTIONS] "
283 : "( ! <STEP-NAME> [STEP-OPTIONS] )* ! info|compare|tile|write "
284 4 : "[WRITE-OPTIONS]\n";
285 :
286 4 : if (m_helpDocCategory == "main")
287 : {
288 1 : return ret;
289 : }
290 :
291 3 : ret += '\n';
292 3 : ret += "Example: 'gdal raster pipeline --progress ! read in.tif ! \\\n";
293 3 : ret += " reproject --output-crs=EPSG:32632 ! ";
294 3 : ret += "write out.tif --overwrite'\n";
295 3 : ret += '\n';
296 3 : ret += "Potential steps are:\n";
297 :
298 126 : for (const std::string &name : m_stepRegistry.GetNames())
299 : {
300 246 : auto alg = GetStepAlg(name);
301 123 : auto [options, maxOptLen] = alg->GetArgNamesForCLI();
302 123 : stepUsageOptions.maxOptLen =
303 123 : std::max(stepUsageOptions.maxOptLen, maxOptLen);
304 : }
305 :
306 : {
307 3 : const auto name = GDALRasterReadAlgorithm::NAME;
308 3 : ret += '\n';
309 6 : auto alg = GetStepAlg(name);
310 6 : alg->SetCallPath({name});
311 3 : ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
312 : }
313 126 : for (const std::string &name : m_stepRegistry.GetNames())
314 : {
315 246 : auto alg = GetStepAlg(name);
316 123 : assert(alg);
317 141 : if (alg->CanBeFirstStep() && !alg->CanBeMiddleStep() &&
318 141 : !alg->IsHidden() && name != GDALRasterReadAlgorithm::NAME)
319 : {
320 6 : ret += '\n';
321 12 : alg->SetCallPath({name});
322 6 : ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
323 : }
324 : }
325 126 : for (const std::string &name : m_stepRegistry.GetNames())
326 : {
327 246 : auto alg = GetStepAlg(name);
328 123 : assert(alg);
329 123 : if (alg->CanBeMiddleStep() && !alg->IsHidden())
330 : {
331 102 : ret += '\n';
332 204 : alg->SetCallPath({name});
333 102 : ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
334 : }
335 : }
336 126 : for (const std::string &name : m_stepRegistry.GetNames())
337 : {
338 246 : auto alg = GetStepAlg(name);
339 123 : assert(alg);
340 144 : if (alg->CanBeLastStep() && !alg->CanBeMiddleStep() &&
341 144 : !alg->IsHidden() && name != GDALRasterWriteAlgorithm::NAME)
342 : {
343 9 : ret += '\n';
344 18 : alg->SetCallPath({name});
345 9 : ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
346 : }
347 : }
348 : {
349 3 : const auto name = GDALRasterWriteAlgorithm::NAME;
350 3 : ret += '\n';
351 6 : auto alg = GetStepAlg(name);
352 6 : alg->SetCallPath({name});
353 3 : ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
354 : }
355 3 : ret += GetUsageForCLIEnd();
356 :
357 3 : return ret;
358 : }
359 :
360 : /************************************************************************/
361 : /* GDALRasterPipelineNonNativelyStreamingAlgorithm() */
362 : /************************************************************************/
363 :
364 511 : GDALRasterPipelineNonNativelyStreamingAlgorithm::
365 : GDALRasterPipelineNonNativelyStreamingAlgorithm(
366 : const std::string &name, const std::string &description,
367 511 : const std::string &helpURL, bool standaloneStep)
368 : : GDALRasterPipelineStepAlgorithm(name, description, helpURL,
369 511 : standaloneStep)
370 : {
371 511 : }
372 :
373 103 : GDALRasterPipelineNonNativelyStreamingAlgorithm::
374 : GDALRasterPipelineNonNativelyStreamingAlgorithm(
375 : const std::string &name, const std::string &description,
376 103 : const std::string &helpURL, const ConstructorOptions &options)
377 103 : : GDALRasterPipelineStepAlgorithm(name, description, helpURL, options)
378 : {
379 103 : }
380 :
381 : /************************************************************************/
382 : /* IsNativelyStreamingCompatible() */
383 : /************************************************************************/
384 :
385 50 : bool GDALRasterPipelineNonNativelyStreamingAlgorithm::
386 : IsNativelyStreamingCompatible() const
387 : {
388 50 : return false;
389 : }
390 :
391 : /************************************************************************/
392 : /* MustCreateOnDiskTempDataset() */
393 : /************************************************************************/
394 :
395 72 : static bool MustCreateOnDiskTempDataset(int nWidth, int nHeight, int nBands,
396 : GDALDataType eDT)
397 : {
398 : // Config option mostly for autotest purposes
399 72 : if (CPLTestBool(CPLGetConfigOption(
400 : "GDAL_RASTER_PIPELINE_USE_GTIFF_FOR_TEMP_DATASET", "NO")))
401 5 : return true;
402 :
403 : // Allow up to 10% of RAM usage for temporary dataset
404 67 : const auto nRAM = CPLGetUsablePhysicalRAM() / 10;
405 67 : const int nDTSize = GDALGetDataTypeSizeBytes(eDT);
406 67 : const bool bOnDisk =
407 134 : nBands > 0 && nDTSize > 0 && nRAM > 0 &&
408 67 : static_cast<int64_t>(nWidth) * nHeight > nRAM / (nBands * nDTSize);
409 67 : return bOnDisk;
410 : }
411 :
412 : /************************************************************************/
413 : /* CreateTemporaryDataset() */
414 : /************************************************************************/
415 :
416 : std::unique_ptr<GDALDataset>
417 47 : GDALRasterPipelineNonNativelyStreamingAlgorithm::CreateTemporaryDataset(
418 : int nWidth, int nHeight, int nBands, GDALDataType eDT,
419 : bool bTiledIfPossible, GDALDataset *poSrcDSForMetadata, bool bCopyMetadata)
420 : {
421 : const bool bOnDisk =
422 47 : MustCreateOnDiskTempDataset(nWidth, nHeight, nBands, eDT);
423 47 : const char *pszDriverName = bOnDisk ? "GTIFF" : "MEM";
424 : GDALDriver *poDriver =
425 47 : GetGDALDriverManager()->GetDriverByName(pszDriverName);
426 94 : CPLStringList aosOptions;
427 94 : std::string osTmpFilename;
428 47 : if (bOnDisk)
429 : {
430 : osTmpFilename =
431 4 : CPLGenerateTempFilenameSafe(
432 : poSrcDSForMetadata
433 4 : ? CPLGetBasenameSafe(poSrcDSForMetadata->GetDescription())
434 2 : .c_str()
435 4 : : "") +
436 2 : ".tif";
437 2 : if (bTiledIfPossible)
438 2 : aosOptions.SetNameValue("TILED", "YES");
439 : const char *pszCOList =
440 2 : poDriver->GetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST);
441 : aosOptions.SetNameValue("COMPRESS",
442 2 : pszCOList && strstr(pszCOList, "ZSTD") ? "ZSTD"
443 4 : : "LZW");
444 2 : aosOptions.SetNameValue("SPARSE_OK", "YES");
445 : }
446 : std::unique_ptr<GDALDataset> poOutDS(
447 47 : poDriver ? poDriver->Create(osTmpFilename.c_str(), nWidth, nHeight,
448 47 : nBands, eDT, aosOptions.List())
449 94 : : nullptr);
450 47 : if (poOutDS && bOnDisk)
451 : {
452 : // In file systems that allow it (all but Windows...), we want to
453 : // delete the temporary file as soon as soon as possible after
454 : // having open it, so that if someone kills the process there are
455 : // no temp files left over. If that unlink() doesn't succeed
456 : // (on Windows), then the file will eventually be deleted when
457 : // poTmpDS is cleaned due to MarkSuppressOnClose().
458 0 : VSIUnlink(osTmpFilename.c_str());
459 0 : poOutDS->MarkSuppressOnClose();
460 : }
461 :
462 47 : if (poOutDS && poSrcDSForMetadata)
463 : {
464 45 : poOutDS->SetSpatialRef(poSrcDSForMetadata->GetSpatialRef());
465 45 : GDALGeoTransform gt;
466 45 : if (poSrcDSForMetadata->GetGeoTransform(gt) == CE_None)
467 30 : poOutDS->SetGeoTransform(gt);
468 45 : if (const int nGCPCount = poSrcDSForMetadata->GetGCPCount())
469 : {
470 0 : const auto apsGCPs = poSrcDSForMetadata->GetGCPs();
471 0 : if (apsGCPs)
472 : {
473 0 : poOutDS->SetGCPs(nGCPCount, apsGCPs,
474 0 : poSrcDSForMetadata->GetGCPSpatialRef());
475 : }
476 : }
477 45 : if (bCopyMetadata)
478 : {
479 21 : poOutDS->SetMetadata(poSrcDSForMetadata->GetMetadata());
480 : }
481 : }
482 :
483 94 : return poOutDS;
484 : }
485 :
486 : /************************************************************************/
487 : /* CreateTemporaryCopy() */
488 : /************************************************************************/
489 :
490 : std::unique_ptr<GDALDataset>
491 25 : GDALRasterPipelineNonNativelyStreamingAlgorithm::CreateTemporaryCopy(
492 : GDALAlgorithm *poAlg, GDALDataset *poSrcDS, int nSingleBand,
493 : bool bTiledIfPossible, GDALProgressFunc pfnProgress, void *pProgressData)
494 : {
495 25 : const int nBands = nSingleBand > 0 ? 1 : poSrcDS->GetRasterCount();
496 : const auto eDT =
497 25 : nBands ? poSrcDS->GetRasterBand(1)->GetRasterDataType() : GDT_Unknown;
498 25 : const bool bOnDisk = MustCreateOnDiskTempDataset(
499 : poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(), nBands, eDT);
500 25 : const char *pszDriverName = bOnDisk ? "GTIFF" : "MEM";
501 :
502 50 : CPLStringList options;
503 25 : if (nSingleBand > 0)
504 : {
505 25 : options.AddString("-b");
506 25 : options.AddString(CPLSPrintf("%d", nSingleBand));
507 : }
508 :
509 25 : options.AddString("-of");
510 25 : options.AddString(pszDriverName);
511 :
512 50 : std::string osTmpFilename;
513 25 : if (bOnDisk)
514 : {
515 : osTmpFilename =
516 3 : CPLGenerateTempFilenameSafe(
517 9 : CPLGetBasenameSafe(poSrcDS->GetDescription()).c_str()) +
518 3 : ".tif";
519 3 : if (bTiledIfPossible)
520 : {
521 3 : options.AddString("-co");
522 3 : options.AddString("TILED=YES");
523 : }
524 :
525 : GDALDriver *poDriver =
526 3 : GetGDALDriverManager()->GetDriverByName(pszDriverName);
527 : const char *pszCOList =
528 3 : poDriver ? poDriver->GetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST)
529 3 : : nullptr;
530 3 : options.AddString("-co");
531 3 : options.AddString(pszCOList && strstr(pszCOList, "ZSTD")
532 : ? "COMPRESS=ZSTD"
533 6 : : "COMPRESS=LZW");
534 : }
535 :
536 : GDALTranslateOptions *translateOptions =
537 25 : GDALTranslateOptionsNew(options.List(), nullptr);
538 :
539 25 : if (pfnProgress)
540 12 : GDALTranslateOptionsSetProgress(translateOptions, pfnProgress,
541 : pProgressData);
542 :
543 : std::unique_ptr<GDALDataset> poOutDS(GDALDataset::FromHandle(
544 : GDALTranslate(osTmpFilename.c_str(), GDALDataset::ToHandle(poSrcDS),
545 25 : translateOptions, nullptr)));
546 25 : GDALTranslateOptionsFree(translateOptions);
547 :
548 25 : if (!poOutDS)
549 : {
550 2 : poAlg->ReportError(CE_Failure, CPLE_AppDefined,
551 : "Failed to create temporary dataset");
552 : }
553 23 : else if (bOnDisk)
554 : {
555 : // In file systems that allow it (all but Windows...), we want to
556 : // delete the temporary file as soon as soon as possible after
557 : // having open it, so that if someone kills the process there are
558 : // no temp files left over. If that unlink() doesn't succeed
559 : // (on Windows), then the file will eventually be deleted when
560 : // poTmpDS is cleaned due to MarkSuppressOnClose().
561 1 : VSIUnlink(osTmpFilename.c_str());
562 1 : poOutDS->MarkSuppressOnClose();
563 : }
564 50 : return poOutDS;
565 : }
566 :
567 : //! @endcond
|