In a script, I am using IJ.openImage() to open a two-channel 16-bit signed single-slice TIF file that has been encoded with the two’s complement.
The LOCI bio-formats dialog opens, and all that is needed to do is push ‘OK’.
How can one prevent the dialog from opening in the first place?
Opening the file manually using the bio-formats API is possible. Here is one attempt at it, that works, but surely it could be simpler?
from loci.formats import ChannelSeparator
#from java.nio import ByteBuffer, ByteOrder
from fiji.scripting import Weaver
from ij.process import ShortProcessor
from ij import ImagePlus, ImageStack, CompositeImage
from jarray import zeros
# *** EDIT HERE ***
filepath = ...
# An embedded piece of java code to parse the raw bytes into signed 16-bit pixels, decoded with two's complement.
# If the two's complement wasn't needed, there would be no need for the Weaver: ByteBuffer would suffice.
arrays = [None, None]
asShorts = Weaver.inline(
"""
final byte[] bytes = (byte[])arrays.get(0);
final short[] shorts = (short[])arrays.get(1);
for (int i=0, k=0; i<shorts.length; i+=1, k+=2) {
// In little endian and with two's complement
shorts[i] = (short) (~(bytes[k+1]&0xff | (bytes[k]&0xff << 8)) + 1);
}
return null;
""", {"arrays": arrays})
# A LOCI bio-formats decoder for the TIFF file
reader = ChannelSeparator()
reader.setGroupFiles(False)
reader.setId(filepath)
width = reader.getSizeX()
height = reader.getSizeY()
# Pre-allocated array for reuse in reading each image plane
bytes = zeros(width * height * 2, 'b')
stack = ImageStack(width, height)
# Read each of the two image planes, one for each channel
for i in xrange(reader.getImageCount()):
reader.openBytes(i, bytes)
shorts = zeros(width * height, 'h') # 'h' is for short (16-bit)
# Should work, but doesn't do the two's complement, which is needed because these TIFF files are signed 16-bit.
#ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts)
# So instead we do it manually with the Weaver:
arrays[0] = bytes
arrays[1] = shorts
asShorts.call()
stack.addSlice(ShortProcessor(reader.getSizeX(), reader.getSizeY(), shorts, None))
# Show the stack as an ImageJ composite image
imp = ImagePlus("all", stack)
imp.setDimensions(2, stack.getSize() / 2, 1) # channels, slices and time frames
comp = CompositeImage(imp, CompositeImage.COMPOSITE)
comp.show()
Surely there is a simpler way?