/usr/share/psychtoolbox-3/PsychGLImageProcessing/Add2DSeparableConvolutionToGLOperator.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 | function Add2DSeparableConvolutionToGLOperator(gloperator, kernel1, kernel2, opname, nrinputchannels, nroutchannels, debug, shadertype)
% Add2DSeparableConvolutionToGLOperator(gloperator, kernel1, kernel2 [, opname] [, nrinputchannels] [, nroutchannels] [, debug] [, shadertype])
%
% Add a separable 2D pair of convolution kernels to GL operator 'gloperator'.
%
% 'kernel1' and 'kernel2' are a simple 1-by-n or m-by-1 matrices of floating
% point numbers with m and n being odd numbers, e.g., 1, 3, 5, 7, 9, ...
% Each entry in the kernel matrices is used as a weight factor for the
% convolution. First kernel1 is applied
%
% The simplest way to get a kernel is to use the function
% kernel = fspecial(...); fspecial is part of the Matlab image
% processing toolbox, see "help fspecial" for more information.
%
% 'opname' is the optional name of the convolution operation, meant as
% debugging aid.
%
% 'nrinputchannels' = The number of image channels to use as input for the
% convolution. Possible values are: 3 = Red, Green and Blue color channels are
% provided as part of a true-color image, don't use the alpha channel (if
% any) for convolution but just pass it through unmodified. 1 = The image
% only defines a luminance channel for convolution, an (optional) alpha
% channel is passed through unmodified. 4 = Use all four channels (Red,
% green, blue, alpha) for convolution.
%
% 'nroutchannels' = The number of channels to convolve as output: 3 =
% Convolve each of the three color channels red, green and blue separately
% by the same kernel. An (optional) alpha channel is passed through unmodified.
% 1 = Output a filtered luminance channel, and an (optional) unmodified
% alpha channel. If input is a 3 channel RGB image, then the RGB image will
% get converted to luminance before convolution. 4 = Filter all four
% channels independently.
%
% Typical settings:
%
% Filter a RGB(A) image: nrinputchannels = 3, nroutchannels = 3.
% Filter a RGB(A) image into grayscale: nrinputchannels = 3, nroutchannels = 1.
% Filter a luminance(A) image: inputchannels = 1, filteredoutchannels = 1.
% Generic filtering of 4-channel data: nrinputchannels = 4, nroutchannels = 4.
%
% 'debug' Optional debug flag: If set to non-zero, will output some debug
% info about the shader.
%
% 'shadertype' (Optional) The type of internal implementation to choose for
% the operator. This parameter is best left alone, unless you really know
% what you are doing.
% History:
% 08/11/07 Written (MK).
% Check input arguments for validity and assign defaults:
if nargin < 1 || isempty(gloperator) || Screen('WindowKind', gloperator)~=4
error('You must provide the handle of a valid GL imaging operator ''gloperator''!');
end
if nargin < 2 || isempty(kernel1) || ndims(kernel1)~=2
error('You must provide a 1D ''kernel1'' matrix as 2nd argument!');
end
% Query size of kernel:
kernelw = size(kernel1,1);
kernelh = size(kernel1,2);
% We only want odd sized kernels of at least 1x1, e.g., 3x3, 5x5, 7x7, ...
if kernelw < 1 || kernelh < 1 || mod(kernelw,2)~=1 || mod(kernelh,2)~=1
error('Your kernel1 must be odd-sized and at least of size 1x1!');
end;
if nargin < 3 || isempty(kernel2) || ndims(kernel2)~=2
error('You must provide a 1D ''kernel2'' matrix as 3rd argument!');
end
% Query size of kernel:
kernelw = size(kernel2,1);
kernelh = size(kernel2,2);
% We only want odd sized kernels of at least 1x1, e.g., 3x3, 5x5, 7x7, ...
if kernelw < 1 || kernelh < 1 || mod(kernelw,2)~=1 || mod(kernelh,2)~=1
error('Your kernel2 must be odd-sized and at least of size 1x1!');
end;
if nargin < 5 || isempty(nrinputchannels)
% Default to RGB channels as separate input channels:
nrinputchannels = 3;
end
if nargin < 6 || isempty(nroutchannels)
% Default to output of filtered RGB channels:
nroutchannels = 3;
end
if nargin < 7 || isempty(debug);
% No debug mode provided: Disable debug output by default:
debug = 0;
end;
if nargin < 8
shadertype = [];
end
if nargin < 4 || isempty(opname)
opname = sprintf('2D separable convolution kernel pair: w x h = %i by %i, nrin=%i, nrout=%i.', kernelw, kernelh, nrinputchannels, nroutchannels);
end
% Input parsing done. Call helper routine for creation of shaders and
% optional lookup textures:
[shader configstring] = EXPCreateStatic2DConvolutionShader(kernel1, nrinputchannels, nroutchannels, debug, shadertype);
% Count number of slots in proxy:
count = CountSlotsInGLOperator(gloperator);
% If its non-zero, then some processing will already take place before our
% shader, so we need to perform a FBO ping-pong step:
if count > 0
Screen('HookFunction', gloperator, 'AppendBuiltin', 'UserDefinedBlit', 'Builtin:FlipFBOs', '');
end
if debug > 3
fprintf('Add2DSeparableConvolutionToGLOperator: Switching operator to dual-pass/multi-pass mode.\n');
end
if count == 0
% Count was 0, so its now two: Change operator to be at least dual-pass capable:
Screen('HookFunction', gloperator, 'ImagingMode', mor(kPsychNeedDualPass, Screen('HookFunction', gloperator, 'ImagingMode')));
else
% Change operator to be multi-pass capable:
Screen('HookFunction', gloperator, 'ImagingMode', mor(kPsychNeedMultiPass, Screen('HookFunction', gloperator, 'ImagingMode')));
end
% Add shader to user defined blit chain of the proxy:
Screen('HookFunction', gloperator, 'AppendShader', 'UserDefinedBlit', opname, shader, configstring);
% Need a ping-pong op for second convolution pass:
Screen('HookFunction', gloperator, 'AppendBuiltin', 'UserDefinedBlit', 'Builtin:FlipFBOs', '');
% Build and add the 2nd shader:
[shader configstring] = EXPCreateStatic2DConvolutionShader(kernel2, nrinputchannels, nroutchannels, debug, shadertype);
Screen('HookFunction', gloperator, 'AppendShader', 'UserDefinedBlit', opname, shader, configstring);
% Check if gloperator is already configured for float precision. If
% not, then assign 32bpc float request. We need this precision for
% dual-pass convolution:
if bitand(Screen('HookFunction', gloperator, 'ImagingMode'), mor(kPsychNeed16BPCFloat, kPsychNeed32BPCFloat)) == 0
% Not yet set. Choose highest precision:
Screen('HookFunction', gloperator, 'ImagingMode', mor(kPsychNeed32BPCFloat, Screen('HookFunction', gloperator, 'ImagingMode')));
if debug > 3
fprintf('Add2DSeparableConvolutionToGLOperator: Increasing precision of operator to 32bpc float.\n');
end
end
% Done.
return;
|