function [X,map] = readpcx(filename)
%READPCX Read image data from a PCX file.
%   [X,MAP] = READPCX(FILENAME) reads image data from a PCX file.
%   X is a uint8 array that is 2-D for indexed or grayscale image
%   data, and it is M-by-N-by-3 for truecolor image data. MAP is
%   normally an M-by-3 MATLAB colormap, but it may be empty if
%   the PCX file does not contain a colormap.
%
%   See also IMREAD, IMWRITE, IMFINFO, IMFORMATS.

%   Steven L. Eddins, June 1996
%   Copyright (c) 1984-98 by The MathWorks, Inc.
%   $Revision: 1.6 $  $Date: 1998/05/06 17:46:14 $

%   Murray and vanRyper, Encyclopedia of Graphics File Formats,
%   2nd ed., O'Reilly, 1996.

info = impcxinfo(filename);

buffer = freadu8(filename, 128);
scanLineLength = info.NumColorPlanes * info.BytesPerLine;

[X, endIndex] = pcxdrle(buffer, info.Height, scanLineLength);
X = X';

map = [];
lookForVGAPalette = 1;
switch info.NumColorPlanes
case 1
    switch info.BitsPerPixelPerPlane
    case 1
        XX = X;
        X = repmat(uint8(0), size(XX) .* [1 8]);
        for k = 1:8
            X(:,k:8:end) = bitslice(XX, 8-k+1, 8-k+1);
        end
        lookForVGAPaletteMap = 1;
        map = [0 0 0; 1 1 1];     % In case a palette isn't found later.
        
    case 8
        % Nothing to do
        
    otherwise
        error('Unsupported combination of "BitDepth" and "NumColorPlanes"');
    end
    
case 3
    switch info.BitsPerPixelPerPlane
    case 1
        error('PCX files with NumColorPlanes=3 and BitDepth=1 are not supported');
        
    case 8
        X = reshape(X, [size(X,1) size(X,2)/3 3]);
        lookForVGAPalette = 1;
        
    otherwise
        error('Unsupported combination of "BitDepth" and "NumColorPlanes"');
    end

case 4
    error('PCX files with NumColorPlanes=4 are not supported');
    
otherwise
    error('Unrecognized value for NumColorPlanes');
    
end
    
if (info.Width ~= size(X,2))
    X = X(:,1:info.Width,:);
end

if (lookForVGAPalette)
    % double called in the next line because == isn't supported
    % for uint8's in MATLAB 5.0.
    remainder = length(buffer) - endIndex;
    if (((remainder == 769) & (double(buffer(endIndex+1)) == 12)) | ...
                (remainder == 768))
        % For "real" PCX files, remainder should be 769 if there's
        % a colormap. However, pcxwrite in IPT v1 failed to write the
        % 0Cx value in the byte before colormap.  For those
        % files, remainder will be 768 and there's no 0Cx code.  -SLE
        map = buffer(end-767:end);
        map = double(reshape(map,3,256)')/255;
    end
end

if ((nargout > 1) & (isempty(map)))
    warning('No colormap found in PCX file');
end
