Skip to content

Commit ef60b9b

Browse files
authored
Merge pull request OSGeo#12438 from rouault/fix_12435
GDALCreateHomographyTransformer(): emit CPLError()s when failures happen
2 parents d7f54c6 + eda0ae2 commit ef60b9b

File tree

3 files changed

+60
-46
lines changed

3 files changed

+60
-46
lines changed

alg/gdal_homography.cpp

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ void *GDALCreateHomographyTransformer(double adfHomography[9])
110110
return psInfo;
111111
}
112112

113+
CPLError(CE_Failure, CPLE_AppDefined,
114+
"GDALCreateHomographyTransformer() failed, because "
115+
"GDALInvHomography() failed");
113116
GDALDestroyHomographyTransformer(psInfo);
114117
return nullptr;
115118
}
@@ -172,14 +175,17 @@ int GDALGCPsToHomography(int nGCPCount, const GDAL_GCP *pasGCPList,
172175
max_geoy = std::max(max_geoy, pasGCPList[i].dfGCPY);
173176
}
174177

175-
double EPS = 1.0e-12;
178+
constexpr double EPSILON = 1.0e-12;
176179

177-
if (std::abs(max_pixel - min_pixel) < EPS ||
178-
std::abs(max_line - min_line) < EPS ||
179-
std::abs(max_geox - min_geox) < EPS ||
180-
std::abs(max_geoy - min_geoy) < EPS)
180+
if (std::abs(max_pixel - min_pixel) < EPSILON ||
181+
std::abs(max_line - min_line) < EPSILON ||
182+
std::abs(max_geox - min_geox) < EPSILON ||
183+
std::abs(max_geoy - min_geoy) < EPSILON)
181184
{
182-
return FALSE; // degenerate in at least one dimension.
185+
CPLError(CE_Failure, CPLE_AppDefined,
186+
"GDALGCPsToHomography() failed: GCPs degenerate in at least "
187+
"one dimension.");
188+
return FALSE;
183189
}
184190

