This file is indexed.

/usr/share/psychtoolbox-3/PsychGLImageProcessing/VignetCalibration.m is in psychtoolbox-3-common 3.0.11.20131230.dfsg1-1build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
function s = VignetCalibration(filename, screenId)
% s = VignetCalibration([filename] [, screenId])
%
% Vignetted Luminance calibration procedure for undistortion of distorted
% display luminance.
%
% This code was created by Jorrit S. Montijn of the Laboratoire Psychologie
% de la Perception at Universite Paris Descartes.
%
% This function allows the user to create a calibration for a vignetted
% luminance distortion. It enables the user to choose from either a
% Gaussian or Exponential approximation of the luminance vignetting. Users
% can change the position and steepness of the luminance fall-off in
% horizontal and vertical direction independently. It is also possible to
% adjust the minimal luminance.
%
% Once the calibration procedure is finished, the gain matrix (and other
% possibly useful parameters and variables) are saved to disk for use by a
% vignetting compensation program (see 'VignettingCorrectionDemo' for an
% example of how to do this).
% 
% How to use:
% 
% Start the script, providing a filename and screennumber:
%
% 'filename' is the name of the file to which calibration results will be 
% saved. If none is provided, a default name will be used. The default file
% will be stored in the directory returned by PsychtoolboxConfigDir('ShadingCalibration').
%
% 'screenId' is the optional index of the screen that you want to
% calibrate. If only one screen is present, it is not necessary to include
% this parameter.
%
% When started, the program will show either a gaussian or exponential
% approximation of the required gain function. You can adjust the
% parameters so that the screen will look approximately isoluminant. It is
% recommended to use a photometer, since human eyes are far from perfect when
% doing this.
%
% You can use the following keys to issue commands:
%
% Escape	-	use this key to save and exit
% Tab		-	show/hide help text
% Space		-	change the parameter you wish to adjust
% '<' and '>'	-	use these keys to change the increment size of the
%					parameter adjustments
% Arrow Keys	-	adjust parameters (depending on selected parameter)
%				1. Luminance/Function type
%				2. Width/Steepness of function
%				3. Position of centre
%

