Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: Algorithm to apply a transformer to geolocation style bands.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2012, Frank Warmerdam
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 "gdal_alg.h"
31 :
32 : #include <cstring>
33 :
34 : #include "cpl_conv.h"
35 : #include "cpl_error.h"
36 : #include "cpl_progress.h"
37 : #include "gdal.h"
38 : #include "gdal_alg_priv.h"
39 : #include "gdal_priv.h"
40 :
41 : /************************************************************************/
42 : /* GDALTransformGeolocations() */
43 : /************************************************************************/
44 :
45 : /**
46 : * Transform locations held in bands.
47 : *
48 : * The X/Y and possibly Z values in the identified bands are transformed
49 : * using a spatial transformer. The changed values are written back to the
50 : * source bands so they need to be updateable.
51 : *
52 : * @param hXBand the band containing the X locations (usually long/easting).
53 : * @param hYBand the band containing the Y locations (usually lat/northing).
54 : * @param hZBand the band containing the Z locations (may be NULL).
55 : * @param pfnTransformer the transformer function.
56 : * @param pTransformArg the callback data for the transformer function.
57 : * @param pfnProgress callback for reporting algorithm progress matching the
58 : * GDALProgressFunc() semantics. May be NULL.
59 : * @param pProgressArg callback argument passed to pfnProgress.
60 : * @param papszOptions list of name/value options - none currently supported.
61 : *
62 : * @return CE_None on success or CE_Failure if an error occurs.
63 : */
64 :
65 1 : CPLErr GDALTransformGeolocations(GDALRasterBandH hXBand, GDALRasterBandH hYBand,
66 : GDALRasterBandH hZBand,
67 : GDALTransformerFunc pfnTransformer,
68 : void *pTransformArg,
69 : GDALProgressFunc pfnProgress,
70 : void *pProgressArg,
71 : CPL_UNUSED char **papszOptions)
72 :
73 : {
74 1 : VALIDATE_POINTER1(hXBand, "GDALTransformGeolocations", CE_Failure);
75 1 : VALIDATE_POINTER1(hYBand, "GDALTransformGeolocations", CE_Failure);
76 :
77 1 : if (pfnProgress == nullptr)
78 1 : pfnProgress = GDALDummyProgress;
79 :
80 : /* -------------------------------------------------------------------- */
81 : /* Ensure the bands are matching in size. */
82 : /* -------------------------------------------------------------------- */
83 1 : GDALRasterBand *poXBand = reinterpret_cast<GDALRasterBand *>(hXBand);
84 1 : GDALRasterBand *poYBand = reinterpret_cast<GDALRasterBand *>(hYBand);
85 1 : GDALRasterBand *poZBand = reinterpret_cast<GDALRasterBand *>(hZBand);
86 1 : const int nXSize = poXBand->GetXSize();
87 1 : const int nYSize = poXBand->GetYSize();
88 :
89 2 : if (nXSize != poYBand->GetXSize() || nYSize != poYBand->GetYSize() ||
90 3 : (poZBand != nullptr && nXSize != poZBand->GetXSize()) ||
91 1 : (poZBand != nullptr && nYSize != poZBand->GetYSize()))
92 : {
93 0 : CPLError(CE_Failure, CPLE_AppDefined,
94 : "Size of X, Y and/or Z bands do not match.");
95 0 : return CE_Failure;
96 : }
97 :
98 : /* -------------------------------------------------------------------- */
99 : /* Allocate a buffer large enough to hold one whole row. */
100 : /* -------------------------------------------------------------------- */
101 1 : double *padfX = static_cast<double *>(CPLMalloc(sizeof(double) * nXSize));
102 1 : double *padfY = static_cast<double *>(CPLMalloc(sizeof(double) * nXSize));
103 1 : double *padfZ = static_cast<double *>(CPLMalloc(sizeof(double) * nXSize));
104 1 : int *panSuccess = static_cast<int *>(CPLMalloc(sizeof(int) * nXSize));
105 1 : CPLErr eErr = CE_None;
106 :
107 1 : pfnProgress(0.0, "", pProgressArg);
108 3 : for (int iLine = 0; eErr == CE_None && iLine < nYSize; iLine++)
109 : {
110 2 : eErr = poXBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfX, nXSize, 1,
111 : GDT_Float64, 0, 0, nullptr);
112 2 : if (eErr == CE_None)
113 2 : eErr = poYBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfY,
114 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
115 2 : if (eErr == CE_None && poZBand != nullptr)
116 2 : eErr = poZBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfZ,
117 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
118 : else
119 0 : memset(padfZ, 0, sizeof(double) * nXSize);
120 :
121 2 : if (eErr == CE_None)
122 : {
123 2 : pfnTransformer(pTransformArg, FALSE, nXSize, padfX, padfY, padfZ,
124 : panSuccess);
125 : }
126 :
127 2 : if (eErr == CE_None)
128 2 : eErr = poXBand->RasterIO(GF_Write, 0, iLine, nXSize, 1, padfX,
129 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
130 2 : if (eErr == CE_None)
131 2 : eErr = poYBand->RasterIO(GF_Write, 0, iLine, nXSize, 1, padfY,
132 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
133 2 : if (eErr == CE_None && poZBand != nullptr)
134 2 : eErr = poZBand->RasterIO(GF_Write, 0, iLine, nXSize, 1, padfZ,
135 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
136 :
137 2 : if (eErr == CE_None)
138 2 : pfnProgress((iLine + 1) / static_cast<double>(nYSize), "",
139 : pProgressArg);
140 : }
141 :
142 : /* -------------------------------------------------------------------- */
143 : /* Cleanup */
144 : /* -------------------------------------------------------------------- */
145 1 : CPLFree(padfX);
146 1 : CPLFree(padfY);
147 1 : CPLFree(padfZ);
148 1 : CPLFree(panSuccess);
149 :
150 1 : return eErr;
151 : }
|