function writebmp(X,map,filename,varargin);
%WRITEBMP Write a BMP (Microsoft Windows Bitmap) file to disk.
%   WRITEBMP(X,MAP,FILENAME) writes the indexed image X,MAP
%   to the file specified by the string FILENAME.
%
%   WRITEBMP(RGB,[],FILENAME) writes the truecolor image
%   represented by the M-by-N-by-3 array RGB.

%   Mounil Patel 3/10/94
%   Revised Steven L. Eddins August 1996
%   Copyright 1984-2000 The MathWorks, Inc.
%   $Revision: 1.11 $  $Date: 2000/06/01 04:17:10 $

if (nargin > 3)
    error('Too many input arguments');
end

if (~isa(X,'uint8') & ~isa(X,'double'))
    error('Class of X must be uint8 or double');
end

numdims = ndims(X);
numcomps = size(X,3);

if ((numdims > 2) & ((numdims ~= 3) | (size(X,3) ~= 3)))
    error('Invalid dimensions for X');
end

if ((numcomps == 1) & (isempty(map)))
  n = 256;
  map = gray(n);
  if isa(X,'double')
    X = uint8(round(X*(n-1)));    
  end
end

if ((numcomps == 1) & (size(map,1) > 256))
    error('BMP colormaps must have 256 or fewer entries');
end

if ((numcomps == 1) & (size(map,2) ~= 3))
    error('Invalid colormap size');
end

fid=fopen(filename,'wb','l');
if (fid==-1)
    error(['Error opening ',filename,' for output.']);
end;
    
biHeight = size(X,1);
biWidth = size(X,2);

if (isa(X,'double'))
    if (numcomps == 3)
        X = uint8(round(255*X));
    else
        X = uint8(X-1);
    end
end
    
% Squeeze 3rd dimension into second
if (numcomps == 3)
    X = X(:,:,[3 2 1]);
    X = permute(X, [1 3 2]);
    X = reshape(X, [size(X,1) size(X,2)*size(X,3)]);
end

width = size(X,2);
tmp = rem(width,4);
if (tmp > 0)
    padding = 4 - tmp;
    X = cat(2, X, repmat(uint8(0), [size(X,1) padding]));
else
    padding = 0;
end

% Rotate X to compensate for BMP scanline orientation.
% In BMP files, the bottom scanline is written first.
X = rot90(X, -1);

fwrite(fid,[66;77],'uint8');

% What will be the physical file size?  First term: image data,
% with width padded to be multiple of 4.  Second term: length of
% bitmap header.  Third term: length of bitmap information
% header.  Third term: length of color palette.
if (numcomps == 1)
    bfSize = biHeight*(width+padding) + 14 + 40 + 256*4;
else
    % No palette written for RGB images
    bfSize = biHeight*(width+padding) + 14 + 40;
end
fwrite(fid,bfSize,'uint32');
bfReserved1=0;
fwrite(fid,bfReserved1,'uint16');
bfReserved2=0;
fwrite(fid,bfReserved2,'uint16');
if (numcomps == 1)
    bfOffBytes=1078;
else
    % No palette written for RGB images
    bfOffBytes = 54;
end
fwrite(fid,bfOffBytes,'uint32');
biSize=40;
fwrite(fid,biSize,'uint32');

fwrite(fid,biWidth,'uint32');
fwrite(fid,biHeight,'uint32');
biPlanes=1;
fwrite(fid,biPlanes,'uint16');
biBitCount=8*numcomps;
fwrite(fid,biBitCount,'uint16');
biCompression=0;
fwrite(fid,biCompression,'uint32');
biSizeImage=biHeight*(width+padding);
fwrite(fid,biSizeImage,'uint32');
biXPels=0;
fwrite(fid,biXPels,'uint32');
biYPels=0;
fwrite(fid,biYPels,'uint32');
if (numcomps == 1)
    biClrUsed=256;
else
    % Not relevant for RGB images.
    biClrUsed = 0;
end
fwrite(fid,biClrUsed,'uint32');
biClrImportant=0;
fwrite(fid,biClrImportant,'uint32');

if (numcomps == 1)
    map = [map; zeros(256 - size(map,1), 3)];
    map=[fliplr(round(map*255)),zeros(256,1)]';
    fwrite(fid,map(:),'uint8');
end

fclose(fid);

fwriteu8(filename, X);