% History:
%
% 16.03.2010     Interactive Vignetting Calibration function created
%			     by Jorrit S. Montijn.
%
% 18.03.2010  mk Minimal cleanup and merge into distribution.
% 27.03.2010  mk Switch to multiplicative inverse. Use gainCorrection of a
%                50% grey background via PsychColorCorretion(). This allows
%                for > 1.0 gain values.
% 19.04.2010  jm Removed Lmin restrictions allowing for gain values to take
%				 any value (-inf < Lmin < inf), added display of 
%				 current parameter values in on-screen help text
%

	% Check for proper installation:
	PsychDefaultSetup(1);

	%create variable if needed
    if ~exist('screenId','var')
        screenId = [];
    end

    % Fetch connected screens:
    screens = Screen('Screens');

    %if no screen nr was provided
    if isempty(screenId)
        %ask which one to calibrate if more than 1 is present
        if length(screens)>1,
            screenId = str2double(input(['Which screen should we calibrate? [' num2str(screens) '] '],'s'));
        else
            screenId = screens;
        end
    end

    if ~ismember(screenId, screens)
        error('No such screen. Please restart program with valid screenid.');
    end
    
	%put screenId number into structure
	s.scrNr = screenId;

	%fetch screen resolution
	[w, h] = Screen('WindowSize', screenId);

	%create variable if needed
	if ~exist('filename', 'var')
		filename = [];
	end

	%if no filename was provided
	if isempty(filename)
		%assign filename
		filename = [PsychtoolboxConfigDir('ShadingCalibration') 'VignetCalibration' sprintf('_%i_%i_%i', screenId, w, h) '.mat'];
		fprintf('\nNo filename defined... Using default\n');
	end

	%show name of output file and check to overwrite
	fprintf('Name of outputfile: %s\n\n', filename);
	if exist(filename, 'file')
		answer = input('File already exists. Overwrite? [y/n]','s');
		if ~strcmp(lower(answer), 'y') %#ok<STCI>
			fprintf('\n\nCalibration aborted. Please restart program and specify another filename.\n\n');
			return;
		end
	end

	%disable synctests
	oldsynclevel = Screen('Preference', 'SkipSyncTests', 2);
	%change verbosity
	oldverbosity = Screen('Preference', 'Verbosity', 1);

	% Open window on desired screenId:
    % Use imaging pipeline for visual processing and display:
    PsychImaging('PrepareConfiguration');

    % Request per-pixel 2D gain correction for display:
    PsychImaging('AddTask', 'FinalFormatting', 'DisplayColorCorrection', 'GainMatrix');

    % Open window with gray background (128 aka 50% gray), return handle 'win':
    [s.window, rect] = PsychImaging('OpenWindow', s.scrNr, 128);
    
	%change text appearance
	Screen('TextSize',s.window, 18);
	Screen('TextStyle', s.window, 1+2);
	Screen('TextColor', s.window, [255 0 0]);

	%put rect into structure
	s.rect = rect;

	try
		%hide cursor and disable input
		HideCursor;
		ListenChar(2);

		%initialize parameters
		[beta,xGrid,yGrid] = InitVignetCalibration(s.rect);

		%put values into structure
		s.quitNow = 0;
		s.beta = beta;
		s.xGrid = xGrid;
		s.yGrid = yGrid;

		%start calibration
		s = CalibrateVignetNow(s);

		%collect variables from structure for easy access
		gainMatrix = s.textureGrid; %#ok<NASGU>
		parameters = s.beta; %#ok<NASGU>
		functionType = s.functionType; %#ok<NASGU>
		
        % Strip redundant data from 's':
        bs = s;
        s.xGrid = [];
        s.yGrid = [];
        s.textureGrid = [];
        
		%save variables and structure to file
		save(filename, 'gainMatrix', 'parameters', 'functionType', 's', '-mat', '-V6');

        % Restore unstripped 's' before return:
        s = bs;
        
		fprintf('The calibration is finished! \n\n');
		fprintf('Your calibration matrix, parameters and function type have been saved to\n%s\n', filename);
		fprintf('Also included in the file is a structure that contains most settings you used.\n');
		fprintf('For an example on how to use the generated gain matrix to reduce vignetting,\n');
		fprintf('please take a look at the PsychToolbox demo ''VignettingCorrectionDemo''\n\n');
	catch
		%show cursor
		ShowCursor('Arrow');

		%reset screen values
		Screen('CloseAll');
		Screen('Preference', 'SkipSyncTests', oldsynclevel);
		Screen('Preference', 'Verbosity', oldverbosity);

		%reenable listenchar
		ListenChar(0);

		%rethrow error
		psychrethrow(psychlasterror);
	end

	%reenable listenchar
	ListenChar(0);

	%restore cursor
	ShowCursor('Arrow');

	%reset screen values
	Screen('CloseAll');
	Screen('Preference', 'SkipSyncTests', oldsynclevel);
	Screen('Preference', 'Verbosity', oldverbosity);
	
	return;
end

function [beta,xGrid,yGrid] = InitVignetCalibration(rect)

	rLeft = rect(1);
	rTop = rect(2);
	rRight = rect(3);
	rBot = rect(4);

	xPixelSpace = rLeft+1:rRight; %horizontal pixel space
	yPixelSpace = rTop+1:rBot; %vertical pixel space

	xPixNum = length(xPixelSpace); %number of pixels on x-axis
	yPixNum = length(yPixelSpace); %number of pixels on y-axis

	Lmin = 0; %minimal luminance level
	wX = xPixNum/2; %initial horizontal gaussian width is quarter of screen
	wY = yPixNum/2; %initial vertical gaussian width is quarter of screen
	muX = xPixNum/2; %initial horizontal gaussian position is at middle of screen
	muY = yPixNum/2; %initial vertical gaussian position is at middle of screen

	%put parameters into beta variable
	beta(1) = Lmin;
	beta(2) = wX;
	beta(3) = wY;
	beta(4) = muX;
	beta(5) = muY;

	%create meshgrids from pixel spaces
	[xGrid,yGrid] = meshgrid(xPixelSpace,yPixelSpace);
end


function s = CalibrateVignetNow(s)

	%define initial variables
	useFunction = 1;
	drawText = 1;
	paramNow = 1;
	beta = s.beta;
	xGrid = s.xGrid;
	yGrid = s.yGrid;
	switchVar = [2 1];
	switchVar3 = [2 3 1];
	redrawTexture = 1;
	functionList = {'Gaussian','Exponential'};
	paramList = {'Minimum Luminance','Width','Position'};

	%create Lmin variables
	Lmin = beta(1);
	LminIncrement = 0.1;

	%create width variables
	wX = beta(2);
	wY = beta(3);
	wIncrement = wX/20;

	%create position variables
	muX = beta(4);
	muY = beta(5);
	muIncrement = muX/20;

	while s.quitNow == 0
		%if texture whould be (re)drawn
		if redrawTexture == 1
			%reset redraw var
			redrawTexture = 0;

			%create grid from parameters
			beta(1) = Lmin;
			beta(2) = wX;
			beta(3) = wY;
			beta(4) = muX;
			beta(5) = muY;
			if useFunction == 1
				%use gaussian approximation
				textureGrid = gaussianGrid(beta, xGrid, yGrid);
			else
				%use exponential approximation
				textureGrid = exponentialGrid(beta,xGrid,yGrid);
			end

            % Apply gain correction matrix to display: This will take effect at the
            % next Screen('Flip'):
            PsychColorCorrection('SetGainMatrix', s.window, textureGrid);
		end

		%if text should be drawn
		if drawText == 1
			%draw help
			s.functionType = functionList{useFunction};
			if paramNow == 1
				thisIncrement = num2str(LminIncrement);
				upDown = 'increase/decrease min Luminance factor';
				curValUD = num2str(beta(1));
				leftRight = 'Shift to other function';
				curValLR = s.functionType;
			elseif paramNow == 2
				thisIncrement = num2str(wIncrement);
				upDown = 'increase/decrease vertical sigma';
				curValUD = num2str(beta(3));
				leftRight = 'decrease/increase horizontal sigma';
				curValLR = num2str(beta(2));
			else
				thisIncrement = num2str(muIncrement);
				upDown = 'move centre up/down';
				curValUD = num2str(beta(5));
				leftRight = 'move centre left/right';
				curValLR = num2str(beta(4));
			end
			
			text = ['You can use the following commands:\n\n'...
				'TAB: show/hide this text\n'...
				'Escape: save&exit\n'...
				'Space: switch parameters :: Current: ' paramList{paramNow} '\n'...
				'"<" and ">": decrease/increase increment: ' thisIncrement '\n'...
				'Up/Down: ' upDown ' :: Current: ' curValUD '\n'...
				'Left/Right: ' leftRight ' :: Current: ' curValLR '\n'];
			DrawFormattedText(s.window,text,20,20);
		end

		%flip screen
		Screen('Flip',s.window);

		%check for input
		inputReceived = 0;
		keyPressed = 0;
        while inputReceived == 0 && s.quitNow == 0
            KbWait; %wait till keypress
            [keyIsDown,secs,keyCode]=KbCheck;
            if keyIsDown
                if keyPressed == 0
                    keyPressed = 1;
                    inputReceived = 1;
                    if keyCode(KbName('Escape'))
                        %done! Put output texture  and parameters in
                        %structure to return to master function and break
                        %loop

                        s.textureGrid = textureGrid;
                        s.beta = beta;
                        s.quitNow = 1;
                        break;
                    elseif keyCode(KbName('space'))
                        %shift adjustment parameters
                        %1: strength (Lmin)
                        %2: width (wX and xY)
                        %3: position (muX and muY)
                        paramNow = switchVar3(paramNow);
                    elseif keyCode(KbName('tab'))
                        %toggle show/hide text
                        drawText = switchVar(drawText);
                    else
                        if paramNow == 1
                            %Lmin
                            valueX = Lmin;
                            valueY = Lmin;
                            increment = LminIncrement;
                        elseif paramNow == 2
                            %width
                            valueX = wX;
                            valueY = wY;
                            increment = wIncrement;
                        elseif paramNow == 3
                            %position
                            valueX = muX;
                            valueY = muY;
                            increment = muIncrement;
                        end

                        if keyCode(KbName('LeftArrow'))
                            %adjust left
                            redrawTexture = 1;
                            valueX = valueX - increment;
                            if paramNow == 1
                                useFunction = switchVar(useFunction);
                            end
                        elseif keyCode(KbName('RightArrow'))
                            %adjust right
                            redrawTexture = 1;
                            valueX = valueX + increment;
                            if paramNow == 1
                                useFunction = switchVar(useFunction);
                            end
                        elseif keyCode(KbName('UpArrow'))
                            %adjust up
                            redrawTexture = 1;
                            if paramNow == 3
                                valueY = valueY - increment;
                            else
                                valueY = valueY + increment;
                            end
                        elseif keyCode(KbName('DownArrow'))
                            %adjust down
                            redrawTexture = 1;
                            if paramNow == 3
                                valueY = valueY + increment;
                            else
                                valueY = valueY - increment;
                            end
                        elseif keyCode(KbName(',<'))
                            %decrease increment
                            increment = increment / 2;
                        elseif keyCode(KbName('.>'))
                            %increase increment
                            increment = increment * 2;

                        else
                            %false alarm: no input received, just a random keypress
                            inputReceived = 0;
                        end

                        if paramNow == 1
                            %Lmin
                            LminIncrement = increment;
                            Lmin = valueY;
                        elseif paramNow == 2
                            %width
                            wIncrement = increment;
                            wX = valueX;
                            wY = valueY;
                        elseif paramNow == 3
                            %position
                            muIncrement = increment;
                            muX = valueX;
                            muY = valueY;
                        end
                    end
                end
            else
                keyPressed = 0;
            end
        end
        KbReleaseWait;
	end
end


function gaussGrid = gaussianGrid(beta, xGrid, yGrid)
	
	Lmin = beta(1); %minimal luminance level (0-1)
	wX = beta(2); %width on x-axis (pixels)
	wY = beta(3); %width on y-axis (pixels)
	muX = beta(4); %centre on x-axis (pixels)
	muY = beta(5); %centre on y-axis (pixels)

	gaussX = exp(- (((xGrid-muX).^2) / ((2*wX).^2) ) ); %create horizontal gaussian
	gaussY = exp(- (((yGrid-muY).^2) / ((2*wY).^2) ) ); %create vertical gaussian

	comb = gaussX.*gaussY; %combine into one grid

    % Invert grid: Multiplicative inverse should compensate for
    % multiplicative attenuation of display. Add offset Lmin to shift the
    % gainfield around: The final matrix stores floating point gain values
    % greater or equal to 0.0:
	gaussGrid = (1 ./ comb) + Lmin;

    fprintf('Mingain = %f, Maxgain = %f\n', min(min(gaussGrid)), max(max(gaussGrid)));
end


function expoGrid = exponentialGrid(beta, xGrid,yGrid)

	Lmin = beta(1); %minimal luminance level (0-1)
	xF = beta(2); %width on x-axis (pixels)
	yF = beta(3); %width on y-axis (pixels)
	muX = beta(4); %centre on x-axis (pixels)
	muY = beta(5); %centre on y-axis (pixels)


	expX = min(exp(xGrid/xF-muX/xF),exp(-xGrid/xF+muX/xF) ); %horizontal part
	expY = min(exp(yGrid/yF-muY/yF),exp(-yGrid/yF+muY/yF) ); %vertical part

	comb = expX.*expY; %combine into one grid

    % Invert grid: Multiplicative inverse should compensate for
    % multiplicative attenuation of display. Add offset Lmin to shift the
    % gainfield around: The final matrix stores floating point gain values
    % greater or equal to 0.0:
	expoGrid = (1 ./ comb) + Lmin;
	
    fprintf('Mingain = %f, Maxgain = %f\n', min(min(expoGrid)), max(max(expoGrid)));
end