Skip to content

Commit 1c4caf3

Browse files
authored
Merge pull request #11144 from dbaston/add_doc_gdalenhance
gdalenhance: add docs and tests
2 parents 71535b5 + 784ba1c commit 1c4caf3

File tree

7 files changed

+220
-10
lines changed

7 files changed

+220
-10
lines changed

apps/gdalenhance.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,13 @@ MAIN_START(argc, argv)
339339
}
340340
}
341341

342+
if (padfScaleMin == nullptr || padfScaleMax == nullptr)
343+
{
344+
fprintf(stderr, "-equalize or -config filename command line options "
345+
"must be specified.\n");
346+
Usage();
347+
}
348+
342349
/* -------------------------------------------------------------------- */
343350
/* If there is no destination, just report the scaling values */
344351
/* and luts. */
@@ -352,9 +359,8 @@ MAIN_START(argc, argv)
352359
for (iBand = 0; iBand < nBandCount; iBand++)
353360
{
354361
fprintf(fpConfig, "%d:Band ", iBand + 1);
355-
if (padfScaleMin != nullptr)
356-
fprintf(fpConfig, "%g:ScaleMin %g:ScaleMax ",
357-
padfScaleMin[iBand], padfScaleMax[iBand]);
362+
fprintf(fpConfig, "%g:ScaleMin %g:ScaleMax ", padfScaleMin[iBand],
363+
padfScaleMax[iBand]);
358364

359365
if (papanLUTs)
360366
{
@@ -372,13 +378,6 @@ MAIN_START(argc, argv)
372378
exit(0);
373379
}
374380

375-
if (padfScaleMin == nullptr || padfScaleMax == nullptr)
376-
{
377-
fprintf(stderr, "-equalize or -config filename command line options "
378-
"must be specified.\n");
379-
exit(1);
380-
}
381-
382381
/* ==================================================================== */
383382
/* Create a virtual dataset. */
384383
/* ==================================================================== */

autotest/pymod/test_cli_utilities.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,14 @@ def get_gdaldem_path():
208208
#
209209

210210

211+
def get_gdalenhance_path():
212+
return get_cli_utility_path("gdalenhance")
213+
214+
215+
###############################################################################
216+
#
217+
218+
211219
def get_gdal_rasterize_path():
212220
return get_cli_utility_path("gdal_rasterize")
213221

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/usr/bin/env pytest
2+
# -*- coding: utf-8 -*-
3+
###############################################################################
4+
#
5+
# Project: GDAL/OGR Test Suite
6+
# Purpose: gdalenhance testing
7+
# Author: Daniel Baston <dbaston at gmail.com>
8+
#
9+
###############################################################################
10+
# Copyright (c) 2024, ISciences LLC
11+
#
12+
# SPDX-License-Identifier: MIT
13+
###############################################################################
14+
15+
import gdaltest
16+
import pytest
17+
import test_cli_utilities
18+
19+
from osgeo import gdal
20+
21+
pytestmark = pytest.mark.skipif(
22+
test_cli_utilities.get_gdalenhance_path() is None,
23+
reason="gdalenhance not available",
24+
)
25+
26+
27+
@pytest.fixture()
28+
def gdalenhance_path():
29+
return test_cli_utilities.get_gdalenhance_path()
30+
31+
32+
###############################################################################
33+
# Output a lookup table, then apply it to the image
34+
35+
36+
def test_gdalenhance_output_histogram(gdalenhance_path, tmp_path):
37+
38+
out, err = gdaltest.runexternal_out_and_err(
39+
f"{gdalenhance_path} -quiet -equalize ../gcore/data/rgbsmall.tif"
40+
)
41+
42+
assert not err
43+
44+
lines = out.strip().split("\n")
45+
assert len(lines) == 3
46+
47+
assert lines[0].startswith("1:Band ")
48+
assert lines[1].startswith("2:Band ")
49+
assert lines[2].startswith("3:Band ")
50+
51+
lut_fname = tmp_path / "lut.txt"
52+
53+
with open(lut_fname, "w") as outfile:
54+
for line in lines:
55+
outfile.write(line.strip())
56+
outfile.write("\n")
57+
58+
enhanced_fname = tmp_path / "out.tif"
59+
60+
out, err = gdaltest.runexternal_out_and_err(
61+
f"{gdalenhance_path} -quiet -config {lut_fname} ../gcore/data/rgbsmall.tif {enhanced_fname}"
62+
)
63+
64+
assert not err
65+
66+
assert enhanced_fname.exists()
67+
68+
69+
###############################################################################
70+
# Write a new image directly
71+
72+
73+
def test_gdalenhance_output_image(gdalenhance_path, tmp_path):
74+
75+
infile = "../gcore/data/rgbsmall.tif"
76+
outfile = tmp_path / "out.tif"
77+
78+
out, err = gdaltest.runexternal_out_and_err(
79+
f"{gdalenhance_path} -quiet -equalize -co COMPRESS=DEFLATE {infile} {outfile}"
80+
)
81+
82+
assert not err
83+
84+
with gdal.Open(infile) as src, gdal.Open(outfile) as dst:
85+
assert src.RasterCount == dst.RasterCount
86+
assert src.RasterXSize == dst.RasterXSize
87+
assert src.RasterYSize == dst.RasterYSize
88+
89+
# check that -co was honored
90+
assert dst.GetMetadata("IMAGE_STRUCTURE")["COMPRESSION"] == "DEFLATE"
91+
92+
93+
###############################################################################
94+
# Usage printed with invalid arguments
95+
96+
97+
def test_gdalenhance_invalid_usage(gdalenhance_path, tmp_path):
98+
99+
infile = "../gcore/data/rgbsmall.tif"
100+
outfile = tmp_path / "out.tif"
101+
102+
out, err = gdaltest.runexternal_out_and_err(
103+
f"{gdalenhance_path} -quiet {infile} {outfile}"
104+
)
105+
106+
assert "ret code = 1" in err
107+
assert "Usage" in out
Loading
Loading

doc/source/programs/gdalenhance.rst

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
.. _gdalenhance:
2+
3+
================================================================================
4+
gdalenhance
5+
================================================================================
6+
7+
.. only:: html
8+
9+
Enhance the contrast of raster images using histogram equalization.
10+
11+
.. Index:: gdalenhance
12+
13+
Synopsis
14+
--------
15+
16+
.. code-block::
17+
18+
gdalenhance [--help-general]
19+
[-of format] [-co "NAME=VALUE"]*
20+
[-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/
21+
CInt16/CInt32/CFloat32/CFloat64}]
22+
[-equalize]
23+
[-config filename]
24+
<src_raster> [<dst_raster>]
25+
26+
Description
27+
-----------
28+
29+
The :program:`gdalenhance` utility enhances the contrast of raster images using
30+
histogram equalization. It can either generate a LUT (look-up-table) that can
31+
later be applied to enhance contrast, or it can write the enhanced image
32+
directly.
33+
34+
.. figure:: ../../images/programs/gdalenhance_little_spruce.jpg
35+
36+
Original image.
37+
38+
.. figure:: ../../images/programs/gdalenhance_little_spruce_enhanced.jpg
39+
40+
Image after histogram equalization using :program:`gdalenhance`.
41+
42+
43+
.. program:: gdalenhance
44+
45+
.. include:: options/help_and_help_general.rst
46+
47+
.. option:: -of format
48+
49+
Select the output format. The default is GeoTIFF (GTiff).
50+
51+
.. include:: options/co.rst
52+
53+
.. include:: options/ot.rst
54+
55+
.. option:: -equalize
56+
57+
Get source image histogram and compute equalization LUTs from
58+
it.
59+
60+
.. option:: -config <filename>
61+
62+
Apply a specified LUT to enhance the contrast of the image.
63+
The number of lines in the LUT file should be equal to the number of bands
64+
of the images.
65+
Example of LUT file:
66+
67+
.. code-block::
68+
69+
1:Band -0.5:ScaleMin 255.5:ScaleMax 0 0 8 16 16 17 17 17 17 18 18 18 18 18 18 19 19 19 19 20 20 20 21 21 21 22 22 22 23 23 24 24 25 25 26 27 27 28 29 30 30 31 32 33 34 35 36 37 38 39 40 42 43 44 46 47 48 50 51 53 55 56 58 60 62 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 101 103 105 107 109 111 113 115 117 119 121 123 125 127 129 131 133 135 137 138 140 142 144 146 148 150 152 153 155 157 159 161 162 164 166 168 169 171 173 174 176 178 179 181 182 184 186 187 189 190 192 193 195 196 198 199 200 202 203 205 206 207 208 210 211 212 213 214 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 234 235 236 237 238 239 239 240 241 241 242 243 244 244 245 245 246 246 247 247 248 248 249 249 250 250 250 251 251 251 251 251 252 252 252 252 252 252 252 252 252 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 254 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
70+
2:Band -0.5:ScaleMin 255.5:ScaleMax 0 0 8 16 16 16 17 17 17 17 17 17 17 17 17 18 18 18 18 18 18 19 19 19 19 19 20 20 20 20 21 21 22 22 23 23 24 24 25 26 27 27 28 29 30 31 32 33 34 35 36 37 38 39 41 42 43 45 46 47 49 51 52 54 55 57 59 60 62 64 66 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 101 103 105 108 110 112 114 116 118 120 122 124 126 128 130 132 134 136 138 140 142 144 146 148 150 152 154 156 157 159 161 163 165 166 168 170 172 173 175 177 179 180 182 183 185 187 188 190 191 193 194 196 197 199 200 202 203 204 206 207 208 209 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 230 231 232 233 234 235 235 236 237 238 239 239 240 241 241 242 243 243 244 245 245 246 246 247 247 248 248 248 249 249 250 250 250 250 251 251 251 251 252 252 252 252 252 252 252 252 252 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 254 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
71+
3:Band -0.5:ScaleMin 255.5:ScaleMax 0 0 9 17 17 18 18 18 18 18 19 19 19 19 19 19 20 20 20 20 20 20 21 21 21 21 21 21 22 22 22 22 22 23 23 23 24 24 24 25 25 26 26 27 28 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 44 45 46 47 48 50 51 53 54 56 57 59 60 62 63 65 67 69 70 72 74 76 78 80 82 84 86 88 90 92 94 97 99 101 103 105 107 109 111 113 115 116 118 120 122 124 126 127 129 131 133 134 136 138 139 141 143 144 146 147 149 151 152 154 155 157 159 160 162 163 165 167 168 170 171 173 175 176 178 179 181 182 184 186 187 189 190 192 193 195 197 198 200 201 203 204 206 207 209 210 212 213 214 216 217 218 219 220 222 223 224 225 226 227 228 229 230 231 232 233 233 234 235 236 237 238 239 239 240 241 242 243 243 244 245 246 246 247 247 248 248 249 249 250 250 251 251 251 251 252 252 252 252 252 252 252 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 255 255 255 255 255 255 2550
72+
73+
Example
74+
--------
75+
76+
.. code-block::
77+
78+
gdalenhance -equalize rgb.tif rgb_equalize_enhance.tif
79+
80+
Apply equalization histogram to enhance the contrast of the image.
81+
82+
83+
.. code-block::
84+
85+
gdalenhance -equalize rgb.tif
86+
87+
Write an equalization LUT to the console.
88+
89+
90+
.. code-block::
91+
92+
gdalenhance -config enhance_config rgb.tif rgb_custom_enhance.tif
93+
94+
Apply a custom LUT (look up-table) to enhance the contrast of the image.

doc/source/programs/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Raster programs
5050
gdalbuildvrt
5151
gdalcompare
5252
gdaldem
53+
gdalenhance
5354
gdalinfo
5455
gdallocationinfo
5556
gdalmanage
@@ -89,6 +90,7 @@ Raster programs
8990
- :ref:`gdalbuildvrt`: Builds a VRT from a list of datasets.
9091
- :ref:`gdalcompare`: Compare two images.
9192
- :ref:`gdaldem`: Tools to analyze and visualize DEMs.
93+
- :ref:`gdalenhance`: Enhance an image with LUT-based contrast enhancement
9294
- :ref:`gdalinfo`: Lists information about a raster dataset.
9395
- :ref:`gdallocationinfo`: Raster query tool
9496
- :ref:`gdalmanage`: Identify, delete, rename and copy raster data files.

0 commit comments

Comments
 (0)