Jump to content
x3kj

[Resource] Greyscale image heightmap to .asc converter (Python script)

Recommended Posts

Idk if it's of use to anyone, but i made a python script to convert greyscale images to .asc format for importing into terrain builder.

I use it to convert 16bit .tif images out of substance designer to .asc, because L3DT and TB dont like the format that much / require manual twiddling everytime

You can also try other image formats (the library supports a plethora of other formats) - just change myheightmap.tif to myheightmap.png or whatever. I have only tested it for my particular use case however and i'm no expert on that library or python in general (in fact, this is my first ever python script).

 

How to execute?

  • If you are a dummy like me and dont know how to Python or sudo - install anaconda distribution, it has all the necessary libraries, then launch spyder tool (that comes with it) and open the file, then run it with F5. Yes it's overkill but its single click...
  • edit the user inputs as applicable to your use case

 

Notes:

  • Sea level is 0 meter
  • min/max elevation are the 0% and 100% grey value in the image format. It doesnt auto-level the image.
  • Image resolution doesnt have to be square or 2^n - wether TB or other tools like it or not i have no idea
  • Conversion on 4k maps takes a while (wait until "###Conversion done###" appears in the console)
  • use at own risk...
import numpy as np
from pathlib import Path
import imageio as io
 
### user inputs ###
filepath = Path("""P:/myheightmap.tif""")
outputpath = Path ("""P:/output.asc""") #attention - any existing file with same name is overwritten
 
hmax = 1000.0       #Input max Elevation (in meter)
hmin = -200.0       #Input min Elevation (in meter)
twidth = 2000.0     #Input mapsize (width in meter)
limit = 2**16       #max grey value of file (16bit-> 2**16, 8bit-> 2**8)
 
########## load image ################
arr = io.imread(filepath)
arr = np.array(arr, np.float32)
adim = arr.shape # dimension of array - returns [Height, Width]
 
cellsize = float(adim[1]/twidth)
print ('Image Resolution:'+str(arr.shape)+' Cellsize:'+str(cellsize))
 
########## write to file ################
file = open(outputpath,'wt') # wt - write mode, text mode. Overwrites any existing file
 
###file header
file.write('ncols         '+str(adim[1])+'\n')
file.write('nrows         '+str(adim[0])+'\n')
file.write('xllcorner     200000.0\n')
file.write('yllcorner     0.000000\n')
file.write('cellsize      '+str(cellsize)+'\n')
file.write('NODATA_value  -9999\n')
 
###body
for y in range (0, adim[0]):                                                    # -1 is not necessary because in case adim[0]= 3 then range is [0,1,2] -> 3 is not in the range
    line =str()                                                                 # empty string
    for x in range (0, adim[1]):
        arr[y,x] = round (hmin + (arr[y,x] / limit) * (hmax - hmin), 2)         # note: numpy arrays are [y,x] whereas default python is [y][x]
        line+='{:.2f}'.format( arr[y,x] )                                       #format string to show 2 decimals
        if (x < adim[1]-1):
            line+=' '
    line+='\n'
    file.write(line)
 
## file end
   
file.close()

print ('### CONVERSION DONE ###')

 

Cheers, X3KJ

 

 

  • Thanks 1

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×