Skip to content

Instantly share code, notes, and snippets.

@manticorp
Last active September 12, 2023 06:33
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manticorp/3759cdbb3488c529c7d1f0c9b3c74ccf to your computer and use it in GitHub Desktop.
Save manticorp/3759cdbb3488c529c7d1f0c9b3c74ccf to your computer and use it in GitHub Desktop.
Rendering a map from terrarium height map tiles and exporting to 16 bit grayscale PNG

Convert tangram tiles to 16 bit grayscale PNG

Requirements

  • PHP >7.2
    • Composer
  • Python3
    • numpy
    • cupy (optional)
    • PIL

Installation

composer install

Usage

For all options use

php renderLocation.php --help

Example command

php renderLocation.php -a YOUR_API_KEY --latitude 12.345 --longitude 123.456 --zoom 15 -x 5 -y 5 -e

Examples

The examples in this gist are generated using the following command:

php renderLocation.php -a YOUR_API_KEY -l 36.6271 -k 138.20453 -x 8 -y 8 -z 13 -e

On my XPS 15 9350 with i7 and 32GB ram, aside from downloading, the process takes around 15s to complete for this example.

import time
import cupy as cp
import numpy as np
import sys
from os import path
from PIL import Image
Image.MAX_IMAGE_PIXELS = 300000*300000
if len(sys.argv) < 8:
raise ValueError('Should be 7 arguments')
x1 = int(sys.argv[1])
x2 = x1+int(sys.argv[2])
y1 = int(sys.argv[3])
y2 = y1+int(sys.argv[4])
z = int(sys.argv[5])
ss = int(sys.argv[6]) # square size
nfn = sys.argv[7]
newIm = Image.new('RGB', (ss * abs(x2-x1), ss * abs(y2-y1)))
for x in range(x1, x2, 1):
print('Reading row {}'.format(abs(x-x1)))
for y in range(y1, y2, 1):
fn = 'cache/{}-{}-{}.png'.format(z,y,x)
im = Image.open(fn)
newIm.paste(im, (abs((y-y1))*ss, abs((x-x1))*ss))
print('Done reading, now writing')
newIm.save(nfn)
print('Done!')
{
"require": {
"guzzlehttp/guzzle": "7.0",
"league/climate": "^3.8",
"nategood/commando": "^0.4.0",
"symfony/process": "^5.4"
}
}
import time
import cupy as cp
import numpy as np
import sys
from os import path
from PIL import Image
Image.MAX_IMAGE_PIXELS = 300000*300000
if len(sys.argv) < 2:
raise ValueError('No file argument given')
fn = sys.argv[1]
if not path.exists(fn):
raise ValueError('File {} does not exist'.format(fn))
usecupy = False
nfn = '{}-gs-norm-{}.png'.format(path.splitext(fn)[0], 'cupy' if usecupy else 'numpy')
if path.exists(nfn):
raise ValueError('File {} already exists'.format(nfn))
factor = 2**8
rangef = 2**15
rangem = 2**16
step = 6
barwidth = 40
barchar1 = '#'
barchar2 = ' '
start = time.time()
print('Reading image - will write to {}'.format(nfn))
with Image.open(fn) as src:
if usecupy:
print('{} GPU devices found'.format(cp.cuda.runtime.getDeviceCount()))
with cp.cuda.Device(0) as dev0:
dev0.use()
print('Compute Capability {}'.format(dev0.compute_capability))
cparray = cp.asarray(src, dtype='uint8')
print('Image read')
cparray = cparray.dot(cp.array([factor,1,1/factor], dtype='float32'))
cparray = cp.subtract(cparray, rangef, dtype='float32')
maxv = cp.amax(cparray)
minv = cp.amin(cparray)
rangev = maxv - minv
cparray = cp.subtract(cparray, minv)
cparray = cp.multiply(cparray, rangem/(maxv - minv))
dest = Image.fromarray(cp.asnumpy(cparray).astype('uint16'), 'I;16')
print('Writing image - Size {}x{} - mode {}'.format(dest.width, dest.height, dest.mode))
dest.save(nfn)
else:
nparray = np.asarray(src, dtype='uint8')
print('Image read')
nparray = nparray.dot(np.array([factor,1,1/factor], dtype='float32'))
nparray = np.subtract(nparray, rangef, dtype='float32')
maxv = np.amax(nparray)
minv = np.amin(nparray)
rangev = maxv - minv
nparray = np.subtract(nparray, minv, dtype='float32')
nparray = np.multiply(nparray, rangem/(maxv - minv)).astype('uint16')
dest = Image.fromarray(nparray, 'I;16')
print('Writing image - Size {}x{} - mode {}'.format(dest.width, dest.height, dest.mode))
dest.save(nfn)
print('Complete - took {:.1f}s'.format(time.time() - start))
View raw

(Sorry about that, but we can’t show files that are this big right now.)

@gerchprung
Copy link

Hi! I would like to say a big thank you for this app and the web interface for it. It's really cool stuff! This web application simplifies my work so much.

@manticorp
Copy link
Author

Hi! I would like to say a big thank you for this app and the web interface for it. It's really cool stuff! This web application simplifies my work so much.

My pleasure!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment