function Color3DLUTTest % A simple test/demo of use of 3D CLUT color correction. % % Shows some simple test color transformations, performs some CLUT % conversion accuracy test at the end, measuring how smaller CLUT sizes / % resolutions affect the precision of color conversion. % % Press any key to progress through different tests/demos. % % History: % 21.09.2012 mk Written. % global diffImage; % Open window with 3D CLUT color correction enabled: PsychImaging('PrepareConfiguration'); PsychImaging('AddTask', 'AllViews', 'DisplayColorCorrection', 'LookupTable3D'); w=PsychImaging('OpenWindow', 0, 0, [0 0 401 401], [], [], [], [], [], kPsychGUIWindow); % Build initial identity 3D-CLUT with 16 slots in each color dimension: clut = ones(3,16,16,16); % Put red-intensity gradient along red-axis of clut cube: for i=0:15; clut(1,i+1,:,:) = ones(16,16) * (i/15); end % Put green-intensity gradient along gree-axis of clut cube: for i=0:15; clut(2,:,i+1,:) = ones(16,16) * (i/15); end % Put blue-intensity gradient along blue-axis of clut cube: for i=0:15; clut(3,:,:,i+1) = ones(16,16) * (i/15); end % Store original identity lut as baseline: origclut = clut; DrawStim(w, clut, 'Identity mapping: gray gradient, increasing left to right.'); % Reduce level of verbosity of PsychColorCorrection() to warnings: oldverbosity = PsychColorCorrection('Verbosity', 2); % Invert red intensity gradient: for i=0:15; clut(1,i+1,:,:) = ones(16,16) * (1 - (i/15)); end DrawStim(w, clut, 'Identity mapping: Red channel gradient, decreasing left to right.'); % Invert green intensity gradient: clut = origclut; for i=0:15; clut(2,:,i+1,:) = ones(16,16) * (1 - (i/15)); end DrawStim(w, clut, 'Identity mapping: Green channel gradient, decreasing left to right.'); % Invert blue intensity gradient: clut = origclut; for i=0:15; clut(3,:,:,i+1) = ones(16,16) * (1 - (i/15)); end DrawStim(w, clut, 'Identity mapping: Blue channel gradient, decreasing left to right.'); % Only yellow gradient: Clear blue output subvolume: clut = origclut; clut(3, :, :, :) = 0; DrawStim(w, clut, 'Identity mapping: Yellow gradient, blue channel all-zeros.'); % Some basic correctness test: Screen('FillRect', w, 0); % Iterate over various CLUT subsampling levels from full resolution % identity mapping to a unit value cube and measure how precision of color % mapping degrades with decreasing resolution of the 3D CLUT: for k = 8:-1:1 mi = 2^k - 1; clut = ones(3,mi+1,mi+1,mi+1); % Put red-intensity gradient along red-axis of clut cube: for i=0:mi; clut(1,i+1,:,:) = ones(mi+1,mi+1) * (i/mi); end % Put green-intensity gradient along gree-axis of clut cube: for i=0:mi; clut(2,:,i+1,:) = ones(mi+1,mi+1) * (i/mi); end % Put blue-intensity gradient along blue-axis of clut cube: for i=0:mi; clut(3,:,:,i+1) = ones(mi+1,mi+1) * (i/mi); end PsychColorCorrection('SetLookupTable3D', w, clut); % Each RGB input triplet should map to identical output triplet (minus % interpolation errors, of course: refImage = uint8(rand(400, 400, 3) * 255); tex = Screen('MakeTexture', w, refImage); Screen('DrawTexture', w, tex); Screen('Close', tex); % Run pipeline, readback result: Screen('DrawingFinished', w); testImage = Screen('GetImage', w, [0 0 400 400], 'backBuffer'); % Show it to user: Screen('Flip', w); WaitSecs(0.5); % Compute differences: diffImage = testImage - refImage; maxdiff = max(max(max(diffImage))); mindiff = min(min(min(diffImage))); meandiff = mean(mean(mean(diffImage))); fprintf('k=%i : CLUT Resolution %i : max = %f min = %f mean = %f error.\n', k, mi+1, maxdiff, mindiff, meandiff); end % We're done: PsychColorCorrection('Verbosity', oldverbosity); Screen('CloseAll'); return; end function DrawStim(w, clut, label) % Draw some test stim: Screen('FillOval', w, [255 0 0]); % A little intensity gradient from rgb (0,0,0) to (255,255,255): Screen('DrawLines', w, [[0 ; 200] , [400 ; 200]], 10, [[0 ; 0 ; 0] , [255 ; 255 ; 255]]); % Show label for this test: Screen('TextSize', w, 14); DrawFormattedText(w, label, 'center', 50, 255); % Upload it: PsychColorCorrection('SetLookupTable3D', w, clut); % And show the color corrected stim: Screen('Flip', w); % Wait until keypress: KbStrokeWait; return; end