The ImageJ software (https://imagej.nih.gov/ij) is a widely-used image viewing and processing software, particularly popular in microscopy and life sciences. It supports the TIFF image format (and many others). It reads TIFF files perfectly, however it can sometimes write them in a peculiar way, meaning that when other softwares try to read TIFF files written by ImageJ, mistakes can be made.
One goal of the ijtiff R package is to correctly import TIFF files that were saved from ImageJ.
It is common to use TIFFTAG_SAMPLESPERPIXEL to record the number of channels in a TIFF image, however ImageJ sometimes leaves TIFFTAG_SAMPLESPERPIXEL with a value of 1 and instead encodes the number of channels in TIFFTAG_IMAGEDESCRIPTION which might look something like
"ImageJ=1.51 images=16 channels=2 slices=8".
A conventional TIFF reader would miss this channel information (because it is in an unusual place). ijtiff does not miss it. We’ll see an example below.
Note: These peculiar ImageJ-written TIFF files are still bona fide TIFF files according to the TIFF specification. They just break with common conventions of encoding channel information.
path_2ch_ij is the path to a TIFF file which was made in ImageJ from the R logo dancing banana GIF used in the README of Jeroen Ooms’ magick package. The TIFF is a time-stack containing only the red and green channels of the first, third and fifth frames of the original GIF. Here’s the full gif:
Here are the red and green channels of the first, third and fifth frames of the TIFF:
tiff packageWhen we import it with the original tiff package:
img <- tiff::readTIFF(path_2ch_ij, all = TRUE)
#> Warning in tiff::readTIFF(path_2ch_ij, all = TRUE): TIFFReadDirectory:
#> Unknown field with tag 50838 (0xc696) encountered
#> Warning in tiff::readTIFF(path_2ch_ij, all = TRUE): TIFFReadDirectory:
#> Unknown field with tag 50839 (0xc697) encountered
str(img) # 10 images
#> List of 6
#> $ : num [1:155, 1:200] 1 1 1 1 1 1 1 1 1 1 ...
#> $ : num [1:155, 1:200] 1 1 1 1 1 1 1 1 1 1 ...
#> $ : num [1:155, 1:200] 1 1 1 1 1 1 1 1 1 1 ...
#> $ : num [1:155, 1:200] 1 1 1 1 1 1 1 1 1 1 ...
#> $ : num [1:155, 1:200] 1 1 1 1 1 1 1 1 1 1 ...
#> $ : num [1:155, 1:200] 1 1 1 1 1 1 1 1 1 1 ...
img[[1]][100:110, 50:60] # print a section of the first image in the series
#> [,1] [,2] [,3] [,4] [,5] [,6]
#> [1,] 0.6627451 0.6627451 0.6549020 0.6627451 0.7058824 0.9215686
#> [2,] 0.6745098 0.6431373 0.6745098 0.6431373 0.6431373 0.6745098
#> [3,] 0.6549020 0.6627451 0.6431373 0.6627451 0.6627451 0.6431373
#> [4,] 0.6431373 0.6431373 0.6627451 0.6431373 0.6627451 0.6431373
#> [5,] 0.6745098 0.6745098 0.6431373 0.6627451 0.6431373 0.6627451
#> [6,] 0.6745098 0.6431373 0.6431373 0.6431373 0.6549020 0.6549020
#> [7,] 0.6549020 0.6549020 0.6431373 0.6549020 0.6549020 0.6431373
#> [8,] 0.6431373 0.6549020 0.6431373 0.6549020 0.6431373 0.6431373
#> [9,] 0.6431373 0.6745098 0.6431373 0.6431373 0.6431373 0.6549020
#> [10,] 0.6431373 0.6549020 0.6431373 0.6549020 0.6431373 0.6431373
#> [11,] 0.6431373 0.6431373 0.6431373 0.6431373 0.6431373 0.6431373
#> [,7] [,8] [,9] [,10] [,11]
#> [1,] 1.0000000 1.0000000 1.0000000 1.0000000 1.0000000
#> [2,] 0.8705882 1.0000000 1.0000000 1.0000000 1.0000000
#> [3,] 0.6627451 0.7803922 1.0000000 1.0000000 1.0000000
#> [4,] 0.6627451 0.6431373 0.7058824 0.9058824 1.0000000
#> [5,] 0.6431373 0.6627451 0.6431373 0.6431373 0.8039216
#> [6,] 0.6549020 0.6431373 0.6431373 0.6549020 0.6431373
#> [7,] 0.6431373 0.6549020 0.6431373 0.6431373 0.6431373
#> [8,] 0.6549020 0.6431373 0.6549020 0.6431373 0.6431373
#> [9,] 0.6431373 0.6431373 0.6431373 0.6431373 0.6431373
#> [10,] 0.6431373 0.6431373 0.6431373 0.6431373 0.6431373
#> [11,] 0.6549020 0.6431373 0.6431373 0.6431373 0.6431373R user.ijtiff packageWhen we import the same image with the ijtiff package:
img <- ijtiff::read_tif(path_2ch_ij)
#> Reading Rlogo-banana-red_green.tif: an 8-bit, 155x200 pixel
#> image of unsigned integer type. Reading 2 channels and 3
#> frames . . .
#> Done.
dim(img) # 2 channels, 3 frames
#> [1] 155 200 2 3
img[100:110, 50:60, 1, 1] # print a section of the first channel, first frame
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
#> [1,] 169 169 167 169 180 235 255 255 255 255 255
#> [2,] 172 164 172 164 164 172 222 255 255 255 255
#> [3,] 167 169 164 169 169 164 169 199 255 255 255
#> [4,] 164 164 169 164 169 164 169 164 180 231 255
#> [5,] 172 172 164 169 164 169 164 169 164 164 205
#> [6,] 172 164 164 164 167 167 167 164 164 167 164
#> [7,] 167 167 164 167 167 164 164 167 164 164 164
#> [8,] 164 167 164 167 164 164 167 164 167 164 164
#> [9,] 164 172 164 164 164 167 164 164 164 164 164
#> [10,] 164 167 164 167 164 164 164 164 164 164 164
#> [11,] 164 164 164 164 164 164 167 164 164 164 164The original tiff package reads several types of TIFFs correctly, including many that are saved from ImageJ. This is just an example of a TIFF type that it doesn’t perform so well with.
Base ImageJ (similar to the tiff R package) does not properly open some perfectly good TIFF files1 (including some TIFF files written by the tiff and ijtiff R packages). Instead it often gives you the error message: imagej can only open 8 and 16 bit/channel images. These images in fact can be opened in ImageJ using the wonderful BioFormats plugin. See https://imagej.net/Bio-Formats.
I think native ImageJ only likes 1, 3 and 4-channel images and complains about the rest, but I’m not sure about this.↩