Skip to content

Commit d42a7e2

Browse files
committed
Implement procedure bitmap-crop in (lispkit draw).
1 parent dae836d commit d42a7e2

File tree

3 files changed

+52
-7
lines changed

3 files changed

+52
-7
lines changed

LispKit.xcodeproj/project.pbxproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -2198,7 +2198,7 @@
21982198
CC4385BB20BAB79500055289 /* HTTP.scm */ = {isa = PBXFileReference; lastKnownFileType = text; path = HTTP.scm; sourceTree = "<group>"; };
21992199
CC4385BD20BB5EE200055289 /* Compiler.scm */ = {isa = PBXFileReference; lastKnownFileType = text; path = Compiler.scm; sourceTree = "<group>"; };
22002200
CC44E5B121DECB850009969C /* All.scm */ = {isa = PBXFileReference; lastKnownFileType = text; path = All.scm; sourceTree = "<group>"; };
2201-
CC4575C520F00C4400116F0F /* DrawingLibrary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DrawingLibrary.swift; sourceTree = "<group>"; };
2201+
CC4575C520F00C4400116F0F /* DrawingLibrary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DrawingLibrary.swift; sourceTree = "<group>"; wrapsLines = 0; };
22022202
CC4575C720F00EE000116F0F /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = "<group>"; };
22032203
CC474EB01ED0390200B535E3 /* Queens.scm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Queens.scm; sourceTree = "<group>"; };
22042204
CC474EB21ED08C9700B535E3 /* SRFI134.scm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SRFI134.scm; sourceTree = "<group>"; };

Sources/LispKit/Primitives/DrawingLibrary.swift

+32-6
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ public final class DrawingLibrary: NativeLibrary {
158158
self.define(Procedure("bitmap-exif-data", bitmapExifData))
159159
self.define(Procedure("set-bitmap-exif-data!", setBitmapExifData))
160160
self.define(Procedure("make-bitmap", makeBitmap))
161+
self.define(Procedure("bitmap-crop", bitmapCrop))
161162
self.define(Procedure("bitmap-blur", bitmapBlur))
162163
self.define(Procedure("save-bitmap", saveBitmap))
163164
self.define(Procedure("bitmap->bytevector", bitmapToBytevector))
@@ -946,7 +947,33 @@ public final class DrawingLibrary: NativeLibrary {
946947
return .object(NativeImage(nsimage))
947948
}
948949

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+
}
950977

951978
private func bitmapBlur(bitmap: Expr, radius: Expr) throws -> Expr {
952979
let nsImage = try self.image(from: bitmap)
@@ -960,11 +987,10 @@ public final class DrawingLibrary: NativeLibrary {
960987
"CIGaussianBlur",
961988
parameters: [ kCIInputRadiusKey: radius ])
962989
.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))
968994
}
969995

970996
private func saveBitmap(filename: Expr, bitmap: Expr, format: Expr) throws -> Expr {

Sources/LispKit/Primitives/DrawingLibrary_iOS.swift

+19
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ public final class DrawingLibrary: NativeLibrary {
154154
self.define(Procedure("bitmap-exif-data", bitmapExifData))
155155
// self.define(Procedure("set-bitmap-exif-data!", setBitmapExifData))
156156
self.define(Procedure("make-bitmap", makeBitmap))
157+
self.define(Procedure("bitmap-crop", bitmapCrop))
157158
self.define(Procedure("bitmap-blur", bitmapBlur))
158159
self.define(Procedure("save-bitmap", saveBitmap))
159160
self.define(Procedure("bitmap->bytevector", bitmapToBytevector))
@@ -920,6 +921,24 @@ public final class DrawingLibrary: NativeLibrary {
920921

921922
private lazy var coreImageContext = CIContext()
922923

924+
private func bitmapCrop(bitmap: Expr, rect: Expr) throws -> Expr {
925+
let image = try self.image(from: bitmap)
926+
let pixels = CGSize(width: image.size.width * image.scale,
927+
height: image.size.height * image.scale)
928+
guard case .pair(.pair(.flonum(let x), .flonum(let y)),
929+
.pair(.flonum(let w), .flonum(let h))) = rect else {
930+
throw RuntimeError.eval(.invalidRect,rect)
931+
}
932+
let bounds = CGRect(x: x, y: y, width: w, height: h)
933+
.intersection(CGRect(x: 0, y: 0, width: pixels.width, height: pixels.height))
934+
guard bounds.width > 0, bounds.height > 0,
935+
let newImage = CIImage(image: image)?.cropped(to: bounds),
936+
let res = self.coreImageContext.createCGImage(newImage, from: newImage.extent) else {
937+
return .false
938+
}
939+
return .object(NativeImage(UIImage(cgImage: res, scale: image.scale, orientation: .up)))
940+
}
941+
923942
private func bitmapBlur(bitmap: Expr, radius: Expr) throws -> Expr {
924943
let orig = try self.image(from: bitmap)
925944
guard let image = CIImage(image: orig) else {

0 commit comments

Comments
 (0)