@@ -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-crop " , bitmapCrop) )
161
162
self . define ( Procedure ( " bitmap-blur " , bitmapBlur) )
162
163
self . define ( Procedure ( " save-bitmap " , saveBitmap) )
163
164
self . define ( Procedure ( " bitmap->bytevector " , bitmapToBytevector) )
@@ -946,7 +947,33 @@ public final class DrawingLibrary: NativeLibrary {
946
947
return . object( NativeImage ( nsimage) )
947
948
}
948
949
949
- private lazy var coreImageContext = CIContext ( )
950
+ private func bitmapCrop( bitmap: Expr , rect: Expr ) throws -> Expr {
951
+ let nsImage = try self . image ( from: bitmap)
952
+ var pixels = nsImage. size
953
+ for repr in nsImage. representations {
954
+ if let bm = repr as? NSBitmapImageRep , bm. size. width > 0.0 {
955
+ pixels. width = CGFloat ( bm. pixelsWide)
956
+ pixels. height = CGFloat ( bm. pixelsHigh)
957
+ }
958
+ }
959
+ guard case . pair( . pair( . flonum( let x) , . flonum( let y) ) ,
960
+ . pair( . flonum( let w) , . flonum( let h) ) ) = rect else {
961
+ throw RuntimeError . eval ( . invalidRect, rect)
962
+ }
963
+ let bounds = NSRect ( x: x, y: y, width: w, height: h)
964
+ . intersection ( NSRect ( x: 0 , y: 0 , width: pixels. width, height: pixels. height) )
965
+ guard bounds. width > 0 , bounds. height > 0 else {
966
+ return . false
967
+ }
968
+ let size = CGSize ( width: nsImage. size. width * bounds. width / pixels. width,
969
+ height: nsImage. size. height * bounds. height / pixels. height)
970
+ guard let cgImage = nsImage. cgImage ( forProposedRect: nil , context: nil , hints: nil ) else {
971
+ return . false
972
+ }
973
+ let res = NSImage ( size: size)
974
+ res. addRepresentation ( NSBitmapImageRep ( ciImage: CIImage ( cgImage: cgImage) . cropped ( to: bounds) ) )
975
+ return . object( NativeImage ( res) )
976
+ }
950
977
951
978
private func bitmapBlur( bitmap: Expr , radius: Expr ) throws -> Expr {
952
979
let nsImage = try self . image ( from: bitmap)
@@ -960,11 +987,10 @@ public final class DrawingLibrary: NativeLibrary {
960
987
" CIGaussianBlur " ,
961
988
parameters: [ kCIInputRadiusKey: radius ] )
962
989
. 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) ) )
990
+ let bitmap = NSBitmapImageRep ( ciImage: blurredImage)
991
+ let res = NSImage ( size: nsImage. size)
992
+ res. addRepresentation ( bitmap)
993
+ return . object( NativeImage ( res) )
968
994
}
969
995
970
996
private func saveBitmap( filename: Expr , bitmap: Expr , format: Expr ) throws -> Expr {
0 commit comments