-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathfactoriomap.py
113 lines (95 loc) · 3.83 KB
/
factoriomap.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
"""Convert a TAR file or directory of Factorio screenshots into Leaflet
map tiles.
Factorio Console Command to generate screenshots:
/c game.player.surface.daytime = 0; for x=-1000,1000 do for y=-1000,1000 do if game.forces["player"].is_chunk_charted(1, {x, y}) then game.take_screenshot{show_entity_info=true, zoom=1, resolution={1024,1024}, position={x=32*x+16,y=32*y+16}, path="DIR/s_"..x.."_"..y..".jpg"}; end; end; end;
"""
import os
from glob import glob
import sys
import tarfile
from PIL import Image
from tqdm import tqdm
USAGE = '''
Usage: python3 factoriomap.py [source] [destination]
source: directory or .tar file
destination: directory
'''
def main():
"""Main executable function."""
# Verify arguments; print usage on failure.
if len(sys.argv) < 3 or not os.path.isdir(sys.argv[2]):
print(USAGE)
sys.exit()
if os.path.isfile(sys.argv[1]):
archive = tarfile.open(sys.argv[1])
chunks = sorted(archive.getnames(), key=chunk_coordinates)
for chunk in tqdm(chunks):
chunk_to_tiles(archive.extractfile(chunk), chunk)
else:
chunks = sorted(glob(sys.argv[1]+'chunk_*.jpg'), key=chunk_coordinates)
for chunk in tqdm(chunks):
chunk_to_tiles(chunk)
for zoom in range(9, 0, -1):
tiles = sorted(
glob('{}{}/*/*.jpg'.format(sys.argv[2], zoom+1)),
key=tile_coordinates)
for tile in tqdm(tiles):
zoom_out(tile, zoom)
def zoom_out(filename, zoom):
"""Shrink and combine tiles to zoom view out."""
source_x, source_y = tile_coordinates(filename)
tile_x = source_x // 2
tile_y = source_y // 2
origin_x = tile_x * 2
origin_y = tile_y * 2
if not os.path.isfile(
'{}{}/{}/{}.jpg'.format(sys.argv[2], zoom, tile_y, tile_x)):
os.makedirs('{}{}/{}'.format(sys.argv[2], zoom, tile_y), exist_ok=True)
tile_image = Image.new('RGB', (512, 512))
for x_adj in range(2):
for y_adj in range(2):
try:
paste_image = Image.open('{}{}/{}/{}.jpg'.format(
sys.argv[2], zoom+1, origin_y+y_adj, origin_x+x_adj))
except FileNotFoundError:
paste_image = Image.new('RGB', (256, 256))
tile_image.paste(
paste_image,
(x_adj*256, y_adj*256))
tile_image.resize((256, 256)).save('{}{}/{}/{}.jpg'.format(
sys.argv[2], zoom, tile_y, tile_x))
def chunk_coordinates(filename):
"""Extract chunk coordinates from filename."""
_, chunk_x, chunk_y = os.path.splitext(filename)[0].split('_')
return (int(chunk_x), int(chunk_y))
def tile_coordinates(path):
"""Compute tile coordinates."""
explosion = os.path.splitext(path)[0].split('/')
return (int(explosion[-1]), int(explosion[-2]))
def chunk_to_tiles(chunk, chunkname=None):
"""Convert the chunk screenshot to Leaflet tiles at maximum zoom."""
chunk_image = Image.open(chunk)
if chunkname is None:
chunk_x, chunk_y = chunk_coordinates(chunk)
else:
chunk_x, chunk_y = chunk_coordinates(chunkname)
tile_x = chunk_x*4
tile_y = chunk_y*4
if not os.path.isfile(
'{}{}/{}/{}.jpg'.format(sys.argv[2], 10, tile_y, tile_x)):
for x_adj in range(4):
for y_adj in range(4):
os.makedirs(
'{}{}/{}'.format(
sys.argv[2], 10, tile_y+y_adj),
exist_ok=True)
chunk_image.crop(
(
x_adj*256,
y_adj*256,
(x_adj+1)*256,
(y_adj+1)*256)
).save('{}{}/{}/{}.jpg'.format(
sys.argv[2], 10, tile_y+y_adj, tile_x+x_adj))
if __name__ == '__main__':
main()