annotate make-tile @ 1:d268ae31f94b

Add docstring.
author David Barts <n5jrn@me.com>
date Tue, 24 Aug 2021 18:01:12 -0700
parents c20b5314774f
children 94762476b171
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
1 #!/usr/bin/env python3
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
3 # should honor GDALBIN, if set, else use PATH
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
4 # https://opengislab.com/blog/2016/4/2/usgs-geopdf-to-geotif-with-gdal
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
5 # gdalinfo -json -mdd LAYERS gunk.pdf
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
6 # build list of all non-Map.Frame.* layers
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
7 # to that add Map_Frame.Projection_and_Grids
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
8 # First:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
9 # gdal_translate gunk.pdf /tmp/xxxxx.tif -of GTiff --config GDAL_PDF_LAYERS_OFF Map_Collar,Map_Frame.Projections_and_Grids,Map_Frame.Terrain.Shaded_Relief,Images.Orthoimage --config GDAL_PDF_DPI 300
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
10 # Then:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
11 # gdal_translate /tmp/xxxxx.tif gunk.tif -of GTiff -srcwin xoff yoff xsize ysize
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
12 # Need to filter out all errors containing: insufficient arguments for Marked Content
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
13 # also fiter out: More than 1000 errors or warnings have been reported. No more will be reported from now.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
14
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
15 # I m p o r t s
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
16
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
17 import os, sys
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
18 import argparse
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
19 import json
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
20 import subprocess, shutil
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
21 import locale
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
22 from abc import abstractmethod
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
23 from enum import IntEnum
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
24 from tempfile import TemporaryDirectory
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
25
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
26 # PIL is ...weird... and needs both of these.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
27 import PIL
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
28 from PIL import Image
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
29
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
30 # V a r i a b l e s
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
31
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
32 MYNAME = os.path.basename(sys.argv[0])
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
33 estat = 0
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
34 ENCODING = "UTF-8"
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
35 ENVIRON = os.environ.copy()
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
36 for k in ENVIRON.keys():
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
37 if k.startswith("LC_"): del(ENVIRON[k])
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
38 ENVIRON["LANG"] = ENVIRON["LC_ALL"] = "C." + ENCODING
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
39
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
40 # C l a s s e s
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
41
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
42 # A horizontal or vertical strip of an image. Assumes RGB images with 8-bit
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
43 # color.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
44 class Strip:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
45 def __init__(self, based_on, index):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
46 if not isinstance(based_on, PIL.Image.Image):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
47 raise TypeError("Expecting RGB PIL.Image object for based_on.")
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
48 if based_on.mode != "RGB":
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
49 raise ValueError("Expecting RGB PIL.Image object for based_on.")
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
50 self._index = index
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
51 self._based_on = based_on
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
52
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
53 @property
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
54 def index(self):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
55 return self._index
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
56
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
57 @abstractmethod
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
58 def __len__(self):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
59 pass
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
60
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
61 @abstractmethod
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
62 def __getitem__(self, key):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
63 pass
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
64
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
65 @abstractmethod
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
66 def __setitem__(self, key, value):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
67 pass
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
68
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
69 def is_all_white(self):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
70 for i in range(len(self)):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
71 if self[i] != (255, 255, 255):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
72 return False
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
73 return True
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
74
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
75 # A horizontal strip of an image.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
76 class Row(Strip):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
77 def __len__(self):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
78 return self._based_on.width
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
79
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
80 def __getitem__(self, key):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
81 return self._based_on.getpixel((key, self._index))
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
82
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
83 def __setitem__(self, key, value):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
84 self._based_on.setpixel((key, self._index), value)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
85
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
86 # A vertical strip of an image.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
87 class Column(Strip):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
88 def __len__(self):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
89 return self._based_on.height
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
90
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
91 def __getitem__(self, key):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
92 return self._based_on.getpixel((self._index, key))
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
93
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
94 def __setitem__(self, key, value):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
95 self._based_on.setpixel((self._index, key), value)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
96
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
97 # A direction in which to search.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
98 class Direction(IntEnum):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
99 DESCENDING = -1
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
100 ASCENDING = 1
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
101
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
102 # An orientation in which to search.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
103 class Orientation(IntEnum):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
104 VERTICAL = 0
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
105 HORIZONTAL = 1
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
106
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
107 class TopoTilerException(Exception):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
108 pass
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
109
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
110 # F u n c t i o n s
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
111
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
112 def find_edge(image, orientation, direction):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
113 """
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
114 Find an edge in an image with a white border.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
115 """
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
116 if orientation == Orientation.VERTICAL:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
117 what = "column"
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
118 strip = Column
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
119 maxn = image.width - 1
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
120 else:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
121 what = "row"
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
122 strip = Row
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
123 maxn = image.height - 1
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
124 # Establish outer bound and sanity-check it.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
125 outer = 0 if direction == Direction.ASCENDING else maxn
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
126 if not strip(image, outer).is_all_white():
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
127 raise TopoTilerException("Unexpected nonwhite edge ({0} = {1})!".format(what, outer))
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
128 # Establish inner bound and sanity-check it.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
129 inner = outer + direction * maxn // 4
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
130 if strip(image, inner).is_all_white():
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
131 raise TopoTilerException("Unexpected white strip ({0} = {1})!".format(what, inner))
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
132 while abs(outer - inner) > 1:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
133 new = (outer + inner) // 2
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
134 if strip(image, new).is_all_white():
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
135 outer = new
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
136 else:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
137 inner = new
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
138 return inner
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
139
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
140 def positive_int(string):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
141 """
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
142 Specify a positive integer argument.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
143 """
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
144 try:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
145 ret = int(string)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
146 except ValueError as e:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
147 raise argparse.ArgumentTypeError(e.message)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
148 if ret <= 0:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
149 raise argparse.ArgumentTypeError("%r is 0 or negative" % string)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
150 return ret
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
151
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
152 def gdalcmd(command, *args):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
153 """
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
154 Build gdal command vector for subprocess.Popen
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
155 """
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
156 # print('$', command, ' '.join(args)) # debug
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
157 gdalbin = os.environ.get("GDALBIN")
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
158 cmd = shutil.which(command) if gdalbin is None else os.path.join(gdalbin, command)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
159 ret = list(args)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
160 ret.insert(0, cmd)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
161 return ret
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
162
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
163 _MUZZLE = [
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
164 "insufficient arguments for Marked Content",
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
165 "More than 1000 errors or warnings have been reported."
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
166 ]
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
167 def drainout(stream):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
168 """
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
169 Drain an output/error stream, muzzling the meaningless babble.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
170 """
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
171 for line in stream:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
172 printit = True
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
173 for m in _MUZZLE:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
174 if m in line:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
175 printit = False
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
176 break
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
177 if printit:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
178 sys.stderr.write(line)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
179
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
180 def waitfor(proc):
1
d268ae31f94b Add docstring.
David Barts <n5jrn@me.com>
parents: 0
diff changeset
181 """
d268ae31f94b Add docstring.
David Barts <n5jrn@me.com>
parents: 0
diff changeset
182 Wait for a GDAL command to finish.
d268ae31f94b Add docstring.
David Barts <n5jrn@me.com>
parents: 0
diff changeset
183 """
0
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
184 global estat
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
185 command_name = os.path.basename(proc.args[0])
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
186 status = proc.wait()
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
187 if status < 0:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
188 sys.stderr.write("{0}: {1} killed by signal {2}\n".format(MYNAME, command_name, -status))
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
189 estat = 1
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
190 elif status > 0:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
191 sys.stderr.write("{0}: {1} exited with status {2}\n".format(MYNAME, command_name, status))
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
192 estat = 1
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
193
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
194 _BLACKLIST = set(["Map_Frame.Projection_and_Grids", "Map_Frame.Terrain.Shaded_Relief"])
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
195 def get_default_layers(name):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
196 """
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
197 Given a file, analyze it, and get the list of layers to not include
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
198 when rendering it.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
199 """
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
200 proc = subprocess.Popen(
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
201 gdalcmd("gdalinfo", "-json", "-mdd", "LAYERS", name),
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
202 stdout=subprocess.PIPE, stderr=sys.stderr, env=ENVIRON, encoding=ENCODING)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
203 data = json.load(proc.stdout)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
204 waitfor(proc)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
205 layers = set(["Map_Frame"])
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
206 for layer in data["metadata"]["LAYERS"].values():
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
207 if layer.startswith("Map_Frame.") and layer not in _BLACKLIST:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
208 layers.add(layer)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
209 return ",".join(layers)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
210
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
211 # M a i n P r o g r a m
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
212
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
213 # Parse command-line arguments.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
214 parser = argparse.ArgumentParser(description='Render GeoPDF into GeoTIFF suitable for tiling.')
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
215 parser.add_argument('--layers', '-l', type=str,
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
216 help='List of layers to include (see documentation for default).')
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
217 parser.add_argument('--resolution', '-r', type=positive_int, default=300,
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
218 help='Resolution to render at in DPI.')
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
219 parser.add_argument('file', nargs=1,
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
220 help='File to read (must be a GeoPDF).')
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
221 try:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
222 args = parser.parse_args()
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
223 except SystemExit:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
224 sys.exit(2)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
225
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
226 # File must end with '.pdf' (case insensitive), or else!
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
227 if not isinstance(args.file, str):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
228 # How silly, it gave us a list or a tuple, despite only one of them!
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
229 args.file = args.file[0]
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
230 if not args.file.lower().endswith('.pdf'):
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
231 sys.steder.write("{0}: input file must end with .pdf (case insensitive)\n".format(MYNAME))
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
232
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
233 # Default the set of layers to delete, if necessary
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
234 if args.layers is None:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
235 args.layers = get_default_layers(args.file)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
236
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
237 with TemporaryDirectory() as td:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
238 # Get scratch file name. This goes under TMPDIR; if the default temporary
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
239 # area is too small, set that environment variable accordingly!
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
240 tf = os.path.join(td, "temp.tiff")
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
241
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
242 # Render. The result will have undesired margins.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
243 sys.stdout.write("Rendering (may take a while)...\n")
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
244 sys.stdout.flush()
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
245 proc = subprocess.Popen(
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
246 gdalcmd("gdal_translate", "-q", args.file, tf, "-of", "GTiff", "--config", "GDAL_PDF_LAYERS", args.layers, "--config", "GDAL_PDF_DPI", str(args.resolution)),
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
247 stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, env=ENVIRON, encoding=ENCODING)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
248 drainout(proc.stderr)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
249 waitfor(proc)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
250 sys.stdout.write("Done!\n")
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
251
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
252 # Determine crop marquee.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
253 with Image.open(tf) as im:
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
254 minx = find_edge(im, Orientation.VERTICAL, Direction.ASCENDING)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
255 maxx = find_edge(im, Orientation.VERTICAL, Direction.DESCENDING)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
256 miny = find_edge(im, Orientation.HORIZONTAL, Direction.ASCENDING)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
257 maxy = find_edge(im, Orientation.HORIZONTAL, Direction.DESCENDING)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
258
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
259 # Determine output file name.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
260 outf = os.path.splitext(args.file)[0] + ".tiff"
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
261
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
262 # Crop.
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
263 proc = subprocess.Popen(
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
264 gdalcmd("gdal_translate", "-q", tf, outf, "-of", "GTiff", "-srcwin", str(minx), str(miny), str(maxx-minx+1), str(maxy-miny+1)),
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
265 stdout=subprocess.DEVNULL, stderr=sys.stderr)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
266 waitfor(proc)
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
267
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
268 # AMF...
c20b5314774f Initial commit.
David Barts <n5jrn@me.com>
parents:
diff changeset
269 sys.exit(estat)