def parse_TIFF_IFDs(filepath): """ Returns a generator of dictionaries of tags for each IFD in the TIFF file, as defined by the 'parseIFD' function above. """ ra = RandomAccessFile(filepath, 'r') try: # TIFF file format can have metadata at the end after the images, so the above approach can fail # TIFF file header is 8-bytes long: # (See: http://paulbourke.net/dataformats/tiff/tiff_summary.pdf ) # # Bytes 1 and 2: identifier. Either the value 4949h (II) or 4D4Dh (MM), # meaning little-endian and big-endian, respectively. # All data encountered past the first two bytes in the file obey # the byte-ordering scheme indicated by the identifier field. b1, b2 = ra.read(), ra.read() # as two java int, each one byte sized bigEndian = chr(b1) == 'M' parseNextInt = parseNextIntBigEndian if bigEndian else parseNextIntLittleEndian # Bytes 3 and 4: Version: Always 42 ra.skipBytes(2) # Bytes 5,6,7,8: IFDOffset: offset to first image file directory (IFD), the metadata entry for the first image. nextIFDoffset = parseNextInt(ra, 4) # offset to first IFD while nextIFDoffset != 0: ra.seek(nextIFDoffset) tags, nextIFDoffset = parseIFD(ra, parseNextInt) tags["bigEndian"] = bigEndian yield tags finally: ra.close()
def readBinaryMaskImg(filepath, width, height, depth, header_size): ra = RandomAccessFile(filepath, 'r') try: ra.skipBytes(header_size) bytes = zeros(width * height * depth, 'b') ra.read(bytes) return ArrayImgs.unsignedBytes(bytes, [width, height, depth]) finally: ra.close()
def read2DImageROI(path, dimensions, interval, pixelType=UnsignedShortType, header=0, byte_order=ByteOrder.LITTLE_ENDIAN): """ Read a region of interest (the interval) of an image in a file. Assumes the image is written with the first dimension moving slowest. path: the file path to the image file. dimensions: a sequence of integer values e.g. [512, 512, 512] interval: two sequences of integer values defining the min and max coordinates, e.g. [[20, 0], [400, 550]] pixeltype: e.g. UnsignedShortType, FloatType header: defaults to zero, the number of bytes between the start of the file and the start of the image data. Supports only these types: UnsignedByteType, UnsignedShortType, FloatType. Returns an ArrayImg of the given type. """ ra = RandomAccessFile(path, 'r') try: width, height = dimensions minX, minY = interval[0] maxX, maxY = interval[1] roi_width, roi_height = maxX - minX + 1, maxY - minY + 1 tailX = width - roi_width - minX #print minX, minY #print maxX, maxY #print roi_width, roi_height size = roi_width * roi_height n_bytes_per_pixel = pixelType().getBitsPerPixel() / 8 #print n_bytes_per_pixel bytes = zeros(size * n_bytes_per_pixel, 'b') # Read only the 2D ROI ra.seek(header + (minY * width + minX) * n_bytes_per_pixel) for h in xrange(roi_height): ra.readFully(bytes, h * roi_width * n_bytes_per_pixel, roi_width * n_bytes_per_pixel) ra.skipBytes((tailX + minX) * n_bytes_per_pixel) # Make an image roiDims = [roi_width, roi_height] if UnsignedByteType == pixelType: return ArrayImgs.unsignedBytes(bytes, roiDims) if UnsignedShortType == pixelType: shorts = zeros(size, 'h') ByteBuffer.wrap(bytes).order(byte_order).asShortBuffer().get(shorts) return ArrayImgs.shorts(shorts, roiDims) if FloatType == pixelType: floats = zeros(size, 'f') ByteBuffer.wrap(bytes).order(byte_order).asFloatBuffer().get(floats) return ArrayImgs.floats(floats, roiDims) finally: ra.close()
def readUnsignedBytes(path, dimensions, header=0): """ Read a file as an ArrayImg of UnsignedShortType """ ra = RandomAccessFile(path, 'r') try: if header < 0: # Interpret from the end: useful for files with variable header lengths # such as some types of uncompressed TIFF formats header = ra.length() + header ra.skipBytes(header) bytes = zeros(reduce(operator.mul, dimensions), 'b') ra.read(bytes) return ArrayImgs.unsignedBytes(bytes, dimensions) finally: ra.close()
def readFloats(path, dimensions, header=0, byte_order=ByteOrder.LITTLE_ENDIAN): """ Read a file as an ArrayImg of FloatType """ size = reduce(operator.mul, dimensions) ra = RandomAccessFile(path, 'r') try: if header < 0: # Interpret from the end: useful for files with variable header lengths # such as some types of uncompressed TIFF formats header = ra.length() + header ra.skipBytes(header) bytes = zeros(size * 4, 'b') ra.read(bytes) floats = zeros(size, 'f') ByteBuffer.wrap(bytes).order(byte_order).asFloatBuffer().get(floats) return ArrayImgs.floats(floats, dimensions) finally: ra.close()
def readUnsignedShorts(path, dimensions, header=0, return_array=False, byte_order=ByteOrder.LITTLE_ENDIAN): """ Read a file as an ArrayImg of UnsignedShortType """ size = reduce(operator.mul, dimensions) ra = RandomAccessFile(path, 'r') try: if header < 0: # Interpret from the end: useful for files with variable header lengths # such as some types of uncompressed TIFF formats header = ra.length() + header ra.skipBytes(header) bytes = zeros(size * 2, 'b') ra.read(bytes) shorts = zeros(size, 'h') # h is for short ByteBuffer.wrap(bytes).order(byte_order).asShortBuffer().get(shorts) return shorts if return_array else ArrayImgs.unsignedShorts(shorts, dimensions) finally: ra.close()
if filepath.endswith("tif"): try: ra = RandomAccessFile(filepath, 'r') # TIFF file format can have metadata at the end after the images, so the above approach can fail # TIFF file header is 8-bytes long: # (See: http://paulbourke.net/dataformats/tiff/tiff_summary.pdf ) # # Bytes 1 and 2: identifier. Either the value 4949h (II) or 4D4Dh (MM), # meaning little-ending and big-endian, respectively. # All data encountered past the first two bytes in the file obey # the byte-ordering scheme indicated by the identifier field. b1, b2 = ra.read(), ra.read() # as two java int, each one byte sized bigEndian = chr(b1) == 'M' parseNextInt = parseNextIntBigEndian if bigEndian else parseNextIntLittleEndian # Bytes 3 and 4: Version: Always 42 ra.skipBytes(2) # Bytes 5,6,7,8: IFDOffset: offset to first image file directory (IFD), the metadata entry for the first image. firstIFDoffset = parseNextInt(ra, 4) ra.skipBytes(firstIFDoffset - ra.getFilePointer() ) # minus the current position: all offsets are absolute firstTags, _ = parseIFD(ra, parseNextInt) # Correct headerSize for TIFF files (and then assuming images are contiguous and in order, # which they don't have to be either in TIFF) headerSize = firstTags["offset"] # Sanity check: if width != firstTags["width"] or height != firstTags[ "height"] or bitDepth != firstTags["samples_per_pixel"] * 8: print "TIFF header disagrees with ChannelSeparator's parsing of metadata." finally: ra.close() """