classdef SeqWriter < handle
%SEQWRITER  Class for writing frame sequences.

% (c) 2020-04-02 Martin Matousek
% Last change: $Date$
%              $Revision$

properties
  filename
  video
  gif
  frameno
  decimate

end

methods


function this = SeqWriter( filename )
  this.video = [];
  this.gif = [];
  this.decimate = 1;
  this.filename = filename;
  this.frameno = 0;
  [~,~,ext] = fileparts( filename );

  switch ext
    case '.avi'
      if isempty( ver( 'matlab' ) )
        assert( ~isempty( ver( 'octave' ) ) )
        % image sequence fallback, no VideoWriter in Octave
        warning( 'Using image sequence fallback instead of avi.' )
        if ~exist( filename, 'dir' ), mkdir( filename ); end
        this.filename = [ filename '/%.4i.png' ];
      else
        this.video = VideoWriter( filename );
        open( this.video );
        %mov.fps = 25;
        %mov.compression = 'none';
      end

    case '.gif'
      if isempty( ver( 'matlab' ) )
        assert( ~isempty( ver( 'octave' ) ) )
        % image sequence fallback, no VideoWriter in Octave
        warning( 'Sequence writing to gif not implemented.' )
        this.gif = -1;
      else
        this.gif = nan;
      end
    case { '.png', '.jpg' }
    otherwise
      error( 'Unhandled file type: %s', ext )
  end
end % fcn.


function Close( this )
  if ~isempty( this.video )
    close( this.video );
    this.video = [];
  end
end % fcn.


function Write( this, frame )
  this.frameno = this.frameno + 1;

  if this.decimate > 1
    d = ceil( this.decimate );

    nframe = 0;
    for i = 1:d
      for j = 1:d
        nframe = nframe + frame( i:d:end-d+i, j:d:end-d+j, : );
      end
    end

    frame = nframe / d / d;
  end

  if ~isempty( this.video )
    writeVideo( this.video, frame )

  elseif ~isempty( this.gif ) % colomap stored in this.gif property
    if isequal( this.gif, -1 ) % ignore, skip
      return
    end
    if this.frameno == 1
      [frame, this.gif] = rgb2ind( frame, 256 );
      imwrite( frame, this.gif, this.filename, ...
               'delaytime', 0.04, 'loopcount', inf );
    else
      frame= rgb2ind( frame, this.gif );
      imwrite( frame, this.gif, this.filename, ...
               'delaytime', 0.04, 'writemode', 'append' );
    end
  else % image sequence
    f = sprintf( this.filename, this.frameno - 1);
    imwrite( frame, f );
  end

end % fcn.

end % meths.

end % cls.
