function img = imtile(images,borderheight)
%montage = imtile(images)
%  This is a hacked version of an image tiling function I'm working on.
%  It's not too pretty at the moment as I wanted some quick changes for
%  this application that will require a little bit of redesign work to do
%  cleanly.

% number of tiles
TR = size(images,1);
TC = size(images,2);
assert(TC==1, 'this version has been customized and simplified for vertical image stacks only');

% size of each tile
tileWidths = zeros(1,TC);
tileHeights = zeros(1,TR);
for tr=1:TR
  for tc=1:TC
    tileWidths(tc) = max(tileWidths(tc), size(getimg(tr,tc), 2));
    tileHeights(tr) = max(tileHeights(tr), size(getimg(tr,tc), 1));
  end
end

% create the output image with borders
img = zeros(...
  sum(tileHeights+borderheight),...
  sum(tileWidths), 'uint8');
img = cat(3, ...
  img+uint8(255*1), ...
  img+uint8(255*1), ...
  img+uint8(255*1));

% fill in tiles
yStart = 1;
for tr=1:TR
  yEnd = yStart + tileHeights(tr) - 1;
  xStart = 1;
  xEnd = xStart + tileWidths(tc) - 1;

  if isempty(getimg(tr,tc))
    for channel=1:3
      img(yStart:yEnd, xStart:xEnd, channel) = uint8(255*[1 1 1]);
    end
  else
    % xy resize
    rz = imresize(getimg(tr,tc), [tileHeights(tr) tileWidths(tc)]);

    % color/intensity scaling
    [clims,doColorScaling] = getClims(tr,tc);
    if doColorScaling && ~isempty(rz)
      rz = double(rz);
      for channel = 1:size(rz,3)
        rz(:,:,channel) = rz(:,:,channel) / double(diff(clims)) + clims(1);
      end
    end

    % gray -> rgb
    if ndims(rz) == 2
      rz = cat(3, rz,rz,rz);
    elseif ndims(rz) == 3
      % nothing special here...
    else
      error('only grayscale and RGB images are supported right now');
    end

    % embed data
    img(yStart:yEnd, xStart:xEnd, :) = uint8(rz);
  end

  yStart = yEnd+1 + borderheight;
end

%-------------------------------------------------------------------------
  function ii = getimg(tr,tc)

    ii = images{tr,tc};
    if iscell(ii)
      ii = ii{1};
    end

  end

%-------------------------------------------------------------------------
  function [clims,doColorScaling] = getClims(tr,tc)

    ii = images{tr,tc};
    if iscell(ii) && numel(ii) == 1
      ii = ii{:};
    end
    if iscell(ii)
      clims = ii{2};
      ii    = ii{1};

      if isempty(clims)
        clims = [min(ii(:)) max(ii(:))];
      end
    else
      if isa(ii, 'uint8')
        clims = [0 255];
      elseif isa(ii, 'uint16')
        clims = [0 65535];
      else
        clims = [0 1];
      end
    end

    % We'll be converting everything to uint8, so it's easiest to embed the
    % scaling factor here.
    % TODO: make sure the scaling stuff actually works for non-zero clims(1).
    clims = clims / 255;

    doColorScaling = 1;
    if isa(ii, 'uint8') && all(clims == [0 255])
      doColorScaling = 0;
    end

  end

end
