Page 1 of 1

converting from floating point to integer

Posted: 2017-09-18T16:07:20-07:00
by user001
I have some 64-bit IEEEFP tiff files. I can convert them to 8-bit unsigned integer (0-255) tiffs using Matlab, but I cannot seem to accomplish it using ImageMagick.

Code: Select all

$ identify <file>
TIFF 144x149 144x149+0+0 64-bit Grayscale Gray 173050B 0.000u 0:00.000

Code: Select all

$ magick <file> -depth 8 miff:- | identify -
-=>/var/folders/z_/my_04rd11_j2drwtjs0j88280000gp/T/magick-6527ZiXJaT0vbV12 MIFF 144x149 144x149+0+0 8-bit Grayscale Gray 21886B 0.010u 0:00.009
identify: unexpected end-of-file '/var/folders/z_/my_04rd11_j2drwtjs0j88280000gp/T/magick-6527ZiXJaT0vbV12': No such file or directory @ error/miff.c/ReadMIFFImage/1615.
Converting to 16-bit "works":

Code: Select all

$ magick F00_C0_T0058* -depth 16 miff:- | identify -
-=>/var/folders/z_/my_04rd11_j2drwtjs0j88280000gp/T/magick-6534jyo532xQR5DS MIFF 144x149 144x149+0+0 16-bit Grayscale Gray 43358B 0.000u 0:00.000
However, the relative values in the 16-bit output have changed since adjusting levels by a percentage gives completely different output on the 64-bit input and 16-bit output:

Code: Select all

$ magick <file> -level 1,20% miff:- | display -			   # gives good contrast
$ magick <file> -depth 16 -level 1,20% miff:- | display -	   # image nearly saturated (white)
I also tried changing the `storage-type` to short, integer, or quantum, but these did not help.

I would like to convert the 64-bit IEEEFP image to unsigned 8-bit while preserving the image histogram within the precision allowed by depth reduction. Can this be done with ImageMagick?

Code: Select all

$ magick -version
Version: ImageMagick 7.0.7-1 Q16 x86_64 2017-09-15 http://www.imagemagick.org
Copyright: © 1999-2017 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules 
Delegates (built-in): bzlib fontconfig freetype jng jpeg ltdl lzma png tiff x xml zlib

Re: converting from floating point to integer

Posted: 2017-09-18T16:18:37-07:00
by fmw42
Can you post an example Tiff file? You can upload to some free hosting service that will not change your format (or zip it). Then put the URL here.

Also what platform are you using?

Re: converting from floating point to integer

Posted: 2017-09-18T16:22:40-07:00
by fmw42
P.S. What does identify -verbose tell you about the range of values in the image. Your 64-bit image is probably outside the range of Q16 (0-65525).

Have you tried

Code: Select all

convert image.tiff -auto-level -depth 8 newimage.tif

Re: converting from floating point to integer

Posted: 2017-09-18T16:51:16-07:00
by user001
Here is an example image: http://s000.tinyupload.com/index.php?fi ... 5170768467
Unzip to recover the 64-bit tiff. I am using mac osx and debian v9. I could not get `identify -verbose` to output a histogram (just the summary statistics). Your `auto-level` command seems to do the job, thanks.

Re: converting from floating point to integer

Posted: 2017-09-18T18:30:06-07:00
by fmw42
Using

Code: Select all

magick identify -verbose a.tif
Image: a.tif
  Format: TIFF (Tagged Image File Format)
  Mime type: image/tiff
  Class: DirectClass
  Geometry: 500x501+0+0
  Units: PixelsPerInch
  Type: Grayscale
  Endianess: LSB
  Colorspace: Gray
  Depth: 64/16-bit
  Channel depth:
    Gray: 16-bit
  Channel statistics:
    Pixels: 250500
    Gray:
      min: 0 (0)
      max: 65535 (1)
      mean: 30571.3 (0.466488)
Shows that your file a 64-bit image containing data that spans only 16-bits (0 to 65535).

Using IM 7.0.7.2 Q16 Mac OSX Sierra, seems to work for -depth 16 and -depth 8.

Code: Select all

magick a.tif -depth 16 b.tif
magick a.tif -depth 8 c.tif 
Both seems to view the same for me in Mac Preview. IM compare shows insignificant difference (about 0.1%)

Code: Select all

magick compare -metric rmse a.tif b.tif null:
0.288847 (4.40752e-06)

magick compare -metric rmse a.tif c.tif null:
74.1683 (0.00113174)
 
magick compare -metric rmse b.tif c.tif null:
74.1667 (0.00113171)

Re: converting from floating point to integer

Posted: 2017-09-18T18:45:55-07:00
by user001
Hmm, I wonder why it is read as 16-bit. It began as a double-precision matrix in matlab (originally acquired with a 16-bit ADC but then convolved with a Gaussian, making it no longer 16-bit) and I saved it using that software's libtiff API with the BitsPerSample tag set to 64).

Could it be because IM was compiled with quantum depth of Q16?

Do you know why the maximum is read as zero when I request normalized values from 0 to 1?

Code: Select all

$ magick a.tif -format "%[fx:min] %[fx:max] %[fx:mean]" info:
0 0 0.466488

$ magick a.tif -format "%[min] %[max] %[mean]" info:
0 65535 30571.3
`%[fx:max]` should be returning 1.

PS: Thanks for pointing out the `magick compare -metric rmse` functionality. I wasn't aware of it.

Re: converting from floating point to integer

Posted: 2017-09-18T19:01:55-07:00
by fmw42
It should be %[fx:maxima] and %[fx:minima].

HDRI supports values larger than Q16 range.

Re: converting from floating point to integer

Posted: 2017-09-18T19:12:37-07:00
by user001
I see, maxima/minima works for both (+/- fx) while the non-fx version also accepts the abbreviated forms.

Supposing that I have done some manipulation on the image myself, is it possible to reduce the bit depth afterwards without altering the image?

For instance

Code: Select all

magick a.tif -fx "(u-0.1)/0.9" -level 100,65000 miff:-
In my particular case, I have many such images and I store the global min/max value (hypothetically min=0.1, and max-min=0.9 using normalized intensities), and then normalize each by subtracting the min and dividing by the range. I have also stored the histogram and may wish to clip the intensity distribution (e.g., 100, 65000). This works fine, but if I finally try to write 8-bit or 16-bit output (using `-depth N`), the output looks quite different. Compare:

Code: Select all

$ magick a.tif -fx "(u-0.1)/0.9" -level 100,65000 miff:- | display -
$ magick a.tif -fx "(u-0.1)/0.9" -level 100,65000 -depth 8 miff:- | display -
Do you know how this can be accomplished? I am essentially performing my own auto-level but with the min/max from a collection of images rather than the min/max for a single image.

Re: converting from floating point to integer

Posted: 2017-09-18T19:14:23-07:00
by user001
Oh, it actually must be a bug with `miff:` since `-depth 8 PNG8:` works just fine.

Re: converting from floating point to integer

Posted: 2017-09-18T19:26:28-07:00
by fmw42
MIFF is not automatically floating point supported. You need to add some defines. To specify a single-precision floating-point format, use -define quantum:format=floating-point. Set the depth to 64 for a double-precision floating-point format. This is the same for TIFF as well in Imagemagick when saving to those formats.

A good format for HDRI supporting fractional values and negative values is PFM or IM's MPC.

Re: converting from floating point to integer

Posted: 2017-09-18T21:22:21-07:00
by user001
Thanks, I'll keep pfm and mpc in mind for future work with floating point data.