Image processing through a Kernel (Convolution)

The title says it all. I’ve made a function that applies an effect to an Editable image using kernel processing (aka convolution).

I have not really tested it with kernel size above 3x3, but in theory it should work.

local function ImageConvolution(Image: EditableImage, Kernel: {number}) 
	local NewPixelArray = {}
	local CanvasSize = Canvas.Size

	local Width, Height = CanvasSize.X, CanvasSize.Y
	local KernelSize = #Kernel // 2
	local PixelArray = Image:ReadPixels(Vector2.zero, CanvasSize)
	
	for yi = 1, Height do
		for xi = 1, Width do
			local sum = {0, 0, 0, 0}
			
			for kc = -KernelSize, KernelSize do
				for kr = -KernelSize, KernelSize do
					local x = xi + kr
					local y = yi + kc
					
					local mx, my = math.clamp(y, 1, Height), math.clamp(x, 1, Width)
					
					local pixelIndex = ((mx - 1) * Width + my - 1) * 4 + 1
					for i = 1, 4 do
						sum[i] = sum[i] + PixelArray[pixelIndex + i - 1] * Kernel[KernelSize + 1 - kc][KernelSize + 1 - kr]
					end
				end
			end
			
			local resultIndex = ((yi - 1) * Width + xi - 1) * 4 + 1
			for i = 1, 4 do
				NewPixelArray[resultIndex + i - 1] = sum[i]
			end
		end
	end

	Image:WritePixels(Vector2.zero, CanvasSize, NewPixelArray)
end

Feel free to use, edit or distribute on your own behalf.

Have a great day/night

Videos of it in action:




7 Likes

How long do each of these operations take?

at 500x500 resolution it takes around 0.3 seconds for 3x3 kernel.