Last active
June 1, 2022 18:46
-
-
Save defremov/e4f0ed47e1402ba65edd9e2d4c2b210c to your computer and use it in GitHub Desktop.
Convert raster images of Slazav's map series (https://slazav.xyz/maps/podm.htm) to Garmin JNX format files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.SUFFIXES: | |
map_files := $(wildcard *.map) | |
jnx_files := $(map_files:%.map=%.jnx) | |
.PHONY: all | |
all: $(jnx_files) | |
%.jnx: %.png %.map | |
bash slazav2jnx.sh $^ $@ | |
clean: | |
rm -f $(jnx_files) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env awk -f | |
# Copyright (C) 2020 Dmitry Efremov <defremov аt aha dоt ru> | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <https://www.gnu.org/licenses/>. | |
function mins_to_dec_degs(degs, mins, hemi) { | |
sign = (hemi == "S" || hemi == "W") ? -1 : 1 | |
return sign * (degs + mins / 60.) | |
} | |
function expand_bounds(lat, lon) { | |
if (lat < minlat) minlat = lat | |
if (lon < minlon) minlon = lon | |
if (lat > maxlat) maxlat = lat | |
if (lon > maxlon) maxlon = lon | |
} | |
BEGIN { | |
_abort = 0 | |
FS = "\\s*,\\s*" | |
CONVFMT = "%.8f" | |
minlat = 90. | |
maxlat = -90. | |
minlon = 180. | |
maxlon = -180. | |
if (!gcp_cmd) { | |
gcp_cmd = "cat" | |
} | |
i = 0 | |
} | |
/^Point[0-9]{2},xy,\s*[0-9]+,/ { | |
xy[i++]= $3 " " $4 | |
lat = mins_to_dec_degs($7, $8, $9) | |
lon = mins_to_dec_degs($10, $11, $12) | |
print lon " " lat |& gcp_cmd | |
expand_bounds(lat, lon) | |
} | |
END { | |
if (_abort) { | |
exit _abort | |
} | |
if (!extents_file) { | |
extents_file = "/dev/stdout" | |
} | |
print minlon, minlat >extents_file | |
print maxlon, maxlat >extents_file | |
if (!gcp_file) { | |
gcp_file = "/dev/stdout" | |
} | |
close(gcp_cmd, "to") | |
i = 0 | |
while ((gcp_cmd |& getline lonlat) > 0) { | |
sub(/\s+0$/, "", lonlat) | |
print xy[i++] " " lonlat >gcp_file | |
} | |
close(gcp_cmd) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env bash | |
# This script converts raster images of Slazav's map series | |
# (https://slazav.xyz/maps/podm.htm) to Garmin JNX format | |
# files. | |
# | |
# Depends on: gawk, map2jnx tool and GDAL utilities. | |
# | |
# Example: to convert N55aE037 sheet to JNX format download | |
# N55aE037.png and N55aE037.map files then run: | |
# slazav2jnx.sh N55aE037.{png,map} N55aE037.jnx | |
# | |
# Copyright (C) 2020 Dmitry Efremov <defremov аt aha dоt ru> | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <https://www.gnu.org/licenses/>. | |
set -Eeuo pipefail | |
PATH=/sbin:/usr/sbin:/bin:/usr/bin | |
export PATH | |
progname="${0##*/}" | |
slazav_map="$(dirname "$0")/slazav-map.awk" | |
declare -a tmpfiles | |
map2jnx=qmt_map2jnx | |
# Suitable for a 160×240 display | |
declare -a jnx_scale_values=(31250 7813 5209 2084 1303) | |
slazav_map_image='' | |
slazav_map_data_file='' | |
jnx_file='' | |
jnx_title='' | |
newtmp() { | |
while (( $# )) ; do | |
tmpfiles=($(mktemp) ${tmpfiles[@]}) | |
eval "${1}=${tmpfiles}" | |
shift | |
done | |
} | |
term_handler() { | |
local signal="${1}" | |
>&2 printf "\n%s: caught %s signal, exiting.\n" \ | |
"${progname}" "${signal}" | |
exit 1 | |
} | |
set_signal_handlers() { | |
trap 'set +e ; kill $(jobs -p) 2>/dev/null ; \ | |
rm -f ${tmpfiles[@]}' EXIT | |
for signal in INT QUIT TERM ; do | |
trap 'term_handler "${signal}"' ${signal} | |
done | |
} | |
usage() { | |
cat <<EOF | |
${progname} script converts raster images of Slazav's map series | |
(http://slazav.mccme.ru/maps/podm/index.htm) to Garmin JNX format | |
files. | |
Usage: ${progname} [options] map_image map_data_file jnx_file [jnx_title] | |
Options: | |
-h show this help message and exit | |
Depends on: gawk, map2jnx tool and GDAL utilities. | |
Example: to convert N55aE037 sheet to JNX format download N55aE037.png | |
and N55aE037.map files then run: | |
${progname} N55aE037.{png,map} N55aE037.jnx 'Slazav N55aE037' | |
EOF | |
} | |
parse_parameters() { | |
while getopts "hn" OPT; do | |
case "${OPT}" in | |
h) | |
usage | |
exit 0 | |
;; | |
\?) | |
echo | |
>&2 usage | |
exit 1 | |
;; | |
esac | |
done | |
shift $((${OPTIND} - 1)) | |
if [[ $# -lt 3 ]] ; then | |
>&2 printf \ | |
"${progname}: script requires 3 arguments.\n\n" | |
>&2 usage | |
exit 1 | |
fi | |
slazav_map_image="${1}" | |
slazav_map_data_file="${2}" | |
jnx_file="${3}" | |
jnx_title="${4:-${jnx_file%.*}}" | |
} | |
slazav2jnx() { | |
# Extract ground control points data and the map extents from | |
# the supplied map data file (.map). | |
# The GCPs are reprojected from WGS 84 to Pulkovo 1942 / | |
# Gauss-Kruger zone 7 coordinate system | |
local pulkovo_42_gcps | |
local cmd='gdaltransform -s_srs EPSG:4326 -t_srs EPSG:28407' | |
newtmp pulkovo_42_gcps | |
local wgs_84_extents=$(awk -f "${slazav_map}" \ | |
-v gcp_cmd="${cmd}" -v gcp_file="${pulkovo_42_gcps}" \ | |
"${slazav_map_data_file}") | |
# Convert the supplied source map image to 24-bit RGB GeoTIFF | |
# format and make it georeferenced by adding the GCPs from the | |
# previous step | |
local pulkovo_42_gcp_image | |
newtmp pulkovo_42_gcp_image | |
gdal_translate -of GTiff -expand rgb\ | |
$(awk '{print " -gcp", $0}' "${pulkovo_42_gcps}") \ | |
-a_srs EPSG:28407 \ | |
"${slazav_map_image}" "${pulkovo_42_gcp_image}" | |
# Reproject the extents of the source map from WGS 84 to the | |
# World Mercator coordinate system | |
local world_mercator_extents=$(gdaltransform -s_srs EPSG:4326 \ | |
-t_srs EPSG:3395 <<<"${wgs_84_extents}" | \ | |
awk '{print $1, $2}') | |
# Reproject the georeferenced image to the World Mercator CS | |
local world_mercator_prj_image | |
newtmp world_mercator_prj_image | |
gdalwarp -t_srs EPSG:3395 \ | |
-te ${world_mercator_extents} -of GTiff -overwrite \ | |
"${pulkovo_42_gcp_image}" "${world_mercator_prj_image}" | |
# Get the width and height in pixels of the World Mercator | |
# image | |
declare -a pixel_size=($(gdalinfo \ | |
"${world_mercator_prj_image}" | awk -F',\\s*' \ | |
'/^Size is / {sub(/^[^0-9]*/, ""); print $1, $2}')) | |
# Reproject the georeferenced image from Pulkovo 42 to WGS 84 | |
# CS and downscale it to a set of level of detail images using | |
# the width and height in pixels from the previous step | |
local level_image | |
declare -a level_images | |
for n in "${!jnx_scale_values[@]}" ; do | |
newtmp level_image | |
level_images=(${level_image} ${level_images[@]}) | |
# Halve the resolution of each successive level | |
gdalwarp -t_srs EPSG:4326 -r cubic \ | |
-te ${wgs_84_extents} \ | |
-ts $(( (${pixel_size[0]} + $n) >> $n )) \ | |
$(( (${pixel_size[1]} + $n) >> $n )) \ | |
-of GTiff -overwrite \ | |
"${pulkovo_42_gcp_image}" "${level_image}" | |
done | |
# Convert the set of level of detail images to a JNX file | |
local x_param=${jnx_scale_values[@]} | |
"${map2jnx}" -q 90 -s 444 -x ${x_param// /,} \ | |
-p 90 -m "${jnx_title}" "${level_images[@]}" \ | |
"${jnx_file}" | |
} | |
main() { | |
set_signal_handlers | |
parse_parameters "${@}" | |
slazav2jnx | |
exit 0 | |
} | |
main "${@}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment