So, for various reasons (i.e. blockproc) I am trying to create a BigTIFF ImageAdapter class that also writes multiple images to the same file. However, these images are not all the same size – they're lower-resolution versions of the same image. Essentially, I'm trying to create a multi-resolution BigTIFF file, but it has to be done through an ImageAdapter/blockproc because the original image is simply too big.
The problem is that when I call TIFF's writeDirectory() function in my ImageAdapter, it seems to wipe out all information in the TIFF object stored in the class, and calls to TIFF's setTag() no longer work on the object (although getTag() does return the correct answer immediately after, but doesn't persist). This may be a simple case of me not understanding how to work with handle-type classes in Matlab, so please let me know if I'm doing something incorrectly:
classdef PagedBigTiffWriter < ImageAdapter properties(GetAccess = public, SetAccess = private) Filename; TiffObject; TileLength; TileWidth; end methods function obj = PagedBigTiffWriter(fname, imageLength, imageWidth, tileLength,... tileWidth, bitsPerSample, compression, sampleFormat) if(mod(tileLength,16)~=0 || mod(tileWidth,16)~=0) error('bigTiffWriter:invalidTileSize',... 'Tile size must be a multiple of 16'); end if strcmpi(sampleFormat,'IEEE floating point') sFormat = Tiff.SampleFormat.IEEEFP; elseif strcmpi(sampleFormat, 'integer') sFormat = Tiff.SampleFormat.Int; else sFormat = Tiff.SampleFormat.UInt; end obj.Filename = fname; obj.ImageSize = [imageLength, imageWidth, 1]; obj.TileLength = tileLength; obj.TileWidth = tileWidth; % Create the Tiff object.
obj.TiffObject = Tiff(obj.Filename, 'w8'); % Setup the tiff file properties
% See "Exporting Image Data and Metadata to TIFF files"
% https://www.mathworks.com/help/matlab/import_export/exporting-to-images.html
%
obj.TiffObject.setTag('ImageLength', obj.ImageSize(1)); obj.TiffObject.setTag('ImageWidth', obj.ImageSize(2)); obj.TiffObject.setTag('TileLength', obj.TileLength); obj.TiffObject.setTag('TileWidth', obj.TileWidth); obj.TiffObject.setTag('Photometric', Tiff.Photometric.MinIsBlack); obj.TiffObject.setTag('BitsPerSample', bitsPerSample); obj.TiffObject.setTag('SampleFormat', sFormat); obj.TiffObject.setTag('SamplesPerPixel', 1); obj.TiffObject.setTag('PlanarConfiguration', Tiff.PlanarConfiguration.Chunky); obj.TiffObject.setTag('Compression', Tiff.Compression.(compression)); end function [] = changePage(obj, imageSize, tileSize) % increments to next directory, so next time we call blockproc
% it will write to the next page
obj.TiffObject.writeDirectory(); % now write out new metadata for the new page
obj.ImageSize = [imageSize(1), imageSize(2), 1]; %length first
obj.TileLength = tileSize(1); obj.TileWidth = tileSize(2); obj.TiffObject.setTag('ImageLength', obj.ImageSize(1)); % <- these do nothing, and obj.TiffObj is essentially blank now
obj.TiffObject.setTag('ImageWidth', obj.ImageSize(2)); obj.TiffObject.setTag('TileLength', obj.TileLength); obj.TiffObject.setTag('TileWidth', obj.TileWidth); % probably need rest of metadata from first page?
%obj.TiffObject.rewriteDirectory(); %not necessary, as haven't
%written meta to this directory before?
end function [] = writeRegion(obj, region_start, region_data) % Map region_start to a tile number.
tile_number = obj.TiffObject.computeTile(region_start); % If region_data is greater than tile size, this function
% warns, else it will silently pads with 0s.
obj.TiffObject.writeEncodedTile(tile_number, region_data); end function data = readRegion(~,~,~) %#ok<STOUT>
% Not implemented.
error('bigTiffWriter:noReadSupport',... 'Read support is not implemented.'); end function close(obj) % Close the tiff file
obj.TiffObject.close(); end end end
In changePage(), the call to obj.TiffObject.writeDirectory() successfully changes the directory, but all that's left in obj.TiffObject is the file name and mode. The indicated calls to setTag do not change obj.TiffObject, (although calling getTag() returns the correct answer, printing out obj.TiffObject shows nothing). Why? Should I be doing this differently? I've heard of subdirectories in TIFF, which may actually be more appropriate for my multi-resolution files, but I couldn't figure out how to get that working. And I tried setting changePage to return obj, but that didn't work either.
I know from reading around that working with TIFFs through Matlab can be a pain, and I have seen the various file exchange options for TIFF stacks, but as far as I know those do not work in this particular use case. Even if they did, I would prefer to avoid using functions not provided with Matlab.
Best Answer