cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Choose Language Hide Translation Bar
Craige_Hales
Super User
Load 16-bit Grayscale Tiff via Python

16-bit TIFF image import  is a wish for JMP to be able to load grayscale data with more than 256 shades of gray. I suggested Python might be a reasonable way to do it before trying it. The first test file I created with Gimp produced an odd error message in Python, which I tracked down to mean "the 16 bit gray scale data can't be imported by Python unless there is no other channel (like an alpha channel, or other layer)." The default in Gimp has an alpha channel, and re-exporting without it made a 16-bit grayscale file Python can load. The following is an 8-bit PNG screen capture. The first image is a bit of lava from Gimp, which was saved as 16-bit gray scale.

 

The delta noise image is multiplied by 30 to make the noise visible. It is nearly uniform gray on my display at < 10X. The truncation error is about 1/255 of the gray scale range.The delta noise image is multiplied by 30 to make the noise visible. It is nearly uniform gray on my display at < 10X. The truncation error is about 1/255 of the gray scale range.

 

The two orange pictures look identical. The conversion to the spectral colors on the bottom image was done using 16-bit data, so there are probably some differences. The faintly textured blue/gray/red image represents the difference between the data that made the two orange images. If your camera can actually produce 10- or 12- or maybe even 14- bit data, that extra precision may be important. Or, the dynamic range may be important.

 

Python Init();

path = Convert File Path(
    Save Text File( "$temp/deleteme.tiff", // the 2channel file will fail - see link in message
        Load Text File( "16bitgray1channel.tif", blob() ) // pic is part of the project, move to $temp
    ),
    "windows"
);

// first import it using built-in image that truncates the bit depth
truncated = Color To RGB( New Image( path ) << getpixels )[1]; // use the red channel

// stretch truncated image bit depth 0 to 1
r = Range( truncated );//[0.00784 0.803]
min = r[1];
max = r[2];
truncated = (truncated - min) / (max - min); // 0 to 1
timage = New Image( Heat Color( 1 - truncated, "spectral" ) );

// now import with Python PIL to preserve the 16-bit depth
rc = Python Execute( {path}, {im}, "\[
import numpy as np
import PIL
from PIL import Image
try:
    im = np.array(Image.open(path))
except Exception as e:
    print("make sure there is only one channel (no alpha for example) see https://github.com/python-pillow/Pillow/issues/1888",e)
]\" );
If( rc, Throw( "python code failed" ) );

// stretch full image bit depth 0 to 1
r = Range( im ); //[530 52698]
min = r[1];
max = r[2];
full = (im - min) / (max - min);
fimage = New Image( Heat Color( 1 - full, "spectral" ) );

// diff and magnify the difference
magnify = 30;
delta = (full - truncated) * magnify; // small negative and positive diffs, scaled up to be visible
delta = delta + .5; // center
dimage = New Image( Heat Color( delta ) );

New Window( "compare", Lineup Box( N Col( 2 ), 
textbox("original\!ngray\!nscale"),New Image( path ),
Text Box( "truncated\!nheatcolor\!nspectral" ), timage, 
Text Box( evalinsert("delta\!ntimes ^magnify^\!nblue\!nto gray\!nto red\!n\!nfullres -\!ntruncated") ), 
dimage, Text Box( "full res\!nheatcolor\!nspectral" ), fimage, ) );

A project file (JMP 16) is attached with two TIFs; one fails because of the extra channel of alpha data. Remove the .zip for JMP 16 or use your zip tools if you are using older JMP.

Thanks @RJ_Bailey !

Last Modified: Mar 17, 2022 6:28 PM