16-bit Grayscale for Heightmaps

I don't understand the jME fondness for the non-standard that is RAW file format, but I offer for your consideration a more capable persistance system for height maps than what is in AbstractHeightMap.save() and RawHeightMap.load().


  - AbstractHeightMap.save() truncates data to 8 bits, which is inadequate resolution for typical height map requirements.

  - Height map persistence support in jME is very incomplete right now.  It seems that people must usually not persist height maps, or use custom tools or apps to save and restore them, since RawHeightMap.load() is incompatible with files generated by AbstractHeightMap.save(), and I know of no other method in jME to save a height map (please do correct me if it is there and I am somehow missing it).  Test case which shows the incompatibility of RawHeightMap.load() and AbstractheightMap.save():

import java.io.IOException;

import com.jmex.terrain.util.RawHeightMap;

import com.jmex.terrain.util.MidPointHeightMap;


public class RawStoreLoad {

    static public void main(String[] sa) throws IOException {

        MidPointHeightMap mphm = new MidPointHeightMap(256, 1.5f);


        RawHeightMap rhm = new RawHeightMap("/tmp/8bit.raw", 256);


        // RawHeightMap.load() swallows up the meaningful exception at line

        // 213, one aspect of exception-handling deficiencies prevalent in

        // the jME code base.

        // Fix that to see that the problem is with the read commands.



   RawHeightMap does support 16 bit data, if you do the work to save such a file in the required format.

  - As RAW file format has no support in the J2SE, it lacks performance enhancements of the java.awt.image system.

  - As there is no consensus about how raw data should be visualized, there is no opportunity for third party graphics programs to allow for visual editing in a consistent way.

[size=16px]Rejected Improvement:  lanmower's CompressedMapData[/size]

  - Unlike AbstractHeightMap.save(), it does store and load 16-bit data.

  - Really fast from Java, since it's using Java native serialization.

  - Portability is far worse than the RAW files.  Besides versioning issues, only Java programs can read these serialized files.

[size=16px]Solution: 16-bit Graymap files[/size]

  - File type is directly supported by J2SE.

  - More than twice as fast as 16 bit RAW (also faster than 8 bit RAW!).  3 x as slow as CompressedMapData though (see benchmarks below).

  - Standard file format, so you can edit it with graphics programs with 16-bit channel capability.  (I use Krita, but I read that there are 16-bit-capable Windows programs available too).


Tested a 256x256 vertex file.

I have not made any attempt to optimize my Grayscale routines yet (for example, by reading or writing in blocks or arrays).

I modified AbstractHeightMap to store 16-bit values, since otherwise it could only save 8-bit values.  Specs for the unmodified 8-bit storage and loading of RAW files is correspondingly crappy.

File format file size save time load time
16-bit RAW 131072 352 ms *
CompressedMapData 131182 52 ms 36 ms
16-bit Grayscale 115384 160 ms 156

* Did not test this because, just as the off-the-shelf RawHeightMap class can't read off-the-shelf AbstractHeightMap 8-bit files; it also can't read AbstractHeightMap files which have been modified to write 16-bits.  I could fix these problems if I thought the RAW system was worth fixing.

My 16-bit grayscale system is working great for my dynamic terrain system, and my unit tests prove the fidelity of persistence.

I am currently working on utility methods to extract requested areas within a 16-bit Grayscale file to make an 8-bit Grayscale "delta" file to work with, then merge back into the 16-bit file.  The primary motivation for this is that there is so much of a range of pixel values in a 16-bit file that it is hard to see fine graduations in visual editors.  In addition, this allows you to use 8-bit editors like Gimp.  The key to using the this utility is that you must specify an area within the 16-bit file which does not have height variance exceeding 8-bit capacity (the program will tell you if you need to reduce the area).  The merge-back method applies the offset which automatically got written as part of the delta file name.
UPDATE:  Done.  I had to make the delta files 16-bit grayscale too, because I found that 256 bits are just useless for real height-mapping ajustments.  However, with a 16-bit editor this makes for great WYSIWYG editing.  User specifies the area they want to edit (which may span as many terrain blocks/tiles as desired) and the desired height resolution (with good, high-res default).

If there is not demand for these features here, I will keep the system to myself.


holy crap, compressedmapdata was fast!

could you bench the new one for me? it uses jme's savable format.