Saving greater than 8 bit images

I’m trying to save out Array{ColorTypes.Gray{Float16},2} as a tiff image. I’m just getting black images in the output file. The package being used is imagemagick. Thank you for your time.

Please provide more context; you are using which save function?

Not exactly sure that I know what you’re experiencing, but I suspect this is an interesting combination of limitations of the ImageMagick C library and a bug in FixedPointNumbers fixed here.

ImageMagick requires that floating-point values be between 0 and 1, so if your values aren’t in that range they will be clamped. Moreover, as far as I can tell (and please correct me if I’m wrong), ImageMagick quantizes your inputs and does not provide any mechanism for knowing the original pixel type, so that when you load the image again you can’t guarantee that the original pixel type is recreated. For these reasons, ImageMagick.jl defaults to N0f8 precision for anything that’s not already “integer” (Normed) datatypes. If you want to control this yourself, consider save(filename, n0f16.(img)) or save(filename, img; mapi=x->N0f16(clamp01nan(x))) so that you’re in charge of the precision yourself.

Now, it turns out there was also a bug in FixedPointNumbers. The problem arises because the computations here overflow:

julia> Float16(1.0)*0xffff   # the 0xffff comes from quantizing to 16-bit integers
Inf16

julia> realmax(Float16)
Float16(6.55e4)

julia> Float16(0xffff)
Inf16

The fix was just to convert to Float32 before converting to N0f16.

If you don’t like the idea of the ImageMagick C library quantizing your inputs and want to exactly preserve the values you supply, a good format choice might be NRRD. Julia’s NRRD package will load them as plain Float16, but you can always do b = colorview(Gray, load("test.nrrd")) to get the Gray back. (And it may be fixable to load them as Gray, feel free to open an issue.)

1 Like