1//
2//  EXCameraUtils.m
3//  Exponent
4//
5//  Created by Stanisław Chmiela on 23.10.2017.
6//  Copyright © 2017 650 Industries. All rights reserved.
7//
8
9#import <EXCamera/EXCameraUtils.h>
10
11#import <CoreMotion/CoreMotion.h>
12
13@implementation EXCameraUtils
14
15# pragma mark - Camera utilities
16
17+ (AVCaptureDevice *)deviceWithMediaType:(AVMediaType)mediaType preferringPosition:(AVCaptureDevicePosition)position
18{
19  return [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInWideAngleCamera mediaType:mediaType position:position];
20}
21
22+ (UIDeviceOrientation)deviceOrientationForAccelerometerData:(CMAccelerometerData*)accelerometerData defaultOrientation:(UIDeviceOrientation)orientation
23{
24  if (accelerometerData.acceleration.x >= 0.75) {
25    return UIDeviceOrientationLandscapeRight;
26  }
27  if(accelerometerData.acceleration.x <= -0.75) {
28    return UIDeviceOrientationLandscapeLeft;
29  }
30  if(accelerometerData.acceleration.y <= -0.75) {
31    return UIDeviceOrientationPortrait;
32  }
33  if(accelerometerData.acceleration.y >= 0.75) {
34    return UIDeviceOrientationPortraitUpsideDown;
35  }
36
37  return orientation;
38}
39
40# pragma mark - Enum conversion
41
42+ (AVCaptureVideoOrientation)videoOrientationForInterfaceOrientation:(UIInterfaceOrientation)orientation
43{
44  switch (orientation) {
45    case UIInterfaceOrientationPortrait:
46      return AVCaptureVideoOrientationPortrait;
47    case UIInterfaceOrientationPortraitUpsideDown:
48      return AVCaptureVideoOrientationPortraitUpsideDown;
49    case UIInterfaceOrientationLandscapeRight:
50      return AVCaptureVideoOrientationLandscapeRight;
51    case UIInterfaceOrientationLandscapeLeft:
52      return AVCaptureVideoOrientationLandscapeLeft;
53    default:
54      return 0;
55  }
56}
57
58+ (AVCaptureVideoOrientation)videoOrientationForDeviceOrientation:(UIDeviceOrientation)orientation
59{
60  switch (orientation) {
61    case UIDeviceOrientationPortrait:
62      return AVCaptureVideoOrientationPortrait;
63    case UIDeviceOrientationPortraitUpsideDown:
64      return AVCaptureVideoOrientationPortraitUpsideDown;
65    case UIDeviceOrientationLandscapeLeft:
66      return AVCaptureVideoOrientationLandscapeRight;
67    case UIDeviceOrientationLandscapeRight:
68      return AVCaptureVideoOrientationLandscapeLeft;
69    default:
70      return AVCaptureVideoOrientationPortrait;
71  }
72}
73
74+ (float)temperatureForWhiteBalance:(EXCameraWhiteBalance)whiteBalance
75{
76  switch (whiteBalance) {
77    case EXCameraWhiteBalanceSunny: default:
78      return 5200;
79    case EXCameraWhiteBalanceCloudy:
80      return 6000;
81    case EXCameraWhiteBalanceShadow:
82      return 7000;
83    case EXCameraWhiteBalanceIncandescent:
84      return 3000;
85    case EXCameraWhiteBalanceFluorescent:
86      return 4200;
87  }
88}
89
90+ (NSString *)captureSessionPresetForVideoResolution:(EXCameraVideoResolution)resolution
91{
92  switch (resolution) {
93    case EXCameraVideo2160p:
94      return AVCaptureSessionPreset3840x2160;
95    case EXCameraVideo1080p:
96      return AVCaptureSessionPreset1920x1080;
97    case EXCameraVideo720p:
98      return AVCaptureSessionPreset1280x720;
99    case EXCameraVideo4x3:
100      return AVCaptureSessionPreset640x480;
101    default:
102      return AVCaptureSessionPresetHigh;
103  }
104}
105
106+ (int)exportImageOrientation:(UIImageOrientation)orientation
107{
108   switch (orientation) {
109     case UIImageOrientationLeft:
110       return 90;
111     case UIImageOrientationRight:
112       return -90;
113     case UIImageOrientationDown:
114       return 180;
115     default:
116       return 0;
117   }
118}
119
120+ (AVVideoCodecType)videoCodecForType:(EXCameraVideoCodec)videoCodecType
121{
122  switch (videoCodecType) {
123    case EXCameraVideoCodecH264:
124      return AVVideoCodecTypeH264;
125    case EXCameraVideoCodecHEVC:
126      return AVVideoCodecTypeHEVC;
127    case EXCameraVideoCodecJPEG:
128      return AVVideoCodecTypeJPEG;
129    case EXCameraVideoCodecAppleProRes422:
130      return AVVideoCodecTypeAppleProRes422;
131    case EXCameraVideoCodecAppleProRes4444:
132      return AVVideoCodecTypeAppleProRes4444;
133    default:
134      return @"VIDEO_CODEC_UNKNOWN";
135  }
136}
137
138
139# pragma mark - Image utilities
140
141+ (UIImage *)generatePhotoOfSize:(CGSize)size
142{
143  CGRect rect = CGRectMake(0, 0, size.width, size.height);
144  UIImage *image;
145  UIGraphicsBeginImageContextWithOptions(size, YES, 0);
146  UIColor *color = [UIColor blackColor];
147  [color setFill];
148  UIRectFill(rect);
149  NSDate *currentDate = [NSDate date];
150  NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
151  [dateFormatter setDateFormat:@"dd.MM.YY HH:mm:ss"];
152  NSString *text = [dateFormatter stringFromDate:currentDate];
153  NSDictionary *attributes = [NSDictionary dictionaryWithObjects: @[[UIFont systemFontOfSize:18.0], [UIColor orangeColor]]
154                                                         forKeys: @[NSFontAttributeName, NSForegroundColorAttributeName]];
155  [text drawAtPoint:CGPointMake(size.width * 0.1, size.height * 0.9) withAttributes:attributes];
156  image = UIGraphicsGetImageFromCurrentImageContext();
157  UIGraphicsEndImageContext();
158  return image;
159}
160
161+ (UIImage *)cropImage:(UIImage *)image toRect:(CGRect)rect
162{
163  CGImageRef takenCGImage = image.CGImage;
164  CGImageRef cropCGImage = CGImageCreateWithImageInRect(takenCGImage, rect);
165  image = [UIImage imageWithCGImage:cropCGImage scale:image.scale orientation:image.imageOrientation];
166  CGImageRelease(cropCGImage);
167  return image;
168}
169
170+ (NSString *)writeImage:(NSData *)image toPath:(NSString *)path
171{
172  [image writeToFile:path atomically:YES];
173  NSURL *fileURL = [NSURL fileURLWithPath:path];
174  return [fileURL absoluteString];
175}
176
177+ (NSData *)dataFromImage:(UIImage *)image withMetadata:(NSDictionary *)metadata imageQuality:(float)quality
178{
179  // Get metadata (includes the EXIF data)
180  CGImageSourceRef sourceCGIImageRef = CGImageSourceCreateWithData((CFDataRef) UIImageJPEGRepresentation(image, 1.0f), NULL);
181  NSDictionary *sourceMetadata = (__bridge NSDictionary *) CGImageSourceCopyPropertiesAtIndex(sourceCGIImageRef, 0, NULL);
182
183  NSMutableDictionary *updatedMetadata = [sourceMetadata mutableCopy];
184
185  for (id key in metadata) {
186    updatedMetadata[key] = metadata[key];
187  }
188
189  // Set compression quality
190  [updatedMetadata setObject:@(quality) forKey:(__bridge NSString *)kCGImageDestinationLossyCompressionQuality];
191
192  // Create an image destination
193  NSMutableData *processedImageData = [NSMutableData data];
194  CGImageDestinationRef destinationCGImageRef = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)processedImageData, CGImageSourceGetType(sourceCGIImageRef), 1, NULL);
195
196  // Add image to the destination
197  // Note: it'll save only these value which are under the kCGImageProperty* key.
198  CGImageDestinationAddImage(destinationCGImageRef, image.CGImage, (__bridge CFDictionaryRef) updatedMetadata);
199
200  // Finalize the destination
201  if (CGImageDestinationFinalize(destinationCGImageRef)) {
202    CFRelease(sourceCGIImageRef);
203    CFRelease(destinationCGImageRef);
204
205    return processedImageData;
206  }
207  return nil;
208}
209
210+ (NSMutableDictionary *)updateExifMetadata:(NSDictionary *)metadata withAdditionalData:(NSDictionary *)additionalData
211{
212  NSMutableDictionary *mutableMetadata = [[NSMutableDictionary alloc] initWithDictionary:metadata];
213  for (id key in additionalData) {
214    mutableMetadata[key] = additionalData[key];
215  }
216
217  NSDictionary *gps = mutableMetadata[(NSString *)kCGImagePropertyGPSDictionary];
218
219  if (gps) {
220    for (NSString *gpsKey in gps) {
221      mutableMetadata[[@"GPS" stringByAppendingString:gpsKey]] = gps[gpsKey];
222    }
223  }
224
225  return mutableMetadata;
226}
227
228@end
229