-
Notifications
You must be signed in to change notification settings - Fork 0
/
RNAssetResizer.m
180 lines (139 loc) · 6.53 KB
/
RNAssetResizer.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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
123
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
//
// Created by Jeff Lerman Oct 5, 2016
//
#import "RNAssetResizer.h"
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
@import Photos;
@implementation RNAssetResizer
-(UIImage *)resizeImage :(UIImage *)theImage :(CGSize)theNewSize {
// keep scale at 1.0 since we are not using this for display
// can assets ever come in with scale greater than 1.0??
UIGraphicsBeginImageContextWithOptions(theNewSize, NO, 1.0);
[theImage drawInRect:CGRectMake(0, 0, theNewSize.width, theNewSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
-(NSDictionary*)metadataFromImageData:(NSData*)imageData{
CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)(imageData), NULL);
if (imageSource) {
NSDictionary *options = @{(NSString *)kCGImageSourceShouldCache : [NSNumber numberWithBool:NO]};
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, (__bridge CFDictionaryRef)options);
if (imageProperties) {
NSDictionary *metadata = (__bridge NSDictionary *)imageProperties;
CFRelease(imageProperties);
CFRelease(imageSource);
return metadata;
}
CFRelease(imageSource);
}
NSLog(@"Can't read metadata");
return nil;
}
- (NSString *)generateFilePath:(NSString *)outputPath ext:(NSString *)ext
{
NSString* directory;
if ([outputPath length] == 0) {
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
directory = [paths firstObject];
}
else {
directory = outputPath;
}
NSString* name = [[NSUUID UUID] UUIDString];
NSString* fullName = [NSString stringWithFormat:@"%@.%@", name, ext];
NSString* fullPath = [directory stringByAppendingPathComponent:fullName];
return fullPath;
}
RCT_EXPORT_MODULE()
RCT_EXPORT_METHOD(resizeAsset:(NSURL *)assetPath
width:(float)width
height:(float)height
outputPath:(NSString *)outputPath
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
{
NSString *assetID = @"";
PHAsset *_asset;
if ([assetPath.scheme caseInsensitiveCompare:@"ph"] == NSOrderedSame) {
assetID = [assetPath.absoluteString substringFromIndex:@"ph://".length];
_asset = [[PHAsset fetchAssetsWithLocalIdentifiers:@[assetID] options:nil] firstObject];
}
else if ([assetPath.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame) {
assetID = [assetPath absoluteString];
_asset = [[PHAsset fetchAssetsWithALAssetURLs:@[assetPath] options:nil] firstObject];
}
if (!_asset) {
reject(@"Error", @"Cannot find asset", nil);
return;
}
CGSize newSize = CGSizeMake(width, height);
NSString* fullPath = [self generateFilePath:outputPath ext:@"jpg"];
// get photo info from this asset
PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
requestOptions.synchronous = YES;
requestOptions.networkAccessAllowed = YES;
[[PHImageManager defaultManager]
requestImageDataForAsset:_asset
options:requestOptions
resultHandler:^(NSData *imageData, NSString *dataUTI,
UIImageOrientation orientation,
NSDictionary *info)
{
// grab metadata and add originalUri to EXIF
NSDictionary *metadata = [self metadataFromImageData:imageData];
NSMutableDictionary *mutableMetadata = nil;
if (metadata != nil) {
mutableMetadata = [metadata mutableCopy];
}
else {
mutableMetadata = [[NSMutableDictionary alloc] init];
}
NSArray *resources = [PHAssetResource assetResourcesForAsset:_asset];
NSString *orgFilename = ((PHAssetResource*)resources[0]).originalFilename;
[mutableMetadata setValue:orgFilename forKey:@"originalUri"];
//mutableMetadata
UIImage *newImage = [UIImage imageWithData:imageData];
// TODO: add option to figure out based on max width/height scale
UIImage *scaledImage = [self resizeImage:newImage :newSize];
//NSLog(@"Got newImage w[%f] h[%f] s[%f] thisO[%ld], origO[%ld]", newImage.size.width, newImage.size.height, newImage.scale, (long)newImage.imageOrientation,(long)orientation);
//NSLog(@"Got scaledImage w[%f] h[%f] s[%f] thisO[%ld], origO[%ld]", scaledImage.size.width, scaledImage.size.height, scaledImage.scale, (long)scaledImage.imageOrientation,(long)orientation);
// set the quality to 75%
[mutableMetadata setObject:@(.75) forKey:(__bridge NSString *)kCGImageDestinationLossyCompressionQuality];
// reset orientation to UP(1) since we did redraw
[mutableMetadata setObject:[NSNumber numberWithInt:1] forKey:@"Orientation"];
// also need to reset TIFF orientation to 1
NSMutableDictionary *tiffMetadata = [mutableMetadata objectForKey:(NSString *)kCGImagePropertyTIFFDictionary];
if (tiffMetadata != nil) {
[tiffMetadata setObject:[NSNumber numberWithInt:1] forKey:(NSString*)kCGImagePropertyTIFFOrientation];
[mutableMetadata setObject:tiffMetadata forKey:(NSString*)kCGImagePropertyTIFFDictionary];
}
//NSLog( @"METADATA: %@", mutableMetadata );
// Create an image destination.
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:fullPath], kUTTypeJPEG , 1, NULL);
if (imageDestination == NULL ) {
// Handle failure.
NSLog(@"Error -> failed to create image destination.");
reject(@"Error", @"Cannot create image destination", nil);
return;
}
// Add your image to the destination.
CGImageDestinationAddImage(imageDestination, scaledImage.CGImage, (__bridge CFDictionaryRef)mutableMetadata);
BOOL finalized = CGImageDestinationFinalize(imageDestination);
tiffMetadata = nil;
mutableMetadata = nil;
// Finalize the destination.
if (finalized == NO) {
// Handle failure.
NSLog(@"Error -> failed to finalize the image.");
}
CFRelease(imageDestination);
if(finalized) {
resolve(fullPath);
} else {
reject(@"Error", @"Could not finalize file", nil);
}
}];
}
@end