# HG changeset patch
# User Lambert Wixson <lambertWx@gmail.com>
# Date 1448802524 18000
#      Sun Nov 29 08:08:44 2015 -0500
# Node ID f5f6385e30ee3fb78c22bb901244e0345b0fba5c
# Parent  a6dbc5e58db4a52ed4db16b9642e42de534749a0
Extended image I/O for Analyze 7.5 format to handle big-endian images.

* analyze75info.m : Add ability to read a header that is in big-endian format.  Fixed bug in the test to see whether ByteOrder arg is passed in. Added lines to open the file for big-endian reading

* analyze75write.m : Add ability to write out a big-endian image.  Set the byte order in the header.  Added fix to properly set the Dimensions field in the header when data is just a 2-D array.  Added some regression tests to ensure that little-endian and big-endian I/O works.

diff -r a6dbc5e58db4 -r f5f6385e30ee inst/analyze75info.m
--- a/inst/analyze75info.m	Fri Nov 27 18:41:58 2015 +0000
+++ b/inst/analyze75info.m	Sun Nov 29 08:08:44 2015 -0500
@@ -32,6 +32,7 @@
 %% @end deftypefn
 
 function header = analyze75info (filename, varargin)
+  isBig = 0;
 
   if (nargin ~= 1 && nargin ~= 3)
     print_usage;
@@ -39,12 +40,12 @@
     error ('analyze75info: `filename'' must be a string');
   elseif (nargin == 3)
     %% Check the byteorder
-    if (strcmpi (varargin{1}, 'byteorder'))
+    if (!strcmpi (varargin{1}, 'byteorder'))
       error ('analyze75info: second argument must be string `ByteOrder''');
-    elseif (!all (strcmpi (varargin{3}, {'ieee-le', 'l', 'ieee-be', 'b'})))
+    elseif (!any (strcmpi (varargin{2}, {'ieee-le', 'l', 'ieee-be', 'b'})))
       error ('analyze75info: valid options for `ByteOrder'' are `ieee-le'' or `ieee-be''');
-    elseif (any (strcmpi (varargin{3}, {'ieee-be', 'b'})))
-      warning ('analyze75info: no support for big-endian. Please consider submitting a patch. Attempting to read as little-endian');
+    elseif (any (strcmpi (varargin{2}, {'ieee-be', 'b'})))
+      isBig = 1;
     end
   end
 
@@ -61,9 +62,13 @@
   header.Format           = 'Analyze';
   header.FormatVersion    = '7.5';
   header.ColorType        = 'grayscale';
-  header.ByteOrder        = 'ieee-le';
-
-  fidH                    = fopen ([fileprefix, '.hdr']);
+  if (isBig) 
+    header.ByteOrder        = 'ieee-be';
+    fidH                    = fopen ([fileprefix, '.hdr'], "r", "ieee-be");
+  else
+    header.ByteOrder        = 'ieee-le';
+    fidH                    = fopen ([fileprefix, '.hdr'], "r", "ieee-le");
+  end
 
   header.HdrFileSize      = fread (fidH, 1, 'int32');
   header.HdrDataType      = char (fread (fidH, 10, 'char'))';
diff -r a6dbc5e58db4 -r f5f6385e30ee inst/analyze75write.m
--- a/inst/analyze75write.m	Fri Nov 27 18:41:58 2015 +0000
+++ b/inst/analyze75write.m	Sun Nov 29 08:08:44 2015 -0500
@@ -76,13 +76,12 @@
   end
   
   % Check the byteorder
-  if (nargin == 6)
-    if (isfield (header, 'ByteOrder')) &&  (any (strcmpi (header.ByteOrder, {'ieee-be', 'b'})))
-      warning ('analyze75write: No support for big-endian. Please consider submitting a patch. Attempting to write as little-endian');
-    end
+  if (isfield (header, 'ByteOrder')) &&  (any (strcmpi (header.ByteOrder, {'ieee-be', 'b'})))
+    header.ByteOrder = 'ieee-be';
+  else
+    header.ByteOrder = 'ieee-le';
   end
-  header.ByteOrder = 'ieee-le';
-  
+
   %% Rearrange the data
   data = permute(data,[2,1,3]);
   
@@ -94,7 +93,11 @@
 
   % Check certain header fields
   header.PixelDimensions = single(10 * [x(2)-x(1),y(2)-y(1),z(2)-z(1)]);
-  header.Dimensions      = int16([size(data),1]);
+  if (ndims(data) == 2)
+    header.Dimensions      = int16([size(data), 1, 1]);
+  else
+    header.Dimensions      = int16([size(data),1]);
+  end
   header.HdrFileSize     = int32(348);
   header.VoxelUnits      = 'mm  ';
   header.GlobalMin       = int32(min(data(:)));
@@ -225,3 +228,44 @@
     datanew(:,:,loopN) = interpn(x,y,z,data,x,y,znew(loopN));
   end
 end
+
+
+%!test 
+%!  printf("TEST: Confirm that little-endian writes are properly read back in.\n");
+%!  # Generate 400 w x 200 h quarter-circle sinusoid pattern
+%!  [x, y] = meshgrid(linspace(0, 4*pi, 400), linspace(0, 2*pi, 200));
+%!  pat = sin(sqrt(x.^2 + y.^2)) .* 5;
+%!  pat = im2single(pat);
+%!  outminmax = [min(min(pat))  max(max(pat))];
+%!  outhdr = struct;
+%!  outhdr.VoxelUnits = 'mm';
+%!  outhdr.PixelDimensions = [1 1 1];
+%!  outhdr.ByteOrder = 'ieee-le';
+%!  outhdr.Dimensions = [rows(pat) columns(pat) 2];
+%!  analyze75write("an_testpat.img", pat, outhdr);  # Creates a .img and .hdr file
+%!  inhdr = analyze75info("an_testpat.hdr");
+%!  inpat = analyze75read(inhdr);
+%!  assert(size(pat) == size(inpat))
+%!  inminmax =  [min(min(inpat))  max(max(inpat))];
+%!  assert(outminmax == inminmax)
+
+
+%!test 
+%!  printf("TEST: Confirm that big-endian writes are properly read back in.\n");
+%!  # Generate 400 w x 200 h quarter-circle sinusoid pattern
+%!  [x, y] = meshgrid(linspace(0, 4*pi, 400), linspace(0, 2*pi, 200));
+%!  pat = sin(sqrt(x.^2 + y.^2)) .* 5;
+%!  pat = im2single(pat);
+%!  outminmax = [min(min(pat))  max(max(pat))];
+%!  outhdr = struct;
+%!  outhdr.VoxelUnits = 'mm';
+%!  outhdr.PixelDimensions = [1 1 1];
+%!  outhdr.ByteOrder = 'ieee-be';
+%!  outhdr.Dimensions = [rows(pat) columns(pat) 2];
+%!  analyze75write("an_testpat.img", pat, outhdr);  # Creates a .img and .hdr file
+%!  inhdr = analyze75info("an_testpat.hdr", 'byteorder', 'ieee-be');
+%!  inpat = analyze75read(inhdr);
+%!  assert(size(pat) == size(inpat))
+%!  inminmax =  [min(min(inpat))  max(max(inpat))];
+%!  assert(outminmax == inminmax)
+
