import benchy, pixie, pixie/internal proc blurSlower*( image: Image, radius: float32, outOfBounds: SomeColor = ColorRGBX() ) = ## Applies Gaussian blur to the image given a radius. let radius = round(radius).int if radius == 0: return let kernel = gaussianKernel(radius) outOfBounds = outOfBounds.asRgbx() proc `*`(sample: ColorRGBX, a: uint32): array[4, uint32] {.inline.} = [ sample.r * a, sample.g * a, sample.b * a, sample.a * a ] template `+=`(values: var array[4, uint32], sample: array[4, uint32]) = values[0] += sample[0] values[1] += sample[1] values[2] += sample[2] values[3] += sample[3] template rgbx(values: array[4, uint32]): ColorRGBX = rgbx( (values[0] div 1024 div 255).uint8, (values[1] div 1024 div 255).uint8, (values[2] div 1024 div 255).uint8, (values[3] div 1024 div 255).uint8 ) # Blur in the X direction. let blurX = newImage(image.width, image.height) for y in 0 ..< image.height: for x in 0 ..< image.width: var values: array[4, uint32] for xx in x - radius ..< min(x + radius, 0): values += outOfBounds * kernel[xx - x + radius] for xx in max(x - radius, 0) .. min(x + radius, image.width - 1): values += image.getRgbaUnsafe(xx, y) * kernel[xx - x + radius] for xx in max(x - radius, image.width) .. x + radius: values += outOfBounds * kernel[xx - x + radius] blurX.setRgbaUnsafe(x, y, rgbx(values)) # Blur in the Y direction. for y in 0 ..< image.height: for x in 0 ..< image.width: var values: array[4, uint32] for yy in y - radius ..< min(y + radius, 0): values += outOfBounds * kernel[yy - y + radius] for yy in max(y - radius, 0) .. min(y + radius, image.height - 1): values += blurX.getRgbaUnsafe(x, yy) * kernel[yy - y + radius] for yy in max(y - radius, image.height) .. y + radius: values += outOfBounds * kernel[yy - y + radius] image.setRgbaUnsafe(x, y, rgbx(values)) let image = newImage(1920, 1080) proc reset() = var path: Path path.rect(100, 100, 1720, 880) image.fillPath(path, rgba(255, 255, 255, 255)) reset() timeIt "blurSlower": image.blurSlower(40) reset() timeIt "blur": image.blur(40)