from read_las_header by Chris Parrish
Reads in and displays the header information from a lidar data file in LAS format

read_las_header(lasFilename)
function lasHeaderInfo = read_las_header(lasFilename)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  Reads and displays the header information from a lidar data file in    %
%  the American Society for Photogrammetry & Remote Sensing (ASPRS) LAS   %
%  format, as specified in the following document: "LAS Specification     %
%  Version 1.2" ASPRS, April 29, 2008.  It is backwards-compatible,       %
%  with respect to the LAS version (i.e., header information from lidar   %
%  files in LAS 1.0 and 1.1 formats will display fine).  Requires the     %
%  file "coordinate_sys.mat" to display coordinate system info.           %
%                                                                         %
%  Input:                                                                 %
%     lasFilename: Path and filename of LAS file                          %
%                  Example of calling this function:                      %
%                  headerInfo = read_las_header('C:\my_lidar_file.las');  %
%                                                                         %
%  Output:                                                                %
%     lasHeaderInfo: Up to 40x2 cell arrray containing all the info read  %
%                    in from the LAS file header. If coordinate system    %
%                    info is missing, then lasHeaderInfo will be a 36x2   %
%                    cell array.                                          %
%                                                                         %
%  Chris Parrish                                                          %
%  Created:  5/13/2008                                                    %
%  Modified: 2/26/2009: Minor edits in preparation to post on MATLAB      %
%                       Central. Tested in MATLAB v7.0.1.15 (R14) and     %
%                       Octave v3.0.3.                                    %
%            9/2/2011:  Fixed bug that caused Version Major, Version      %
%                       Minor, and Point Data Format IDs to not be        %
%                       read in correctly. Also now displays vertical     %
%                       datum info and units, if polulated in             %
%                       GeoKeyDirectoryTag.                               %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Open the LAS file
fid=fopen(lasFilename);
if fid == -1 
    error('LAS file could not be opened; check filename and path.')
end

