replate-camera 0.4.1 → 0.5.1
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.
|
@@ -1255,63 +1255,107 @@ class ReplateCameraController: NSObject {
|
|
|
1255
1255
|
return context.createCGImage(ciImage, from: ciImage.extent)
|
|
1256
1256
|
}
|
|
1257
1257
|
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
let source = CGImageSourceCreateWithData(imageData as CFData, nil) else {
|
|
1263
|
-
return nil
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
|
|
1267
|
-
let uniqueFilename = "image_\(Date().timeIntervalSince1970).jpg"
|
|
1268
|
-
let fileURL = temporaryDirectoryURL.appendingPathComponent(uniqueFilename)
|
|
1269
|
-
|
|
1270
|
-
guard let imageProperties = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as? [CFString: Any] else {
|
|
1271
|
-
return nil
|
|
1272
|
-
}
|
|
1273
|
-
|
|
1274
|
-
var mutableMetadata = imageProperties
|
|
1275
|
-
mutableMetadata[kCGImagePropertyExifDictionary] = [
|
|
1276
|
-
kCGImagePropertyExifUserComment: cameraTransform
|
|
1277
|
-
]
|
|
1278
|
-
|
|
1279
|
-
guard let destination = CGImageDestinationCreateWithURL(
|
|
1280
|
-
fileURL as CFURL,
|
|
1281
|
-
kUTTypeJPEG,
|
|
1282
|
-
1,
|
|
1283
|
-
nil
|
|
1284
|
-
) else {
|
|
1285
|
-
return nil
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
CGImageDestinationAddImageFromSource(
|
|
1289
|
-
destination,
|
|
1290
|
-
source,
|
|
1291
|
-
0,
|
|
1292
|
-
mutableMetadata as CFDictionary
|
|
1293
|
-
)
|
|
1294
|
-
|
|
1295
|
-
guard CGImageDestinationFinalize(destination) else {
|
|
1296
|
-
return nil
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
return fileURL
|
|
1258
|
+
func saveImageAsJPEG(_ image: UIImage) -> URL? {
|
|
1259
|
+
guard let imageData = image.jpegData(compressionQuality: 1),
|
|
1260
|
+
let source = CGImageSourceCreateWithData(imageData as CFData, nil) else {
|
|
1261
|
+
return nil
|
|
1300
1262
|
}
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1263
|
+
|
|
1264
|
+
let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
|
|
1265
|
+
let uniqueFilename = "image_\(Date().timeIntervalSince1970).jpg"
|
|
1266
|
+
let fileURL = temporaryDirectoryURL.appendingPathComponent(uniqueFilename)
|
|
1267
|
+
|
|
1268
|
+
guard let imageProperties = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as? [CFString: Any] else {
|
|
1269
|
+
return nil
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
var mutableMetadata = imageProperties
|
|
1273
|
+
mutableMetadata[kCGImagePropertyExifDictionary] = [
|
|
1274
|
+
kCGImagePropertyExifUserComment: getTransformJSON(session: ReplateCameraView.arView.session)
|
|
1275
|
+
]
|
|
1276
|
+
|
|
1277
|
+
guard let destination = CGImageDestinationCreateWithURL(
|
|
1278
|
+
fileURL as CFURL,
|
|
1279
|
+
kUTTypeJPEG,
|
|
1280
|
+
1,
|
|
1281
|
+
nil
|
|
1282
|
+
) else {
|
|
1283
|
+
return nil
|
|
1314
1284
|
}
|
|
1285
|
+
|
|
1286
|
+
CGImageDestinationAddImageFromSource(
|
|
1287
|
+
destination,
|
|
1288
|
+
source,
|
|
1289
|
+
0,
|
|
1290
|
+
mutableMetadata as CFDictionary
|
|
1291
|
+
)
|
|
1292
|
+
|
|
1293
|
+
guard CGImageDestinationFinalize(destination) else {
|
|
1294
|
+
return nil
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
return fileURL
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
func getTransformJSON(session: ARSession) -> String {
|
|
1301
|
+
let transform = session.currentFrame?.camera.transform ?? simd_float4x4()
|
|
1302
|
+
// Extract translation
|
|
1303
|
+
let translation = [
|
|
1304
|
+
"x": transform.columns.3.x,
|
|
1305
|
+
"y": transform.columns.3.y,
|
|
1306
|
+
"z": transform.columns.3.z
|
|
1307
|
+
]
|
|
1308
|
+
|
|
1309
|
+
// Extract scale by calculating the length of each column vector
|
|
1310
|
+
let scale = [
|
|
1311
|
+
"x": simd_length(simd_float3(transform.columns.0.x, transform.columns.0.y, transform.columns.0.z)),
|
|
1312
|
+
"y": simd_length(simd_float3(transform.columns.1.x, transform.columns.1.y, transform.columns.1.z)),
|
|
1313
|
+
"z": simd_length(simd_float3(transform.columns.2.x, transform.columns.2.y, transform.columns.2.z))
|
|
1314
|
+
]
|
|
1315
|
+
|
|
1316
|
+
// Extract rotation by normalizing each axis and converting it into a 3x3 rotation matrix
|
|
1317
|
+
let rotationMatrix = simd_float3x3(columns: (
|
|
1318
|
+
simd_float3(transform.columns.0.x / scale["x"]!, transform.columns.0.y / scale["x"]!, transform.columns.0.z / scale["x"]!),
|
|
1319
|
+
simd_float3(transform.columns.1.x / scale["y"]!, transform.columns.1.y / scale["y"]!, transform.columns.1.z / scale["y"]!),
|
|
1320
|
+
simd_float3(transform.columns.2.x / scale["z"]!, transform.columns.2.y / scale["z"]!, transform.columns.2.z / scale["z"]!)
|
|
1321
|
+
))
|
|
1322
|
+
|
|
1323
|
+
// Convert rotation matrix to quaternion
|
|
1324
|
+
let quaternion = simd_quatf(rotationMatrix)
|
|
1325
|
+
let rotation = [
|
|
1326
|
+
"x": quaternion.vector.x,
|
|
1327
|
+
"y": quaternion.vector.y,
|
|
1328
|
+
"z": quaternion.vector.z,
|
|
1329
|
+
"w": quaternion.vector.w
|
|
1330
|
+
]
|
|
1331
|
+
|
|
1332
|
+
// Get the gravity vector from the AR session
|
|
1333
|
+
var gravityVector: [String: Any] = [:]
|
|
1334
|
+
if let currentFrame = session.currentFrame {
|
|
1335
|
+
let gravityEulerAngles = currentFrame.camera.eulerAngles
|
|
1336
|
+
gravityVector = [
|
|
1337
|
+
"x": gravityEulerAngles.x,
|
|
1338
|
+
"y": gravityEulerAngles.y,
|
|
1339
|
+
"z": gravityEulerAngles.z
|
|
1340
|
+
]
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
// Format as JSON
|
|
1344
|
+
let jsonObject: [String: Any] = [
|
|
1345
|
+
"translation": translation,
|
|
1346
|
+
"rotation": rotation,
|
|
1347
|
+
"scale": scale,
|
|
1348
|
+
"gravityVector": gravityVector
|
|
1349
|
+
]
|
|
1350
|
+
|
|
1351
|
+
// Convert dictionary to JSON string
|
|
1352
|
+
if let jsonData = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted),
|
|
1353
|
+
let jsonString = String(data: jsonData, encoding: .utf8) {
|
|
1354
|
+
return jsonString
|
|
1355
|
+
} else {
|
|
1356
|
+
return "{}" // Return empty JSON if conversion fails
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1315
1359
|
}
|
|
1316
1360
|
|
|
1317
1361
|
extension ARView: ARCoachingOverlayViewDelegate {
|