diff --git a/Utilities/rtbMakeMontage.m b/Utilities/rtbMakeMontage.m
index 72ba3cad1ecdbac7cb006a842285e45ced5cbf74..3e6b1f163fdd626f7db7666c33128d4cfee8730b 100644
--- a/Utilities/rtbMakeMontage.m
+++ b/Utilities/rtbMakeMontage.m
@@ -73,7 +73,7 @@ if isempty(outPath)
         'hints', hints);
 end
 
-SRGBMontage = [];
+% SRGBMontage = [];
 XYZMontage = [];
 
 %% Pick the montage dimensions.
diff --git a/external/PsychToolbox/BasicToneMapCalFormat.m b/external/PsychToolbox/BasicToneMapCalFormat.m
new file mode 100755
index 0000000000000000000000000000000000000000..ebb85a2e9393dbeef263801f734793492d3f96a4
--- /dev/null
+++ b/external/PsychToolbox/BasicToneMapCalFormat.m
@@ -0,0 +1,22 @@
+function outputXYZCalFormat = BasicToneMapCalFormat(inputXYZCalFormat, maxLum)
+% outputXYZCalFormat = BasicToneMapCalFormat(inputXYZCalFormat, maxLum)
+%
+% Simple tone mapping.  Leaves any pixel with luminance below maxLum alone.
+% For pixels whose luminance exceeds maxLum, scale XYZ down multiplicatively so
+% that luminance is maxLum.
+%
+% 10/1/09 bjh, dhb     Created it.
+% 10/4/09 dhb          Debug and make it work right.
+
+% Find offending pixels
+index = find(inputXYZCalFormat(2,:) > maxLum);
+
+% If any pixel exceeds maxLum, scale it by 1/Y.  Uses
+% MATLAB's indexing trick of repeating an index to replicate 
+% values.
+outputXYZCalFormat = inputXYZCalFormat;
+if (~isempty(index))
+   outputXYZCalFormat(:, index) = maxLum*(inputXYZCalFormat(:, index)./inputXYZCalFormat([2 2 2]', index)); 
+end
+
+end
diff --git a/external/PsychToolbox/CalFormatToImage.m b/external/PsychToolbox/CalFormatToImage.m
new file mode 100755
index 0000000000000000000000000000000000000000..a060bb4ba86efecd1d976adf98b3a962d4c4179f
--- /dev/null
+++ b/external/PsychToolbox/CalFormatToImage.m
@@ -0,0 +1,18 @@
+function image = CalFormatToImage(calFormat,nX,nY)
+% image = CalFormatToImage(calFormat,nX,nY)
+% 
+% Convert a calibration format image back to a real
+% image.
+%
+% Note that the order nX,nY makes sense for thinking about images
+% in terms of x and y coordinates, but that the order is backwards
+% from the MATLAB convention of row dim then column dim.
+%
+% See also ImageToCalFormat
+%
+% 8/04/04  dhb  Wrote it.
+% 9/1/09   dhb  Update help.
+% 10/2/09  dhb  Try again on making help clear.
+
+k = size(calFormat,1);
+image = reshape(calFormat',nY,nX,k);
diff --git a/external/PsychToolbox/ImageToCalFormat.m b/external/PsychToolbox/ImageToCalFormat.m
new file mode 100755
index 0000000000000000000000000000000000000000..83c3abd91657a3778c85d563bf86689edf053d59
--- /dev/null
+++ b/external/PsychToolbox/ImageToCalFormat.m
@@ -0,0 +1,24 @@
+function [calFormat,nX,nY] = ImageToCalFormat(image)
+% [calFormat,nX,nY] = ImageToCalFormat(image)
+%
+% Take an nX (col dimension) by nY (row dimension) by k image
+% and convert it to a format that may be used to Psychtoolbox
+% calibration routines.
+%
+% Note that the order nX,nY makes sense for thinking about images
+% in terms of x and y coordinates, but that the order is backwards
+% from the MATLAB convention of row dim then column dim.
+%
+% See also CalFormatToImage
+%
+% 8/04/04  dhb  Wrote it.
+% 7/16/07  dhb  Update help line.
+% 10/2/09  dhb  Try again on making help clear.
+
+[nY,nX,k] = size(image);
+
+if nY*nX == 1
+	calFormat = squeeze(reshape(image,nY*nX,1,k));
+else
+	calFormat = squeeze(reshape(image,nY*nX,1,k))';
+end
diff --git a/external/PsychToolbox/SRGBGammaCorrect.m b/external/PsychToolbox/SRGBGammaCorrect.m
new file mode 100644
index 0000000000000000000000000000000000000000..9737ce8148dbe2f1f54bb7ab0ed00efc50226529
--- /dev/null
+++ b/external/PsychToolbox/SRGBGammaCorrect.m
@@ -0,0 +1,71 @@
+function RGB = SRGBGammaCorrect(rgb,SCALE)
+% RGB = SRGBGammaCorrect(rgb,[SCALE])
+%
+% Gamma correct according to sRGB standard.
+% 
+% SCALE = 0: No scaling applied to input rgb.  Input values > 1 truncated to 1.
+% SCALE = 1: Input data scaled to max of 1.  (Default).
+% 
+% Input values less than 0 are truncated to zero.
+%
+% The gamma correction stage of the SRGB standard converts inputs in the
+% range [0,1] into gamma corrected output in the same range.
+%
+% This routine then multiplies the [0,1] output by 255 and quantizes
+% to integer values.  None-the-less, it still returns the output as
+% a double (rather than uint8) matrix.  I (DHB) am not sure this was
+% a good design decision, but am for now (6/15/11) leaving it as is
+% to avoid breaking code that relies on the current implementation.
+% [Smarter, I think would have been to return values in the [0,1] range
+% and leave the quantization to the caller, or else to convert to uint8
+% after scaling into [0,255].]
+%
+% See XYZToSRGBPrimary for comment on evolution of the standard
+% and of this implementation.
+%
+% 5/1/04    dhb             Wrote it.
+% 7/8/10    dhb             Updated to match standard I can now find on the web.
+% 6/15/11   dhb, ms         Clarify input output range issues in comment.
+
+% Set SCALE if not passed.
+if (nargin < 2 || isempty(SCALE))
+	SCALE = 1;
+end
+
+% Scale into range, or truncate to 1.
+if (SCALE)
+	rgb = rgb/max(rgb(:));
+else
+	index = find(rgb > 1);
+	if (~isempty(index))
+		rgb(index) = 1;
+	end
+end
+
+% Truncate negative values to 0.
+index = find(rgb < 0);
+if (~isempty(index))
+	rgb(index) = 0;
+end
+
+% Cutoff value
+% Value in old routines was 0.0031308, which I actually think
+% was wrong even for the old standard.  It should have been
+% 0.00405 for the old standard.
+cutoff = 0.00304; 
+
+% Apply sRGB gamma correction according to formulae
+rgbprime = rgb;
+index = find(rgb < cutoff);
+if (~isempty(index))
+	rgbprime(index) = 12.92*rgb(index);
+end
+index = find(rgb >= cutoff);
+if (~isempty(index))
+	rgbprime(index) = 1.055*(rgb(index).^(1/2.4))-0.055;
+end
+clear rgb;
+
+% Quantize to 8 bits.
+RGB = round(255*rgbprime);
+
diff --git a/external/PsychToolbox/T_xyz1931.mat b/external/PsychToolbox/T_xyz1931.mat
new file mode 100644
index 0000000000000000000000000000000000000000..64b6669f5acda7a4c60899937f9994f81bde1060
Binary files /dev/null and b/external/PsychToolbox/T_xyz1931.mat differ
diff --git a/external/PsychToolbox/XYZToSRGBPrimary.m b/external/PsychToolbox/XYZToSRGBPrimary.m
new file mode 100644
index 0000000000000000000000000000000000000000..cf183e33b488bfa7c84610b8e315c7b592f7757b
--- /dev/null
+++ b/external/PsychToolbox/XYZToSRGBPrimary.m
@@ -0,0 +1,39 @@
+function [rgb,M] = XYZToSRGBPrimary(XYZ)
+% [rgb,M] = XYZToSRGBPrimary(XYZ)
+%
+% Convert between CIE XYZ to sRGB primary
+% coordinates.  These are linear device
+% coordinates for the primaries of the sRGB
+% standard.  If your input is scaled in the
+% gamut of the monitor, the numbers will come
+% out in the range 0-1.  You may want to scale
+% the result into the range 0-1 before applying
+% sRGB gamma correction. 
+%
+% Originally implemented from conversion matrix as specified at:
+%   http://www.srgb.com/basicsofsrgb.htm
+% It turns out this was the draft standard.  The site above is gone
+% You can still find the draft standard at:
+%   http://www.colour.org/tc8-05/Docs/colorspace/61966-2-1.pdf
+%
+% I can't find the official technical standard on the web, but
+% there is pretty good agreement across web sources.  Wikipedia
+% seems fine, as does.
+%   http://www.w3.org/Graphics/Color/sRGB
+%
+% 5/1/04	dhb				Wrote it.
+% 7/8/10    dhb             Updated to match standard I can now find on the web.
+
+% Define the transformation matrix.  Now matching what's at w3.org.  The
+% old matrix is commented out in the second line.
+M = [3.2410 -1.5374 -0.4986 ; -0.9692 1.8760 0.0416 ; 0.0556 -0.2040 1.0570];
+%M = [3.2406 -1.5372 -0.4986 ; -0.9689 1.8758 0.0415 ; 0.0557 -0.2040 1.0570];
+
+% Do the transform
+if (~isempty(XYZ))
+    rgb = M*XYZ;
+else
+    rgb = [];
+end
+
+