% Read the header info. Numeric data is always read in as a double because 
% built-in MATLAB funtions typically expect doubles.
lasHeaderInfo(1,1:2) = [{'File Signature'}; ...
    {sscanf(char(fread(fid,4,'char*1=>char*1')'),'%c')}];
lasHeaderInfo(2,1:2) = [{'File Source ID'}; ...
    {fread(fid,1,'uint16=>double')}];
lasHeaderInfo(3,1:2) = [{'Global Encoding'}; ...
    {fread(fid,1,'uint16=>double')}];
lasHeaderInfo(4,1:2) = [{'Project ID - GUID data 1'}; ...
    {fread(fid,1,'uint32=>double')}];
lasHeaderInfo(5,1:2) = [{'Project ID - GUID data 2'}; ...
    {fread(fid,1,'uint16=>double')}];
lasHeaderInfo(6,1:2) = [{'Project ID - GUID data 3'}; ...
    {fread(fid,1,'uint16=>double')}];
lasHeaderInfo(7,1:2) = [{'Project ID - GUID data 4'}; ...
    {sscanf(char(fread(fid,8,'char*1=>char*1')'),'%c')}];
lasHeaderInfo(8,1:2) = [{'Version Major'}; ...
    {fread(fid,1,'uint8=>double')}];
lasHeaderInfo(9,1:2) = [{'Version Minor'}; ...
    {fread(fid,1,'uint8=>double')}];
lasHeaderInfo(10,1:2) = [{'System Identifier'}; ...
    {sscanf(char(fread(fid,32,'char*1=>char*1')'),'%c')}];
lasHeaderInfo(11,1:2) = [{'Generating Software'}; ...
    {sscanf(char(fread(fid,32,'char*1=>char*1')'),'%c')}];
lasHeaderInfo(12,1:2) = [{'File Creation Day of Year'}; ...
    {fread(fid,1,'uint16=>double')}];
lasHeaderInfo(13,1:2) = [{'File Creation Year'}; ...
    {fread(fid,1,'uint16=>double')}];
lasHeaderInfo(14,1:2) = [{'Header Size'}; ...
    {fread(fid,1,'uint16=>double')}];
lasHeaderInfo(15,1:2) = [{'Offset to point data'}; ...
    {fread(fid,1,'uint32=>double')}];
lasHeaderInfo(16,1:2) = [{'Number of variable length records'}; ...
    {fread(fid,1,'uint32=>double')}];
lasHeaderInfo(17,1:2) = [{'Point Data Format ID'}; ...
    {fread(fid,1,'uint8=>double')}];
lasHeaderInfo(18,1:2) = [{'Point Data Record Length'}; ...
    {fread(fid,1,'uint16=>double')}];
lasHeaderInfo(19,1:2) = [{'Number of point records'}; ...
    {fread(fid,1,'uint32=>double')}];
lasHeaderInfo(20,1:2) = [{'Number of points return 1'}; ...
    {fread(fid,1,'uint32=>double')}];
lasHeaderInfo(21,1:2) = [{'Number of points return 2'}; ...
    {fread(fid,1,'uint32=>double')}];
lasHeaderInfo(22,1:2) = [{'Number of points return 3'}; ...
    {fread(fid,1,'uint32=>double')}];
lasHeaderInfo(23,1:2) = [{'Number of points return 4'}; ...
    {fread(fid,1,'uint32=>double')}];
lasHeaderInfo(24,1:2) = [{'Number of points return 5'}; ...
    {fread(fid,1,'uint32=>double')}];
lasHeaderInfo(25,1:2) = [{'X scale factor'}; ...
    {fread(fid,1,'double=>double')}];
lasHeaderInfo(26,1:2) = [{'Y scale factor'}; ...
    {fread(fid,1,'double=>double')}];
lasHeaderInfo(27,1:2) = [{'Z scale factor'}; ...
    {fread(fid,1,'double=>double')}];
lasHeaderInfo(28,1:2) = [{'X offset'}; ...
    {fread(fid,1,'double=>double')}];
lasHeaderInfo(29,1:2) = [{'Y offset'}; ...
    {fread(fid,1,'double=>double')}];
lasHeaderInfo(30,1:2) = [{'Z offset'}; ...
    {fread(fid,1,'double=>double')}];
lasHeaderInfo(31,1:2) = [{'Max X'}; ...
    {fread(fid,1,'double=>double')}];
lasHeaderInfo(32,1:2) = [{'Min X'}; ...
    {fread(fid,1,'double=>double')}];
lasHeaderInfo(33,1:2) = [{'Max Y'}; ...
    {fread(fid,1,'double=>double')}];
lasHeaderInfo(34,1:2) = [{'Min Y'}; ...
    {fread(fid,1,'double=>double')}];
lasHeaderInfo(35,1:2) = [{'Max Z'}; ...
    {fread(fid,1,'double=>double')}];
lasHeaderInfo(36,1:2) = [{'Min Z'}; ...
    {fread(fid,1,'double=>double')}];

% Read the coordinate system info from the variable length records, if 
% available
filePos = lasHeaderInfo{14,2};  % Set file position based on header size
nVarRec = lasHeaderInfo{16,2};  % Number of variable length records
if ~(nVarRec > 0) || ~exist('coordinate_sys.mat')
    disp('Note: Cannot display coordinate system info because')
    disp('coordinate_sys.mat file was not found, or the LAS file does')
    disp('not contain any varaible length records.')
else
    load('-mat', 'coordinate_sys')
    for i = 1:nVarRec
        fseek(fid, filePos, 'bof');
        rsvd = fread(fid,1,'uint16=>double');
        userId = sscanf(char(fread(fid,16,'char*1=>char*1')'),'%c');
        recId = fread(fid,1,'uint16=>double');
        lenRec = fread(fid,1,'uint16=>double');
        desc = sscanf(char(fread(fid,32,'char*1=>char*1')'),'%c');
        filePos = filePos + lenRec + 54;
        % If the current variable length record contains the
        % GeoKeyDirectoryTag, then display the georeferencing info. Note:
        % GeoKeyDirectoryTag = 34735.
        if strcmp(userId,'LASF_Projection') && recId == 34735
            nTags = floor(lenRec/2);
            % Jump to the correct position in the file
            newFilePos = filePos - lenRec;
            fseek(fid, newFilePos, 'bof');
            nCodesFound = 0;     % Number of codes found that match tags
            for j = 1:nTags
                tag = fread(fid,1,'uint16=>double');
                % Read through the CS and units codes and see if the tag
                % matches a known code; if so store it
                index = find(projectedCsCodes == tag);
                if ~isempty(index)
                    nCodesFound = nCodesFound + 1;
                    lasHeaderInfo(36+nCodesFound,1:2) = ...
                        [{'Projected Coordinate System'}; ...
                        projectedCsNames(index)];
                end
                index = find(geographicCsCodes == tag);
                if ~isempty(index)
                    nCodesFound = nCodesFound + 1;
                    lasHeaderInfo(36+nCodesFound,1:2) = ...
                        [{'Geographic Coordinate System'}; ...
                        geographicCsNames(index)];
                end
                index = find(vertCsCodes == tag);
                if ~isempty(index)
                    nCodesFound = nCodesFound + 1;
                    lasHeaderInfo(36+nCodesFound,1:2) = ...
                        [{'Vertical Coordinate System'}; ...
                        vertCsNames(index)];
                end
                index = find(angularUnitsCodes == tag);
                if ~isempty(index)
                    nCodesFound = nCodesFound + 1;
                    lasHeaderInfo(36+nCodesFound,1:2) = ...
                        [{'Angular Units'}; ...
                        angularUnitsNames(index)];
                end
                index = find(linearUnitsCodes == tag);
                if ~isempty(index)
                    nCodesFound = nCodesFound + 1;
                    lasHeaderInfo(36+nCodesFound,1:2) = ...
                        [{'Linear Units'}; ...
                        linearUnitsNames(index)];
                end
            end
        end
    end
end

% Display the header info to the screen in a nice format
disp(['Header information from: ' lasFilename])
for i = 1:length(lasHeaderInfo)
    if isnumeric(lasHeaderInfo{i,2})
        screenOut = [lasHeaderInfo{i,1} ': ' num2str(lasHeaderInfo{i,2})];
    elseif isempty(lasHeaderInfo(i,2))
        screenOut = [lasHeaderInfo{i,1} ': 0'];
    else
        screenOut = [lasHeaderInfo{i,1} ': ' lasHeaderInfo{i,2}];
    end
    disp(screenOut)
end

% Close the LAS file
fclose(fid);


Contact us at files@mathworks.com