Mon « industrialisation artisanale » consiste à disposer d’un script qui me crée les tuiles pour les 5 niveaux de zoom que je souhaite utiliser. Le script a besoin d’un paramètre, le nom du fichier image grand format. Il crée dans le répertoire actif les 5 répertoires, un par niveau de zoom. Tout cela est totalement dépendant de ImageMagick.
Aucune vérification d’erreur... c’est vraiment très sommaire. Mais ça fonctionne...
Le script redimensionne les images pour que les dimensions soient des multiples de 256, en comblant les espaces vides par du blanc.
#!/bin/bash
source_file=$1
tmp_dir=./tmp/
mkdir $tmp_dir
tile_width=256
tile_height=256
minZ=13
maxZ=18
for ((z=$maxZ;z>=$minZ;z--))
do
dest_file=${tmp_dir}zoom_${z}.jpg
if [ $z -eq $maxZ ]; then
image_width=`identify -format %w $source_file`
image_height=`identify -format %h $source_file`
image_width=$(((($image_width+$tile_width-1)/$tile_width)*$tile_width))
image_height=$(((($image_height+$tile_height-1)/$tile_height)*$tile_height))
convert -size ${image_width}x${image_height} -quality 80 xc:white $dest_file
composite -gravity NorthWest $source_file $dest_file $dest_file
#source_file=$dest_file
fi
if [ $z -ne $maxZ ]; then
image_width=`identify -format %w $source_file`
image_height=`identify -format %h $source_file`
image_width=$(($image_width/(2**(maxZ-$z))))
image_height=$(($image_height/(2**(maxZ-$z))))
convert -resize ${image_width}x${image_height} $source_file $dest_file
image_width=$(((($image_width+$tile_width-1)/$tile_width)*$tile_width))
image_height=$(((($image_height+$tile_height-1)/$tile_height)*$tile_height))
temp_file=${tmp_dir}zoom_${z}_temp.jpg
convert -size ${image_width}x${image_height} -quality 80 xc:white $temp_file
composite -gravity NorthWest $dest_file $temp_file $dest_file
fi
mkdir ./${z}/
convert -crop 256x256 +repage $dest_file ./${z}/tiles_%d.png
image_width=`identify -format %w $dest_file`
image_height=`identify -format %h $dest_file`
echo $image_width $image_height
tiles_per_column=$((($image_width+$tile_width-1)/$tile_width))
tiles_per_row=$((($image_height+$tile_height-1)/$tile_height))
total_tiles=$(($tiles_per_column*$tiles_per_row))
n=0
row=0
column=0
for (( i=$n; i<$total_tiles; i++ ))
do
filename=./${z}/tiles_${i}.png
target=./${z}/map_${column}_${row}.png
cp -f $filename $target
column=$(($column + 1))
if [ $column -ge $tiles_per_column ]; then
column=0
row=$(($row + 1))
fi
done
rm -f ./${z}/tiles_*.png
done
rm -rf $tmp_dir
Le fichier html qui va utiliser les images est conçu peu ou prou de la sorte. Il convient de personnaliser les variables mapW et mapH avec les vraies dimensions en pixel de l’image la plus grande.
<html>
<head>
<title>Pirates</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta charset="utf-8">
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" />
<link rel="stylesheet" href="resources/map.css" />
</head>
<body bgcolor="#ffffff">
<div id="map"></div>
<script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script>
<script language="javascript" type="text/javascript">
var maxZ = 18;
var minZ = 13;
var mapW = 7424;
var mapH = 6144;
var mapName = 'pirates';
</script>
<script src="resources/map.js"></script>
</body>
</html>
Le fichier map.css est très simple... Il permet d’avoir un fond blanc dans le conteneur principal :
#map { width:100%;height:100%; }
.leaflet-container { background: #fff; }
Et le fichier map.js contient le code qui initialise l’ensemble. Les tuiles sont attendues dans le répertoire nommé comme la variable « mapName ».
var map = L.map('map',{center: [0, 0], maxZoom: maxZ, minZoom: minZ, crs: L.CRS.Simple}).setView([0, 0], Math.floor((maxZ + minZ) / 2));
var southWest = map.unproject([0, mapH], map.getMaxZoom());
var northEast = map.unproject([mapW, 0], map.getMaxZoom());
map.setMaxBounds(new L.LatLngBounds(southWest, northEast));
L.tileLayer('/' + mapName + '/{z}/map_{x}_{y}.png', {attribution: '© BigGrizzly <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'}).addTo(map);