-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathImageLib.scpt
More file actions
453 lines (367 loc) · 15.5 KB
/
ImageLib.scpt
File metadata and controls
453 lines (367 loc) · 15.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
#@osa-lang:AppleScript
use framework "Foundation"
use framework "AppKit"
use framework "Quartz"
use scripting additions
property NSImage : class "NSImage"
property X_AXIS : 1
property Y_AXIS : 0
(*
Initializes an ILImage script object.
Params:
theTarget (String) - The file path or remote URL to an image.
Returns:
(ILImage) - The newly created image object.
*)
on Image(theTarget)
script ILImage
property target : theTarget
property width : missing value
property height : missing value
property base64data : missing value
property modified : false
(*
Gets the NSImage object representation of the image.
*)
on _getNSImage()
set _NSImage to current application's NSClassFromString("NSImage")
set theImage to missing value
if my modified is true then
set theImageData to current application's NSData's alloc()'s initWithBase64EncodedString:(my base64data) options:0
return current application's NSImage's alloc()'s initWithData:theImageData
end if
if my target starts with "/" then
-- The target is an image file on the disk
return current application's NSImage's alloc()'s initWithContentsOfFile:(my target)
else if my target contains ":" then
-- The target is a remote URL
set theURL to current application's NSURL's URLWithString:(my target)
return current application's NSImage's alloc()'s initWithContentsOfURL:theURL
else if my target is "---" then
return (missing value)
else
error "Cannot create image from " & (my target)
end if
end _getNSImage
(*
Flips the image vertically or horizontally.
Params:
axis (Number) - The axis to flip the image across. One of X_AXIS, Y_AXIS, 0, or 1.
*)
on flip over axis
set theImage to my _getNSImage()
set flippedImage to (current application's NSImage's alloc()'s initWithSize:(theImage's |size|()))
flippedImage's lockFocus()
set transform to current application's NSAffineTransform's alloc()'s init()
if axis is 0 then
(transform's scaleXBy:-1 yBy:1)
(transform's translateXBy:(0 - (my width)) yBy:0)
else if axis is 1 then
(transform's scaleXBy:1 yBy:-1)
(transform's translateXBy:0 yBy:(0 - (my height)))
else
error "Invalid axis."
end if
transform's concat()
set theRect to current application's NSMakeRect(0, 0, my width, my height)
theImage's drawInRect:theRect
flippedImage's unlockFocus()
set flippedImageData to flippedImage's TIFFRepresentation()
set my base64data to (flippedImageData's base64EncodedStringWithOptions:0) as string
set my modified to true
end flip
(*
Rotates the image clockwise by the specified number of degrees.
Informed by https://stackoverflow.com/a/31702419.
Params:
degrees (Number) - The amount to rotate the image.
*)
on rotate by degrees
set theImage to my _getNSImage()
set imageBounds to current application's NSMakeRect(0, 0, my width, my height)
set pathBounds to current application's NSBezierPath's bezierPathWithRect:imageBounds
set theTransform to current application's NSAffineTransform's transform()
theTransform's rotateByDegrees:-degrees
pathBounds's transformUsingAffineTransform:theTransform
set rotatedBounds to current application's NSMakeRect(0, 0, item 1 of item 2 of pathBounds's |bounds|(), item 2 of item 2 of pathBounds's |bounds|())
set rotatedImage to current application's NSImage's alloc()'s initWithSize:(item 2 of rotatedBounds)
set item 1 of imageBounds to {(current application's NSMidX(rotatedBounds)) - (current application's NSWidth(imageBounds)) / 2, (current application's NSMidY(rotatedBounds)) - (current application's NSHeight(imageBounds)) / 2}
set transform to current application's NSAffineTransform's transform()
transform's translateXBy:((item 1 of item 2 of rotatedBounds) / 2) yBy:((item 2 of item 2 of rotatedBounds) / 2)
transform's rotateByDegrees:-degrees
transform's translateXBy:((item 1 of item 2 of rotatedBounds) / -2) yBy:((item 2 of item 2 of rotatedBounds) / -2)
rotatedImage's lockFocus()
transform's concat()
theImage's drawInRect:imageBounds fromRect:(current application's CGRectZero) operation:(current application's NSCompositingOperationCopy) fraction:1.0
rotatedImage's unlockFocus()
set rotatedImageData to rotatedImage's TIFFRepresentation()
set my base64data to (rotatedImageData's base64EncodedStringWithOptions:0) as string
set my width to current application's NSWidth(rotatedBounds)
set my height to current application's NSHeight(rotatedBounds)
set my modified to true
end rotate
(*
Extracts text from the image.
Returns:
({String}) - The list of text items found in the image.
*)
on extractText()
set theImage to my _getNSImage()
set requestHandler to current application's VNImageRequestHandler's alloc()'s initWithData:(theImage's TIFFRepresentation()) options:(current application's NSDictionary's alloc()'s init())
set textRequest to current application's VNRecognizeTextRequest's alloc()'s init()
requestHandler's performRequests:{textRequest} |error|:(missing value)
set textResults to textRequest's results()
set textItems to {}
repeat with observation in textResults
copy (first item in (observation's topCandidates:1))'s |string|() as text to end of textItems
end repeat
return textItems
end extractText
(*
Gets a list of possible classifications for objects in the image.
Params:
confidenceThreshold (Real) - The minimum confidence level of each returned classification.
Returns:
({{identifier: String, confidence: Real}}) - The list of classifications.
*)
on classifications above confidenceThreshold
set theImage to my _getNSImage()
set requestHandler to current application's VNImageRequestHandler's alloc()'s initWithData:(theImage's TIFFRepresentation()) options:(current application's NSDictionary's alloc()'s init())
set classificationRequest to current application's VNClassifyImageRequest's alloc()'s init()
requestHandler's performRequests:{classificationRequest} |error|:(missing value)
set classificationResults to classificationRequest's results()
set classifications to {}
repeat with observation in classificationResults
if observation's confidence() > confidenceThreshold then
copy {identifier:observation's identifier() as text, confidence:observation's confidence() as real} to end of classifications
end if
end repeat
return classifications
end classifications
(*
Gets the payload text of all barcodes, QR codes, etc. in the image.
Returns:
({String}) - The list of payload texts.
*)
on extractPayloads()
set theImage to my _getNSImage()
set requestHandler to current application's VNImageRequestHandler's alloc()'s initWithData:(theImage's TIFFRepresentation()) options:(current application's NSDictionary's alloc()'s init())
set barcodeRequest to current application's VNDetectBarcodesRequest's alloc()'s init()
requestHandler's performRequests:{barcodeRequest} |error|:(missing value)
set barcodeResults to barcodeRequest's results()
set payloads to {}
repeat with observation in barcodeResults
copy (observation's payloadStringValue() as text) to end of payloads
end repeat
return payloads
end extractPayloads
(*
Counts the number of human faces in the image.
Returns:
(Integer) - The number of faces observed in the image.
*)
on countFaces()
set theImage to my _getNSImage()
set requestHandler to current application's VNImageRequestHandler's alloc()'s initWithData:(theImage's TIFFRepresentation()) options:(current application's NSDictionary's alloc()'s init())
set faceRequest to current application's VNDetectFaceRectanglesRequest's alloc()'s init()
requestHandler's performRequests:{faceRequest} |error|:(missing value)
set faceResults to faceRequest's results()
return count of faceResults
end countFaces
(*
Saves the image at the provided file path.
Params:
filePath (String) - The path to save the image at.
fileType (String) - The image type / file extension. One of "png", "jpg", "jpeg", "gif", "bmp", or "tiff".
Returns:
(Boolean) - True if the image was saved successfully.
*)
on save in filePath : (missing value) as fileType : "png"
set theImageData to missing value
if my modified is true then
set theImageData to current application's NSData's alloc()'s initWithBase64EncodedString:(my base64data) options:0
else
set theImage to my _getNSImage()
set theImageData to theImage's TIFFRepresentation()
end if
set theBitmap to current application's NSBitmapImageRep's imageRepWithData:theImageData
if filePath is missing value then
if my target starts with "/" then
set filePath to my target
else
error "Must provide an output destination."
end if
end if
set theType to current application's NSBitmapImageFileTypePNG
ignoring case
if fileType is "jpg" or fileType is "jpeg" then
set theType to current application's NSBitmapImageFileTypeJPEG
else if fileType is "gif" then
set theType to current application's NSBitmapImageFileTypeGIF
else if fileType is "bmp" then
set theType to current application's NSBitmapImageFileTypeBMP
else if fileType is "tiff" then
set theType to current application's NSBitmapImageFileTypeTIFF
end if
end ignoring
set theData to theBitmap's representationUsingType:theType |properties|:(missing value)
set theURL to current application's |NSURL|'s fileURLWithPath:filePath
theData's writeToURL:theURL atomically:true
end save
(*
Opens the image, accounting for any modifications.
Returns:
(Boolean) - True if the image was opened successfully.
*)
on open
set theImageData to missing value
if my modified is true then
set theImageData to current application's NSData's alloc()'s initWithBase64EncodedString:(my base64data) options:0
else
set theImage to my _getNSImage()
set theImageData to theImage's TIFFRepresentation()
end if
set theBitmap to current application's NSBitmapImageRep's imageRepWithData:theImageData
set theData to theBitmap's representationUsingType:(current application's NSBitmapImageFileTypePNG) |properties|:(missing value)
set theTempFile to POSIX path of (current application's NSTemporaryDirectory() as string) & "Image.png"
set theURL to current application's |NSURL|'s fileURLWithPath:theTempFile
theData's writeToURL:theURL atomically:true
set theWorkspace to current application's NSWorkspace's sharedWorkspace()
theWorkspace's openURL:theURL
end open
end script
set theImage to ILImage's _getNSImage()
if theImage is not missing value then
set ILImage's base64data to (theImage's TIFFRepresentation()'s base64EncodedStringWithOptions:0) as string
set ILImage's width to theImage's |size|()'s width()
set ILImage's height to theImage's |size|()'s height()
end if
return ILImage
end Image
(*
Extract texts from an image.
Syn. ILImage's extractText()
Params:
theImage (ILImage) - The image to extract text from.
Returns:
({String}) - The list of text items found in the image.
*)
on extractText from theImage
return theImage's extractText()
end extractText
(*
Gets a list of possible classifications for objects in an image.
Syn. ILImage's classifications above confidenceThreshold
Params:
theImage (ILImage) - The image to get classifications for.
confidenceThreshold (Real) - The minimum confidence level of each returned classification.
Returns:
({{identifier: String, confidence: Real}}) - The list of classifications.
*)
on classifications for theImage above confidenceLevel
return theImage's (classifications above confidenceLevel)
end classifications
(*
Gets the payload text of all barcodes, QR codes, etc. in an image.
Syn. ILImage's extractPayloads()
Params:
theImage (ILImage) - The image to extract payloads from.
Returns:
({String}) - The list of payload texts.
*)
on extractPayloads from theImage
return theImage's extractPayloads()
end extractPayloads
(*
Initializes an ILImage script object from a system symbol.
Params:
symbolName (String) - The name the target system symbol.
pointSize (Number) - The font size of the symbol.
Returns:
(ILImage) - The newly created image object.
*)
on Symbol(symbolName, pointSize)
set imageObj to Image("---")
set theConfig to current application's NSImageSymbolConfiguration's configurationWithPointSize:pointSize weight:(current application's NSFontWeightRegular)
set theImage to current application's NSImage's imageWithSystemSymbolName:symbolName accessibilityDescription:(missing value)
set theImage to theImage's imageWithSymbolConfiguration:theConfig
set imageObj's base64data to (theImage's TIFFRepresentation()'s base64EncodedStringWithOptions:0) as string
set imageObj's width to theImage's |size|()'s width()
set imageObj's height to theImage's |size|()'s height()
set imageObj's modified to true
return imageObj
end Symbol
(*
Creates an ILImage object from data.
Syn. imageFromData:theData
Params:
theData («data», String, NSData) - The data of an image, as an AppleScript or Objective-C data class, or as a base 64 encoded string.
Returns:
(ILImage) - The new image object.
*)
on createImage from theData
if theData is missing value then
error "Data is missing value"
end if
set imageObj to Image("---")
set theImage to missing value
if class of theData is text then
-- The data is a base64 string
set imageObj's base64data to theData
set base64data to current application's NSData's alloc()'s initWithBase64EncodedString:theData options:0
set theImage to current application's NSImage's alloc()'s initWithData:base64data
else
try
if (class of theData as text) contains "picture" then
-- The data is an AppleScript picture
set theTempFile to POSIX path of (current application's NSTemporaryDirectory() as string) & "tmp.data"
set fileRef to open for access theTempFile with write permission
try
write theData to fileRef
close access fileRef
on error
close access fileRef
end try
set theURL to current application's |NSURL|'s fileURLWithPath:theTempFile
set theImage to current application's NSImage's alloc()'s initWithContentsOfFile:theTempFile
set imageObj's base64data to (theImage's TIFFRepresentation()'s base64EncodedStringWithOptions:0) as string
end if
on error err
-- The data is (probably) an NSData object
try
set imageObj's base64data to (theData's base64EncodedStringWithOptions:0) as string
set theImage to current application's NSImage's alloc()'s initWithData:theData
end try
end try
end if
if theImage is missing value then
error "Could not convert data to base 64 string."
end if
set imageObj's modified to true
set imageObj's width to theImage's |size|()'s width()
set imageObj's height to theImage's |size|()'s height()
return imageObj
end createImage
on imageFromData:theData
return my (createImage from theData)
end imageFromData:
(*
Rotates an image clockwise by the specifies number of degrees.
Syn. rotate(theImage, degrees), ILImage's rotate by degrees
Params:
theImage (ILImage) - The image object to rotate.
degrees (Number) - The amount to rotate the image.
*)
on rotatation of theImage by degrees
theImage's (rotate by degrees)
end rotatation
(*
Rotates an image clockwise by the specifies number of degrees.
Syn. rotation of theImage by degrees, ILImage's rotate by degrees
Params:
theImage (ILImage) - The image object to rotate.
degrees (Number) - The amount to rotate the image.
*)
on rotate(theImage, degrees)
theImage's (rotate by degrees)
end rotate