@@ -158,6 +158,7 @@ public final class DrawingLibrary: NativeLibrary {
158
158
self . define ( Procedure ( " bitmap-exif-data " , bitmapExifData) )
159
159
self . define ( Procedure ( " set-bitmap-exif-data! " , setBitmapExifData) )
160
160
self . define ( Procedure ( " make-bitmap " , makeBitmap) )
161
+ self . define ( Procedure ( " bitmap-blur " , bitmapBlur) )
161
162
self . define ( Procedure ( " save-bitmap " , saveBitmap) )
162
163
self . define ( Procedure ( " bitmap->bytevector " , bitmapToBytevector) )
163
164
@@ -945,6 +946,27 @@ public final class DrawingLibrary: NativeLibrary {
945
946
return . object( NativeImage ( nsimage) )
946
947
}
947
948
949
+ private lazy var coreImageContext = CIContext ( )
950
+
951
+ private func bitmapBlur( bitmap: Expr , radius: Expr ) throws -> Expr {
952
+ let nsImage = try self . image ( from: bitmap)
953
+ guard let cgImage = nsImage. cgImage ( forProposedRect: nil , context: nil , hints: nil ) else {
954
+ return . false
955
+ }
956
+ let image = CIImage ( cgImage: cgImage)
957
+ let radius = CGFloat ( try radius. asDouble ( coerce: true ) )
958
+ let blurredImage = image. clampedToExtent ( )
959
+ . applyingFilter (
960
+ " CIGaussianBlur " ,
961
+ parameters: [ kCIInputRadiusKey: radius ] )
962
+ . cropped ( to: image. extent)
963
+ guard let res = self . coreImageContext. createCGImage ( blurredImage,
964
+ from: blurredImage. extent) else {
965
+ return . false
966
+ }
967
+ return . object( NativeImage ( NSImage ( cgImage: res, size: blurredImage. extent. size) ) )
968
+ }
969
+
948
970
private func saveBitmap( filename: Expr , bitmap: Expr , format: Expr ) throws -> Expr {
949
971
guard case . symbol( let sym) = format else {
950
972
throw RuntimeError . eval ( . invalidImageFileType, format)
0 commit comments