I'm trying to get a real-world heightmap data for my game. I'm grabbing an image in GeoTIFF format from here and then converting it to png and cleaning up some errors. This is an example of a fjord heightmap after cleanup: You can see that it's mostly white and I would like to use the full range form black to white. I tried normalizing it in GIMP with Strech Contrast with Non-linear Components checked (it gave the best result), but it creates this ramping effect, which is very visible when used as terrain height data in Unity: I tried using a blur filter on it, but I have to blur it a lot for the "steps" to disappear. Is there any better way to normalize an image without creating ramping?
In your initial image you have 38 values. All the color adjustments are going to stretch this range between 256 values. But all the pixels with a given value are going to be mapped to the same new value, so you have 38 values spread in the 0..255 range, which means that assuming a strictly linear stretch, pixels with near values are now separated by 7 values, which is a lot more visible, especially in the dark tones. You can also see this in the histogram, which looks like a hair comb.
One possible cure is to use "spread noise". This sort of randomly move pixels, and the nice linear ramp (which translates into a flight of steps when you stretch the values) is a bit less smooth on entry, so the flight of steps on output is a lot more irregular and less visible.
However in your case you have to use a rather large radius for the spread noise and that makes the output rather grainy, but you can apply some blur to mitigate this (and much less blur that what you would need to remove the steps):
7px of spread+2px of blur:
v.s. 7px of blur: