The ConvolutionKernel convolves its first input with a second, filter input. It has no parameters.
//Warning: connecting a large image to the filter input will cause the kernel to run very slowly!
//If running on a GPU connected to a display, this will cause problems if the time taken to
//execute the kernel is longer than your operating system allows. Use with caution!
kernel ConvolutionKernel : public ImageComputationKernel<ePixelWise>
{
Image<eRead, eAccessRanged2D, eEdgeClamped> src;
Image<eRead, eAccessRandom> filter;
Image<eWrite> dst;
local:
int2 _filterOffset;
void init()
{
//Get the size of the filter input and store the radius.
int2 filterRadius(filter.bounds.width()/2, filter.bounds.height()/2);
//Store the offset of the bottom-left corner of the filter image
//from the current pixel:
_filterOffset[0] = filter.bounds.x1 - filterRadius[0];
_filterOffset[1] = filter.bounds.y1 - filterRadius[1];
//Set up the access for the src image
src.setRange(-filterRadius[0], -filterRadius[1], filterRadius[0], filterRadius[1]);
}
void process() {
SampleType(src) valueSum(0);
ValueType(filter) filterSum(0);
//Iterate over the filter image
for(int j = filter.bounds.y1; j < filter.bounds.y2; j++) {
for(int i = filter.bounds.x1; i < filter.bounds.x2; i++) {
//Get the filter value
ValueType(filter) filterVal = filter(i, j, 0);
//Multiply the src value by the corresponding filter weight and accumulate
valueSum += filterVal * src(i + _filterOffset[0], j + _filterOffset[1]);
//Update the filter sum with the current filter value
filterSum += filterVal;
}
}
//Normalise the value sum, avoiding division by zero
if (filterSum != 0)
valueSum /= filterSum;
dst() = valueSum;
}
};