185191
double pl_normalize[9], geo_normalize[9];
@@ -207,6 +213,8 @@ int GDALGCPsToHomography(int nGCPCount, const GDAL_GCP *pasGCPList,
207213
double inv_geo_normalize[9] = {0.0};
208214
if (!GDALInvHomography(geo_normalize, inv_geo_normalize))
209215
{
216+
CPLError(CE_Failure, CPLE_AppDefined,
217+
"GDALGCPsToHomography() failed: GDALInvHomography() failed");
210218
return FALSE;
211219
}
212220

@@ -231,6 +239,10 @@ int GDALGCPsToHomography(int nGCPCount, const GDAL_GCP *pasGCPList,
231239
!GDALApplyHomography(geo_normalize, pasGCPList[i].dfGCPX,
232240
pasGCPList[i].dfGCPY, &geox, &geoy))
233241
{
242+
CPLError(CE_Failure, CPLE_AppDefined,
243+
"GDALGCPsToHomography() failed: GDALApplyHomography() "
244+
"failed on GCP %d.",
245+
i);
234246
return FALSE;
235247
}
236248

@@ -260,10 +272,15 @@ int GDALGCPsToHomography(int nGCPCount, const GDAL_GCP *pasGCPList,
260272
GDALMatrix h_normalized(9, 1);
261273
if (!GDALLinearSystemSolve(AtA, rhs, h_normalized))
262274
{
275+
CPLError(
276+
CE_Failure, CPLE_AppDefined,
277+
"GDALGCPsToHomography() failed: GDALLinearSystemSolve() failed");
263278
return FALSE;
264279
}
265280
if (std::abs(h_normalized(6, 0)) < 1.0e-15)
266281
{
282+
CPLError(CE_Failure, CPLE_AppDefined,
283+
"GDALGCPsToHomography() failed: h_normalized(6, 0) not zero");
267284
return FALSE;
268285
}
269286

@@ -295,6 +312,8 @@ int GDALGCPsToHomography(int nGCPCount, const GDAL_GCP *pasGCPList,
295312
double cross23 = x[2] * y[3] - x[3] * y[2];
296313
if (cross12 * cross23 <= 0.0)
297314
{
315+
CPLError(CE_Failure, CPLE_AppDefined,
316+
"GDALGCPsToHomography() failed: cross12 * cross23 <= 0.0");
298317
return FALSE;
299318
}
300319

@@ -423,7 +442,7 @@ int GDALApplyHomography(const double *padfHomography, double dfPixel,
423442
int GDALInvHomography(const double *padfHIn, double *padfHOut)
424443

425444
{
426-
// Special case - no rotation - to avoid computing determinate
445+
// Special case - no rotation - to avoid computing determinant
427446
// and potential precision issues.
428447
if (padfHIn[2] == 0.0 && padfHIn[4] == 0.0 && padfHIn[1] != 0.0 &&
429448
padfHIn[5] != 0.0 && padfHIn[7] == 0.0 && padfHIn[8] == 0.0 &&
@@ -438,10 +457,10 @@ int GDALInvHomography(const double *padfHIn, double *padfHOut)
438457
padfHOut[6] = 1.0 / padfHIn[6];
439458
padfHOut[7] = 0.0;
440459
padfHOut[8] = 0.0;
441-
return 1;
460+
return TRUE;
442461
}
443462

444-
// Compute determinate.
463+
// Compute determinant.
445464

446465
const double det = padfHIn[1] * padfHIn[5] * padfHIn[6] -
447466
padfHIn[2] * padfHIn[4] * padfHIn[6] +
@@ -454,7 +473,11 @@ int GDALInvHomography(const double *padfHIn, double *padfHOut)
454473
std::max(fabs(padfHIn[4]), fabs(padfHIn[5])));
455474

456475
if (fabs(det) <= 1e-10 * magnitude * magnitude)
457-
return 0;
476+
{
477+
CPLError(CE_Failure, CPLE_AppDefined,
478+
"GDALInvHomography() failed: null determinant");
479+
return FALSE;
480+
}
458481

459482
const double inv_det = 1.0 / det;
460483

@@ -472,7 +495,7 @@ int GDALInvHomography(const double *padfHIn, double *padfHOut)
472495
padfHOut[3] = (padfHIn[0] * padfHIn[4] - padfHIn[1] * padfHIn[3]) * inv_det;
473496
padfHOut[6] = (padfHIn[1] * padfHIn[5] - padfHIn[2] * padfHIn[4]) * inv_det;
474497

475-
return 1;
498+
return TRUE;
476499
}
477500

478501
/************************************************************************/

autotest/alg/gcps2homography.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -226,26 +226,26 @@ def test_gcps2h_8():
226226

227227
def test_gcps2h_broken_hour_glass():
228228

229-
h = gdal.GCPsToHomography(
230-
_list2gcps(
231-
[
232-
(0, 0, 0, 0),
233-
(0, 10, 0, 10),
234-
(10, 0, 10, 10),
235-
(10, 10, 10, 0),
236-
]
229+
with pytest.raises(Exception, match=r"cross12 \* cross23 <= 0.0"):
230+
gdal.GCPsToHomography(
231+
_list2gcps(
232+
[
233+
(0, 0, 0, 0),
234+
(0, 10, 0, 10),
235+
(10, 0, 10, 10),
236+
(10, 10, 10, 0),
237+
]
238+
)
237239
)
238-
)
239-
assert h is None
240240

241-
h = gdal.GCPsToHomography(
242-
_list2gcps(
243-
[
244-
(0, 0, 0, 0),
245-
(0, 10, 10, 10),
246-
(10, 0, 10, 0),
247-
(10, 10, 0, 10),
248-
]
241+
with pytest.raises(Exception, match=r"cross12 \* cross23 <= 0.0"):
242+
gdal.GCPsToHomography(
243+
_list2gcps(
244+
[
245+
(0, 0, 0, 0),
246+
(0, 10, 10, 10),
247+
(10, 0, 10, 0),
248+
(10, 10, 0, 10),
249+
]
250+
)
249251
)
250-
)
251-
assert h is None

autotest/alg/homography.py

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,10 @@
1212
# SPDX-License-Identifier: MIT
1313
###############################################################################
1414

15-
import gdaltest
1615
import pytest
1716

1817
from osgeo import gdal
1918

20-
21-
###############################################################################
22-
@pytest.fixture(autouse=True, scope="module")
23-
def module_disable_exceptions():
24-
with gdaltest.disable_exceptions():
25-
yield
26-
27-
2819
###############################################################################
2920
# Test gdal.InvHomography()
3021

@@ -52,16 +43,16 @@ def test_homography_1():
5243
assert res == pytest.approx(expected_inv_h, abs=1e-6), res
5344

5445
h = (10, 1, 1, 20, 2, 2, 1, 0, 0)
55-
res = gdal.InvHomography(h)
56-
assert not res
46+
with pytest.raises(Exception, match="null determinant"):
47+
gdal.InvHomography(h)
5748

5849
h = (10, 1e10, 1e10, 20, 2e10, 2e10, 1, 0, 0)
59-
res = gdal.InvHomography(h)
60-
assert not res
50+
with pytest.raises(Exception, match="null determinant"):
51+
gdal.InvHomography(h)
6152

6253
h = (10, 1e-10, 1e-10, 20, 2e-10, 2e-10, 1, 0, 0)
63-
res = gdal.InvHomography(h)
64-
assert not res
54+
with pytest.raises(Exception, match="null determinant"):
55+
gdal.InvHomography(h)
6556

6657
# Test fix for #1615
6758
h = (-2, 1e-8, 1e-9, 52, 1e-9, -1e-8, 1, 0, 0)

0 commit comments

Comments
 (0)