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