Skip to content

Commit 13be97c

Browse files
authored
Merge pull request #86 from panter/improve-snapshot-stuff
allow to specify options for image capture
2 parents f89bba4 + 8f2f33e commit 13be97c

File tree

4 files changed

+118
-23
lines changed

4 files changed

+118
-23
lines changed

ARKit.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,14 @@ Object.keys(ARKitManager).forEach(key => {
156156
ARKit[key] = ARKitManager[key];
157157
});
158158

159+
const addDefaultsToSnapShotFunc = funcName => ({
160+
target = 'cameraRoll',
161+
format = 'png',
162+
}) => ARKitManager[funcName]({ target, format });
163+
164+
ARKit.snapshot = addDefaultsToSnapShotFunc('snapshot');
165+
ARKit.snapshotCamera = addDefaultsToSnapShotFunc('snapshotCamera');
166+
159167
ARKit.exportModel = presetId => {
160168
const id = presetId || generateId();
161169
const property = { id };

ios/RCTARKit.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ typedef void (^RCTARKitReject)(NSString *code, NSString *message, NSError *error
5656
- (void)hitTestSceneObjects:(CGPoint)tapPoint resolve:(RCTARKitResolve) resolve reject:(RCTARKitReject)reject;
5757
- (SCNVector3)projectPoint:(SCNVector3)point;
5858
- (float)getCameraDistanceToPoint:(SCNVector3)point;
59-
- (void)snapshot:(RCTARKitResolve)resolve reject:(RCTARKitReject)reject;
60-
- (void)snapshotCamera:(RCTARKitResolve)resolve reject:(RCTARKitReject)reject;
59+
- (UIImage *)getSnaphshot;
60+
- (UIImage *)getSnaphshotCamera;
6161
- (void)focusScene;
6262
- (void)clearScene;
6363
- (NSDictionary *)readCameraPosition;

ios/RCTARKit.m

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -231,40 +231,32 @@ - (void)hitTestSceneObjects:(const CGPoint)tapPoint resolve:(RCTARKitResolve)res
231231
}
232232

233233

234-
- (void)snapshot:(RCTARKitResolve)resolve reject:(RCTARKitReject)reject {
234+
- (UIImage *)getSnaphshot {
235235
UIImage *image = [self.arView snapshot];
236-
// FIXME: I belive this is not the right way. I don't know how to pass 'resolve' to the completionSelector
237-
// If you know how to do it, please PR. Thanks!
238-
_resolve = resolve;
239-
UIImageWriteToSavedPhotosAlbum(image, self, @selector(thisImage:savedInAlbumWithError:ctx:), NULL);
236+
return image;
240237
}
241238

242239

243-
- (void)snapshotCamera:(RCTARKitResolve)resolve reject:(RCTARKitReject)reject {
244240

245-
// thx https://stackoverflow.com/a/8094038/1463534
241+
242+
243+
- (UIImage *)getSnaphsotCamera {
246244
CVPixelBufferRef pixelBuffer = self.arView.session.currentFrame.capturedImage;
247245
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
248-
246+
249247
CIContext *temporaryContext = [CIContext contextWithOptions:nil];
250248
CGImageRef videoImage = [temporaryContext
251249
createCGImage:ciImage
252250
fromRect:CGRectMake(0, 0,
253251
CVPixelBufferGetWidth(pixelBuffer),
254252
CVPixelBufferGetHeight(pixelBuffer))];
255-
253+
256254
UIImage *image = [UIImage imageWithCGImage:videoImage scale: 1.0 orientation:UIImageOrientationRight];
257255
CGImageRelease(videoImage);
258-
_resolve = resolve;
259-
UIImageWriteToSavedPhotosAlbum(image, self, @selector(thisImage:savedInAlbumWithError:ctx:), NULL);
256+
return image;
260257
}
261258

262-
- (void)thisImage:(UIImage *)image savedInAlbumWithError:(NSError *)error ctx:(void *)ctx {
263-
if (error) {
264-
} else {
265-
_resolve(@{ @"success": @(YES) });
266-
}
267-
}
259+
268260

269261

270262

ios/RCTARKitManager.m

Lines changed: 99 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#import "RCTARKitManager.h"
1010
#import "RCTARKit.h"
1111
#import "RCTARKitNodes.h"
12+
#import <UIKit/UIKit.h>
13+
#import <Photos/Photos.h>
1214

1315
@implementation RCTARKitManager
1416

@@ -95,12 +97,104 @@ - (NSDictionary *)constantsToExport
9597

9698

9799

98-
RCT_EXPORT_METHOD(snapshot:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
99-
[[ARKit sharedInstance] snapshot:resolve reject:reject];
100+
- (NSString *)getAssetUrl:(NSString *)localID {
101+
// thx https://stackoverflow.com/a/34788748/1463534
102+
// heck, objective c is such a mess
103+
NSString * assetID = [localID stringByReplacingOccurrencesOfString:@"/.*" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [localID length])];
104+
NSString * ext = @"JPG";
105+
NSString * assetURLStr = [NSString stringWithFormat:@"assets-library://asset/asset.%@?id=%@&ext=%@", ext, assetID, ext];
106+
return assetURLStr;
100107
}
101108

102-
RCT_EXPORT_METHOD(snapshotCamera:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
103-
[[ARKit sharedInstance] snapshotCamera:resolve reject:reject];
109+
- (void)storeImageInPhotoAlbum:(UIImage *)image reject:(RCTPromiseRejectBlock)reject resolve:(RCTPromiseResolveBlock)resolve {
110+
__block PHObjectPlaceholder *placeholder;
111+
112+
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
113+
PHAssetChangeRequest* createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
114+
placeholder = [createAssetRequest placeholderForCreatedAsset];
115+
116+
} completionHandler:^(BOOL success, NSError *error) {
117+
if (success)
118+
{
119+
120+
NSString * localID = placeholder.localIdentifier;
121+
122+
NSString * assetURLStr = [self getAssetUrl:localID];
123+
124+
resolve(@{@"url": assetURLStr, @"width":@(image.size.width), @"height": @(image.size.height)});
125+
}
126+
else
127+
{
128+
reject(@"snapshot_error", @"Could not store snapshot", error);
129+
}
130+
}];
131+
}
132+
133+
134+
- (void)storeImageInDirectory:(UIImage *)image directory:(NSString *)directory format:(NSString *)format reject:(RCTPromiseRejectBlock)reject resolve:(RCTPromiseResolveBlock)resolve {
135+
NSData *data;
136+
if([format isEqualToString:@"jpg"]) {
137+
data = UIImageJPEGRepresentation(image, 0.9);
138+
} else if([format isEqualToString:@"png"]) {
139+
data = UIImagePNGRepresentation(image);
140+
} else {
141+
reject(@"snapshot_error", [NSString stringWithFormat:@"unkown file format '%@'", format], nil);
142+
return;
143+
}
144+
NSString *prefixString = @"capture";
145+
146+
NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString] ;
147+
NSString *uniqueFileName = [NSString stringWithFormat:@"%@_%@.%@", prefixString, guid, format];
148+
149+
NSString *filePath = [directory stringByAppendingPathComponent:uniqueFileName]; //Add the file name
150+
bool success = [data writeToFile:filePath atomically:YES]; //Write the file
151+
if(success) {
152+
resolve(@{@"url": filePath, @"width":@(image.size.width), @"height": @(image.size.height)});
153+
} else {
154+
// TODO use NSError from writeToFile
155+
reject(@"snapshot_error", [NSString stringWithFormat:@"could not save to '%@'", filePath], nil);
156+
}
157+
158+
}
159+
160+
- (void)storeImage:(UIImage *)image options:(NSDictionary *)options reject:(RCTPromiseRejectBlock)reject resolve:(RCTPromiseResolveBlock)resolve {
161+
NSString * target = @"cameraRoll";
162+
NSString * format = @"png";
163+
164+
if(options[@"target"]) {
165+
target = options[@"target"];
166+
}
167+
if(options[@"format"]) {
168+
format = options[@"format"];
169+
}
170+
if([target isEqualToString:@"cameraRoll"]) {
171+
// camera roll / photo album
172+
[self storeImageInPhotoAlbum:image reject:reject resolve:resolve];
173+
} else {
174+
NSString * dir;
175+
if([target isEqualToString:@"cache"]) {
176+
dir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
177+
} else if([target isEqualToString:@"documents"]) {
178+
dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
179+
180+
} else {
181+
dir = target;
182+
}
183+
[self storeImageInDirectory:image directory:dir format:format reject:reject resolve:resolve];
184+
}
185+
}
186+
187+
RCT_EXPORT_METHOD(snapshot:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
188+
UIImage *image = [[ARKit sharedInstance] getSnaphshot];
189+
[self storeImage:image options:options reject:reject resolve:resolve];
190+
}
191+
192+
193+
194+
195+
RCT_EXPORT_METHOD(snapshotCamera:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
196+
UIImage *image = [[ARKit sharedInstance] getSnaphshotCamera];
197+
[self storeImage:image options:options reject:reject resolve:resolve];
104198
}
105199

106200
RCT_EXPORT_METHOD(getCamera:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
@@ -138,3 +232,4 @@ - (NSDictionary *)constantsToExport
138232
}
139233

140234
@end
235+

0 commit comments

Comments
 (0)