1%% Copyright (C) 2012 Adam H Aitkenhead <adamaitkenhead@hotmail.com>
2%% Copyright (C) 2012 Carnë Draug <carandraug+dev@gmail.com>
3%%
4%% This program is free software; you can redistribute it and/or modify
5%% it under the terms of the GNU General Public License as published by
6%% the Free Software Foundation; either version 3 of the License, or
7%% (at your option) any later version.
8%%
9%% This program is distributed in the hope that it will be useful,
10%% but WITHOUT ANY WARRANTY; without even the implied warranty of
11%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12%% GNU General Public License for more details.
13%%
14%% You should have received a copy of the GNU General Public License
15%% along with this program; If not, see <http://www.gnu.org/licenses/>.
16
17%% -*- texinfo -*-
18%% @deftypefn {Function File} {@var{header} =} analyze75info (@var{filename})
19%% @deftypefnx {Function File} {@var{header} =} analyze75info (@var{filename}, "ByteOrder", @var{arch})
20%% Read header of an Analyze 7.5 file.
21%%
22%% @var{filename} must be the path for an Analyze 7.5 file or the path for a
23%% directory with a single .hdr file can be specified.
24%%
25%% The optional argument @code{"ByteOrder"} reads the file with the specified
26%% @var{arch} ("ieee-be" or "ieee-le" for IEEE big endian or IEEE
27%% little endian respectively).
28%%
29%% @var{header} is a structure with the file information.
30%%
31%% @seealso{analyze75read, analyze75write}
32%% @end deftypefn
33
34function header = analyze75info (filename, varargin)
35
36  if (nargin ~= 1 && nargin ~= 3)
37    print_usage;
38  elseif (~ischar (filename))
39    error ('analyze75info: `filename'' must be a string');
40  elseif (nargin == 3)
41    %% Check the byteorder
42    if (strcmpi (varargin{1}, 'byteorder'))
43      error ('analyze75info: second argument must be string `ByteOrder''');
44    elseif (!all (strcmpi (varargin{3}, {'ieee-le', 'l', 'ieee-be', 'b'})))
45      error ('analyze75info: valid options for `ByteOrder'' are `ieee-le'' or `ieee-be''');
46    elseif (any (strcmpi (varargin{3}, {'ieee-be', 'b'})))
47      warning ('analyze75info: no support for big-endian. Please consider submitting a patch. Attempting to read as little-endian');
48    end
49  end
50
51  fileprefix = analyze75filename (filename);
52
53  %% finally start reading the actual file
54  hdrdirdata              = dir ([fileprefix, '.hdr']);
55  imgdirdata              = dir ([fileprefix, '.img']);
56
57  header.ImgFileSize      = imgdirdata.bytes;
58
59  header.Filename         = [fileprefix, '.hdr'];
60  header.FileModDate      = hdrdirdata.date;
61  header.Format           = 'Analyze';
62  header.FormatVersion    = '7.5';
63  header.ColorType        = 'grayscale';
64  header.ByteOrder        = 'ieee-le';
65
66  fidH                    = fopen ([fileprefix, '.hdr']);
67
68  header.HdrFileSize      = fread (fidH, 1, 'int32');
69  header.HdrDataType      = char (fread (fidH, 10, 'char'))';
70  header.DatabaseName     = char (fread (fidH, 18, 'char'))';
71  header.Extents          = fread (fidH, 1, 'int32');
72  header.SessionError     = fread (fidH, 1, 'int16');
73  header.Regular          = char (fread (fidH, 1, 'char'));
74  unused                  = char (fread (fidH, 1, 'char'));
75  unused                  = fread (fidH, 1, 'int16');
76  header.Dimensions       = zeros (size (1, 4));
77  header.Dimensions(1)    = fread (fidH, 1, 'int16');
78  header.Dimensions(2)    = fread (fidH, 1, 'int16');
79  header.Dimensions(3)    = fread (fidH, 1, 'int16');
80  header.Dimensions(4)    = fread (fidH, 1, 'int16');
81  unused                  = fread (fidH, 3, 'int16');
82  header.VoxelUnits       = char (fread (fidH, 4, 'char'))';
83  header.CalibrationUnits = char (fread (fidH, 8, 'char'))';
84  unused                  = fread (fidH, 1, 'int16');
85
86  datatype = fread (fidH, 1, 'int16');
87  switch datatype
88  case   0, header.ImgDataType = 'DT_UNKNOWN';
89  case   1, header.ImgDataType = 'DT_BINARY';
90  case   2, header.ImgDataType = 'DT_UNSIGNED_CHAR';
91  case   4, header.ImgDataType = 'DT_SIGNED_SHORT';
92  case   8, header.ImgDataType = 'DT_SIGNED_INT';
93  case  16, header.ImgDataType = 'DT_FLOAT';
94  case  32, header.ImgDataType = 'DT_COMPLEX';
95  case  64, header.ImgDataType = 'DT_DOUBLE';
96  case 128, header.ImgDataType = 'DT_RGB';
97  case 255, header.ImgDataType = 'DT_ALL';
98  otherwise, warning ('analyze75: unable to detect ImgDataType');
99  end
100
101  header.BitDepth           = fread (fidH, 1, 'int16');
102  unused                    = fread (fidH, 1, 'int16');
103  unused                    = fread (fidH, 1, 'float');
104  header.PixelDimensions    = zeros (1, 3);
105  header.PixelDimensions(1) = fread (fidH, 1, 'float');
106  header.PixelDimensions(2) = fread (fidH, 1, 'float');
107  header.PixelDimensions(3) = fread (fidH, 1, 'float');
108  unused                    = fread (fidH, 4, 'float');
109  header.VoxelOffset        = fread (fidH, 1, 'float');
110  unused                    = fread (fidH, 3, 'float');
111  header.CalibrationMax     = fread (fidH, 1, 'float');
112  header.CalibrationMin     = fread (fidH, 1, 'float');
113  header.Compressed         = fread (fidH, 1, 'float');
114  header.Verified           = fread (fidH, 1, 'float');
115  header.GlobalMax          = fread (fidH, 1, 'int32');
116  header.GlobalMin          = fread (fidH, 1, 'int32');
117  header.Descriptor         = char (fread (fidH, 80, 'char'))';
118  header.AuxFile            = char (fread (fidH, 24, 'char'))';
119  header.Orientation        = char (fread (fidH, 1,  'char'))';
120  header.Originator         = char (fread (fidH, 10, 'char'))';
121  header.Generated          = char (fread (fidH, 10, 'char'))';
122  header.Scannumber         = char (fread (fidH, 10, 'char'))';
123  header.PatientID          = char (fread (fidH, 10, 'char'))';
124  header.ExposureDate       = char (fread (fidH, 10, 'char'))';
125  header.ExposureTime       = char (fread (fidH, 10, 'char'))';
126  unused                    = char (fread (fidH, 3,  'char'))';
127  header.Views              = fread (fidH, 1, 'int32');
128  header.VolumesAdded       = fread (fidH, 1, 'int32');
129  header.StartField         = fread (fidH, 1, 'int32');
130  header.FieldSkip          = fread (fidH, 1, 'int32');
131  header.OMax               = fread (fidH, 1, 'int32');
132  header.OMin               = fread (fidH, 1, 'int32');
133  header.SMax               = fread (fidH, 1, 'int32');
134  header.SMin               = fread (fidH, 1, 'int32');
135
136  header.Width              = header.Dimensions(1);
137  header.Height             = header.Dimensions(2);
138
139  fclose(fidH);
140end
141