@akylas/nativescript-app-utils 2.1.4 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [2.1.5](https://github.com/akylas/nativescript-app-utils/compare/v2.1.4...v2.1.5) (2024-11-08)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **ios:** getImageSize fix ([fff82d7](https://github.com/akylas/nativescript-app-utils/commit/fff82d79420ecffac199934905bf00683c466913))
|
|
11
|
+
|
|
6
12
|
## [2.1.4](https://github.com/akylas/nativescript-app-utils/compare/v2.1.3...v2.1.4) (2024-10-20)
|
|
7
13
|
|
|
8
14
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akylas/nativescript-app-utils",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
4
|
"description": "Provides API for changing the styles of SystemUI (StatusBar, NavigationBar...) on iOS.",
|
|
5
5
|
"main": "index",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"bugs": {
|
|
64
64
|
"url": "https://github.com/akylas/nativescript-app-utils/issues"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "4653c117a97d1999227bc500ec7ed0783a2e3601"
|
|
67
67
|
}
|
|
@@ -1,419 +1,231 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import java.io.FileNotFoundException
|
|
16
|
-
import java.io.IOException
|
|
17
|
-
import kotlin.math.floor
|
|
18
|
-
import kotlin.math.max
|
|
19
|
-
import kotlin.math.min
|
|
20
|
-
import kotlin.concurrent.thread
|
|
21
|
-
|
|
22
|
-
import com.nativescript.apputils.FunctionCallback
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* This class contains helper functions for processing images
|
|
26
|
-
*
|
|
27
|
-
* @constructor creates image util
|
|
28
|
-
*/
|
|
29
|
-
class ImageUtils {
|
|
30
|
-
|
|
31
|
-
class LoadImageOptions {
|
|
32
|
-
var options: JSONObject? = null
|
|
33
|
-
var sourceWidth = 0
|
|
34
|
-
var sourceHeight = 0
|
|
35
|
-
var width = 0
|
|
36
|
-
var maxWidth = 0
|
|
37
|
-
var height = 0
|
|
38
|
-
var maxHeight = 0
|
|
39
|
-
var keepAspectRatio = true
|
|
40
|
-
var autoScaleFactor = true
|
|
41
|
-
|
|
42
|
-
fun initWithJSON(jsonOpts: JSONObject)
|
|
43
|
-
{
|
|
44
|
-
options = jsonOpts
|
|
45
|
-
if (jsonOpts.has("resizeThreshold")) {
|
|
46
|
-
maxWidth = jsonOpts.optInt("resizeThreshold", maxWidth)
|
|
47
|
-
maxHeight = maxWidth
|
|
48
|
-
} else if (jsonOpts.has("maxSize")) {
|
|
49
|
-
maxWidth = jsonOpts.optInt("maxSize", maxWidth)
|
|
50
|
-
maxHeight = maxWidth
|
|
51
|
-
}
|
|
52
|
-
if (jsonOpts.has("width")) {
|
|
53
|
-
width = jsonOpts.optInt("width", width)
|
|
54
|
-
} else if (jsonOpts.has("maxWidth")) {
|
|
55
|
-
maxWidth = jsonOpts.optInt("maxWidth", maxWidth)
|
|
56
|
-
}
|
|
57
|
-
if (jsonOpts.has("height")) {
|
|
58
|
-
height = jsonOpts.optInt("height", height)
|
|
59
|
-
} else if (jsonOpts.has("maxHeight")) {
|
|
60
|
-
maxHeight = jsonOpts.optInt("maxHeight", maxHeight)
|
|
61
|
-
}
|
|
62
|
-
sourceWidth = jsonOpts.optInt("sourceWidth", sourceWidth)
|
|
63
|
-
sourceHeight = jsonOpts.optInt("sourceHeight", sourceHeight)
|
|
64
|
-
keepAspectRatio = jsonOpts.optBoolean("keepAspectRatio", keepAspectRatio)
|
|
65
|
-
autoScaleFactor = jsonOpts.optBoolean("autoScaleFactor", autoScaleFactor)
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
constructor(options: String?) {
|
|
69
|
-
if (options != null) {
|
|
70
|
-
try {
|
|
71
|
-
val jsonOpts = JSONObject(options)
|
|
72
|
-
initWithJSON(jsonOpts)
|
|
73
|
-
} catch (ignored: JSONException) {
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
constructor(jsonOpts: JSONObject) {
|
|
78
|
-
initWithJSON(jsonOpts)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
var resizeThreshold = 0
|
|
82
|
-
get() { return min(maxWidth, maxHeight)}
|
|
83
|
-
|
|
84
|
-
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
extension UIImage.Orientation {
|
|
5
|
+
init(_ cgOrientation: CGImagePropertyOrientation) {
|
|
6
|
+
switch cgOrientation {
|
|
7
|
+
case .up: self = .up
|
|
8
|
+
case .upMirrored: self = .upMirrored
|
|
9
|
+
case .down: self = .down
|
|
10
|
+
case .downMirrored: self = .downMirrored
|
|
11
|
+
case .left: self = .left
|
|
12
|
+
case .leftMirrored: self = .leftMirrored
|
|
13
|
+
case .right: self = .right
|
|
14
|
+
case .rightMirrored: self = .rightMirrored
|
|
85
15
|
}
|
|
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
|
-
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
@objcMembers
|
|
19
|
+
@objc(ImageUtils)
|
|
20
|
+
class ImageUtils : NSObject {
|
|
21
|
+
|
|
22
|
+
static func toJSON(_ str: String?) -> NSDictionary? {
|
|
23
|
+
guard let data = str?.data(using: .utf8, allowLossyConversion: false) else { return nil }
|
|
24
|
+
return try? (JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSDictionary?)
|
|
25
|
+
}
|
|
26
|
+
class LoadImageOptions {
|
|
27
|
+
var width = 0.0
|
|
28
|
+
var maxWidth = 0.0
|
|
29
|
+
var height = 0.0
|
|
30
|
+
var maxHeight = 0.0
|
|
31
|
+
var keepAspectRatio = true
|
|
32
|
+
var autoScaleFactor = true
|
|
33
|
+
|
|
34
|
+
func initWithJSONOptions(_ jsonOpts:NSDictionary?){
|
|
35
|
+
if let jsonOpts = jsonOpts {
|
|
36
|
+
if ((jsonOpts["resizeThreshold"]) != nil) {
|
|
37
|
+
maxWidth = jsonOpts["resizeThreshold"] as! Double
|
|
38
|
+
maxHeight = maxWidth
|
|
39
|
+
} else if ((jsonOpts["maxSize"]) != nil) {
|
|
40
|
+
maxWidth = jsonOpts["maxSize"] as! Double
|
|
41
|
+
maxHeight = maxWidth
|
|
42
|
+
}
|
|
43
|
+
if ((jsonOpts["width"]) != nil) {
|
|
44
|
+
width = jsonOpts["width"] as! Double
|
|
45
|
+
} else if ((jsonOpts["maxWidth"]) != nil) {
|
|
46
|
+
maxWidth = jsonOpts["maxWidth"] as! Double
|
|
47
|
+
}
|
|
48
|
+
if ((jsonOpts["height"]) != nil) {
|
|
49
|
+
height = jsonOpts["height"] as! Double
|
|
50
|
+
} else if ((jsonOpts["maxHeight"]) != nil) {
|
|
51
|
+
maxHeight = jsonOpts["maxHeight"] as! Double
|
|
52
|
+
}
|
|
53
|
+
if ((jsonOpts["keepAspectRatio"]) != nil) {
|
|
54
|
+
keepAspectRatio = jsonOpts["keepAspectRatio"] as! Bool
|
|
55
|
+
}
|
|
56
|
+
if ((jsonOpts["autoScaleFactor"]) != nil) {
|
|
57
|
+
autoScaleFactor = jsonOpts["autoScaleFactor"] as! Bool
|
|
58
|
+
}
|
|
59
|
+
}
|
|
123
60
|
}
|
|
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
|
-
BitmapFactory.decodeFileDescriptor(pfd!!.fileDescriptor, null, bitmapOptions)
|
|
293
|
-
} else {
|
|
294
|
-
BitmapFactory.decodeFile(src, bitmapOptions)
|
|
295
|
-
}
|
|
296
|
-
val rotationAngle: Int
|
|
297
|
-
if (pfd != null) {
|
|
298
|
-
rotationAngle = calculateAngleFromFileDescriptor(pfd.fileDescriptor)
|
|
299
|
-
closePfd(pfd)
|
|
300
|
-
} else {
|
|
301
|
-
rotationAngle = calculateAngleFromFile(src)
|
|
302
|
-
}
|
|
303
|
-
return intArrayOf(bitmapOptions.outWidth, bitmapOptions.outHeight, rotationAngle)
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
fun readBitmapFromFileSync(context: Context, src: String, options: LoadImageOptions?, sourceSize:Pair<Int, Int>?): Bitmap? {
|
|
307
|
-
// val start = System.currentTimeMillis()
|
|
308
|
-
var sourceSize = sourceSize
|
|
309
|
-
if (sourceSize == null && options?.sourceWidth != 0 && options?.sourceHeight != 0) {
|
|
310
|
-
sourceSize = Pair(options!!.sourceWidth, options!!.sourceHeight)
|
|
311
|
-
}
|
|
312
|
-
var bitmap: Bitmap?
|
|
313
|
-
val bitmapOptions = BitmapFactory.Options()
|
|
314
|
-
var pfd: ParcelFileDescriptor? = null
|
|
315
|
-
if (src.startsWith("content://")) {
|
|
316
|
-
val uri = Uri.parse(src)
|
|
317
|
-
val resolver: ContentResolver = context.getContentResolver()
|
|
318
|
-
pfd = try {
|
|
319
|
-
resolver.openFileDescriptor(uri, "r")
|
|
320
|
-
} catch (e: FileNotFoundException) {
|
|
321
|
-
closePfd(pfd)
|
|
322
|
-
throw e;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
if (sourceSize == null) {
|
|
326
|
-
bitmapOptions.inJustDecodeBounds = true
|
|
327
|
-
|
|
328
|
-
if (pfd != null) {
|
|
329
|
-
BitmapFactory.decodeFileDescriptor(pfd!!.fileDescriptor, null, bitmapOptions)
|
|
330
|
-
} else {
|
|
331
|
-
BitmapFactory.decodeFile(src, bitmapOptions)
|
|
332
|
-
}
|
|
333
|
-
sourceSize = Pair(bitmapOptions.outWidth, bitmapOptions.outHeight)
|
|
334
|
-
}
|
|
335
|
-
val opts = ImageAssetOptions(sourceSize, options)
|
|
336
|
-
|
|
337
|
-
val (first, second) = getRequestedImageSize(sourceSize, opts)
|
|
338
|
-
val sampleSize: Int = calculateInSampleSize(
|
|
339
|
-
sourceSize.first, sourceSize.second,
|
|
340
|
-
first,
|
|
341
|
-
second
|
|
342
|
-
)
|
|
343
|
-
val finalBitmapOptions = BitmapFactory.Options()
|
|
344
|
-
finalBitmapOptions.inSampleSize = sampleSize
|
|
345
|
-
if (sampleSize != 1) {
|
|
346
|
-
finalBitmapOptions.inScaled = true;
|
|
347
|
-
finalBitmapOptions.inDensity = sourceSize.first;
|
|
348
|
-
finalBitmapOptions.inTargetDensity = first * sampleSize;
|
|
349
|
-
} else {
|
|
350
|
-
finalBitmapOptions.inScaled = false;
|
|
351
|
-
}
|
|
352
|
-
// read as minimum bitmap as possible (slightly bigger than the requested size)
|
|
353
|
-
bitmap = if (pfd != null) {
|
|
354
|
-
BitmapFactory.decodeFileDescriptor(pfd.fileDescriptor, null, finalBitmapOptions)
|
|
355
|
-
} else {
|
|
356
|
-
BitmapFactory.decodeFile(src, finalBitmapOptions)
|
|
357
|
-
}
|
|
358
|
-
// Log.d("ImageAnalysis", "readBitmapFromFile in ${System.currentTimeMillis() - start} ms")
|
|
359
|
-
if (bitmap != null) {
|
|
360
|
-
val rotationAngle: Int
|
|
361
|
-
if (pfd != null) {
|
|
362
|
-
rotationAngle = calculateAngleFromFileDescriptor(pfd.fileDescriptor)
|
|
363
|
-
closePfd(pfd)
|
|
364
|
-
} else {
|
|
365
|
-
rotationAngle = calculateAngleFromFile(src)
|
|
366
|
-
}
|
|
367
|
-
// if (first !== bitmap.getWidth() || second !== bitmap.getHeight() || rotationAngle != 0) {
|
|
368
|
-
//
|
|
369
|
-
// val matrix = Matrix()
|
|
370
|
-
// if (first !== bitmap.getWidth() || second !== bitmap.getHeight()) {
|
|
371
|
-
// val scale = first.toFloat() / bitmap.width
|
|
372
|
-
// matrix.postScale(scale, scale)
|
|
373
|
-
// }
|
|
374
|
-
// if (rotationAngle != 0) {
|
|
375
|
-
// matrix.postRotate(rotationAngle.toFloat())
|
|
376
|
-
// }
|
|
377
|
-
// bitmap = Bitmap.createBitmap(
|
|
378
|
-
// bitmap,
|
|
379
|
-
// 0,
|
|
380
|
-
// 0,
|
|
381
|
-
// bitmap.getWidth(),
|
|
382
|
-
// bitmap.getHeight(),
|
|
383
|
-
// matrix,
|
|
384
|
-
// false
|
|
385
|
-
// )
|
|
386
|
-
// }
|
|
387
|
-
|
|
388
|
-
if (rotationAngle != 0) {
|
|
389
|
-
val matrix = Matrix()
|
|
390
|
-
matrix.postRotate(rotationAngle.toFloat())
|
|
391
|
-
bitmap = Bitmap.createBitmap(
|
|
392
|
-
bitmap,
|
|
393
|
-
0,
|
|
394
|
-
0,
|
|
395
|
-
bitmap.getWidth(),
|
|
396
|
-
bitmap.getHeight(),
|
|
397
|
-
matrix,
|
|
398
|
-
true
|
|
399
|
-
)
|
|
400
|
-
}
|
|
401
|
-
// Log.d("ImageAnalysis", "readBitmapFromFile2 in ${System.currentTimeMillis() - start} ms")
|
|
402
|
-
}
|
|
403
|
-
return bitmap
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
fun readBitmapFromFileSync(context: Context, src: String, opts: String?): Bitmap? {
|
|
407
|
-
return readBitmapFromFileSync(context, src, LoadImageOptions(opts), null)
|
|
408
|
-
}
|
|
409
|
-
fun readBitmapFromFile(context: Context, src: String, callback: FunctionCallback, opts: String?) {
|
|
410
|
-
thread(start = true) {
|
|
411
|
-
try {
|
|
412
|
-
callback.onResult(null, readBitmapFromFileSync(context, src, opts))
|
|
413
|
-
} catch (e: Exception) {
|
|
414
|
-
callback.onResult(e, null)
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
}
|
|
61
|
+
|
|
62
|
+
init(_ optionsStr:String?) {
|
|
63
|
+
initWithJSONOptions(toJSON(optionsStr))
|
|
64
|
+
}
|
|
65
|
+
init( jsonOpts:NSDictionary?) {
|
|
66
|
+
initWithJSONOptions(jsonOpts)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
class ImageAssetOptions {
|
|
70
|
+
var width = 0.0
|
|
71
|
+
var height = 0.0
|
|
72
|
+
var keepAspectRatio = true
|
|
73
|
+
var autoScaleFactor = true
|
|
74
|
+
init (_ size: CGSize, options: LoadImageOptions?) {
|
|
75
|
+
width = size.width
|
|
76
|
+
height = size.height
|
|
77
|
+
if (options != nil) {
|
|
78
|
+
if (options!.width > 0) {
|
|
79
|
+
width = options!.width
|
|
80
|
+
}
|
|
81
|
+
if (options!.height > 0) {
|
|
82
|
+
height = options!.height
|
|
83
|
+
}
|
|
84
|
+
if (options!.maxWidth > 0) {
|
|
85
|
+
width = min(
|
|
86
|
+
width,
|
|
87
|
+
options!.maxWidth
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
if (options!.maxHeight > 0) {
|
|
91
|
+
height = min(
|
|
92
|
+
height,
|
|
93
|
+
options!.maxHeight
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
keepAspectRatio = options!.keepAspectRatio
|
|
97
|
+
autoScaleFactor = options!.autoScaleFactor
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
static func getAspectSafeDimensions(
|
|
103
|
+
_ sourceWidth: Double,
|
|
104
|
+
_ sourceHeight: Double,
|
|
105
|
+
_ reqWidth: Double,
|
|
106
|
+
_ reqHeight: Double
|
|
107
|
+
) -> CGSize {
|
|
108
|
+
let widthCoef = sourceWidth / reqWidth
|
|
109
|
+
let heightCoef = sourceHeight / reqHeight
|
|
110
|
+
let aspectCoef = max(widthCoef, heightCoef)
|
|
111
|
+
return CGSize(width: floor((sourceWidth / aspectCoef)), height: floor((sourceHeight / aspectCoef)))
|
|
112
|
+
}
|
|
113
|
+
static func getRequestedImageSize(_ size: CGSize, _ options: ImageAssetOptions) -> CGSize {
|
|
114
|
+
var reqWidth = options.width
|
|
115
|
+
if (reqWidth <= 0) {
|
|
116
|
+
reqWidth = size.width
|
|
117
|
+
}
|
|
118
|
+
var reqHeight = options.height
|
|
119
|
+
if (reqHeight <= 0) {
|
|
120
|
+
reqHeight = size.height
|
|
121
|
+
}
|
|
122
|
+
if (options.keepAspectRatio) {
|
|
123
|
+
let size2 = getAspectSafeDimensions(
|
|
124
|
+
size.width,
|
|
125
|
+
size.height,
|
|
126
|
+
reqWidth,
|
|
127
|
+
reqHeight
|
|
128
|
+
)
|
|
129
|
+
reqWidth = size2.width
|
|
130
|
+
reqHeight = size2.height
|
|
131
|
+
}
|
|
132
|
+
return CGSize(width: reqWidth, height: reqHeight)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// this scales an image but also return the image "rotated"
|
|
136
|
+
// based on imageOrientation
|
|
137
|
+
static func scaleImage(_ image: UIImage, _ scaledImageSize: CGSize) -> UIImage? {
|
|
138
|
+
// Create a graphics context
|
|
139
|
+
UIGraphicsBeginImageContextWithOptions(scaledImageSize, false, image.scale)
|
|
140
|
+
// Draw the image in the new size
|
|
141
|
+
image.draw(in: CGRect(
|
|
142
|
+
origin: .zero,
|
|
143
|
+
size: scaledImageSize
|
|
144
|
+
))
|
|
145
|
+
// Get the resized, scaled, and rotated image from the context
|
|
146
|
+
let resizedScaledRotatedImage = UIGraphicsGetImageFromCurrentImageContext()
|
|
147
|
+
|
|
148
|
+
// End the graphics context
|
|
149
|
+
UIGraphicsEndImageContext()
|
|
150
|
+
|
|
151
|
+
return resizedScaledRotatedImage
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
static func getImageSize(_ src: String) -> Dictionary<String, Any>? {
|
|
155
|
+
let url = NSURL.fileURL(withPath: src)
|
|
156
|
+
let imageSource = CGImageSourceCreateWithURL(url as CFURL, nil);
|
|
157
|
+
if (imageSource == nil) {
|
|
158
|
+
// Error loading image
|
|
159
|
+
return nil;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
let options = [kCGImageSourceShouldCache:false];
|
|
163
|
+
let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource!, 0, options as CFDictionary) as! [NSString: Any]? ;
|
|
164
|
+
var result: Dictionary<String, Any>?;
|
|
165
|
+
if (imageProperties != nil) {
|
|
166
|
+
let width = imageProperties![kCGImagePropertyPixelWidth] as! Double;
|
|
167
|
+
let height = imageProperties![kCGImagePropertyPixelHeight] as! Double;
|
|
168
|
+
var degrees: Int = 0
|
|
169
|
+
let orientation = imageProperties![kCGImagePropertyOrientation];
|
|
170
|
+
if (orientation != nil) {
|
|
171
|
+
let uiOrientation = UIImage.Orientation.init(CGImagePropertyOrientation(rawValue: UInt32(orientation as! Int))!);
|
|
172
|
+
switch uiOrientation {
|
|
173
|
+
case .down, .downMirrored:
|
|
174
|
+
degrees = 180
|
|
175
|
+
break
|
|
176
|
+
case .right, .rightMirrored:
|
|
177
|
+
degrees = -90
|
|
178
|
+
break
|
|
179
|
+
case .left, .leftMirrored:
|
|
180
|
+
degrees = 90
|
|
181
|
+
break
|
|
182
|
+
default:
|
|
183
|
+
degrees = 0
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
result = ["width": width, "height": height, "rotation":degrees];
|
|
188
|
+
}
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
static func readImageFromFileSync(_ src: String, options: NSDictionary?) -> UIImage? {
|
|
194
|
+
let image = UIImage(contentsOfFile: src)
|
|
195
|
+
if let image {
|
|
196
|
+
let size = image.size
|
|
197
|
+
let imageOrientation = image.imageOrientation
|
|
198
|
+
let loadImageOptions = LoadImageOptions(jsonOpts: options)
|
|
199
|
+
let opts = ImageAssetOptions(size, options: loadImageOptions)
|
|
200
|
+
let requestedSize = getRequestedImageSize(size, opts)
|
|
201
|
+
var result: UIImage? = image
|
|
202
|
+
if (requestedSize.width != size.width || requestedSize.height != size.height || imageOrientation != .up) {
|
|
203
|
+
result = scaleImage(image, requestedSize )
|
|
204
|
+
}
|
|
205
|
+
if (options?["jpegQuality"] != nil) {
|
|
206
|
+
result = UIImage.init(data: result!.jpegData(compressionQuality: CGFloat((options!["jpegQuality"] as! Int)) / 100.0)!)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return result
|
|
210
|
+
}
|
|
211
|
+
return nil
|
|
212
|
+
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
static func readImageFromFileSync(_ src: String, _ stringOptions: String?) -> UIImage? {
|
|
216
|
+
let options = toJSON(stringOptions)
|
|
217
|
+
return readImageFromFileSync(src, options: options)
|
|
218
|
+
}
|
|
219
|
+
static func readImageFromFile(_ src: String, _ delegate: NCompletionDelegate?, _ stringOptions: String?) {
|
|
220
|
+
DispatchQueue.global(qos: .userInitiated).async {
|
|
221
|
+
let options = toJSON(stringOptions)
|
|
222
|
+
// do {
|
|
223
|
+
delegate?.onComplete(readImageFromFileSync(src, stringOptions) as NSObject?, error: nil)
|
|
224
|
+
|
|
225
|
+
// } catch {
|
|
226
|
+
// delegate?.onComplete(readImageFromFileSync(src, stringOptions) as NSObject?, error: error as NSError?)
|
|
227
|
+
//
|
|
228
|
+
// }
|
|
418
229
|
}
|
|
419
|
-
}
|
|
230
|
+
}
|
|
231
|
+
}
|