2323#import " RCTImageUtils.h"
2424#endif
2525
26+ #define DEFAULT_DISPLAY_SIZE 0
2627#define DEFAULT_COMPRESSION_QUALITY 0.9
2728#define DEFAULT_RESIZE_MODE " cover"
2829
30+ struct Params {
31+ public:
32+ CGPoint offset;
33+ CGSize size;
34+ CGSize displaySize;
35+ RCTResizeMode resizeMode;
36+ CGFloat quality;
37+ NSString *format;
38+ };
39+
2940@implementation RNCImageEditor
3041
3142RCT_EXPORT_MODULE ()
3243
3344@synthesize bridge = _bridge;
3445
46+ - (Params)adaptParamsWithFormat : (id )format
47+ width : (id )width
48+ height : (id )height
49+ offsetX : (id )offsetX
50+ offsetY : (id )offsetY
51+ resizeMode : (id )resizeMode
52+ displayWidth : (id )displayWidth
53+ displayHeight : (id )displayHeight
54+ quality : (id )quality
55+ {
56+ return Params{
57+ .offset = {[RCTConvert double: offsetX], [RCTConvert double: offsetY]},
58+ .size = {[RCTConvert double: width], [RCTConvert double: height]},
59+ .displaySize = {[RCTConvert double: displayWidth], [RCTConvert double: displayHeight]},
60+ .resizeMode = [RCTConvert RCTResizeMode: resizeMode ?: @(DEFAULT_RESIZE_MODE)],
61+ .quality = [RCTConvert CGFloat: quality],
62+ .format = [RCTConvert NSString: format]
63+ };
64+ }
65+
3566/* *
3667 * Crops an image and saves the result to temporary file. Consider using
3768 * CameraRoll API or other third-party module to save it in gallery.
@@ -49,71 +80,60 @@ - (void) cropImage:(NSString *)uri
4980 resolve : (RCTPromiseResolveBlock)resolve
5081 reject : (RCTPromiseRejectBlock)reject
5182{
52- NSString *format = data.format ();
53- CGSize size = [RCTConvert CGSize: @{ @" width" : @(data.size ().width ()), @" height" : @(data.size ().height ()) }];
54- CGPoint offset = [RCTConvert CGPoint: @{ @" x" : @(data.offset ().x ()), @" y" : @(data.offset ().y ()) }];
55- CGSize targetSize = size;
56- CGSize displaySize = CGSizeZero;
57- BOOL hasDisplaySizeValue = data.displaySize ().has_value ();
58- if (hasDisplaySizeValue) {
59- JS::NativeRNCImageEditor::SpecCropImageCropDataDisplaySize rawDisplaySize = *data.displaySize (); // Extract the value from the optional
60- // in pixels
61- displaySize = [RCTConvert CGSize: @{ @" width" : @(rawDisplaySize.width ()), @" height" : @(rawDisplaySize.height ()) }];
62- }
63- RCTResizeMode resizeMode = [RCTConvert RCTResizeMode: data.resizeMode () ?: @(DEFAULT_RESIZE_MODE)];
64- NSURLRequest *imageRequest = [NSURLRequest requestWithURL: [NSURL URLWithString: uri]];
65- CGFloat compressionQuality = DEFAULT_COMPRESSION_QUALITY;
66- if (data.quality ().has_value ()) {
67- compressionQuality = *data.quality ();
68- }
83+ NSURLRequest *imageRequest = [NSURLRequest requestWithURL: [NSURL URLWithString: uri]];
84+ auto params = [self adaptParamsWithFormat: data.format ()
85+ width: @(data.size ().width ())
86+ height: @(data.size ().height ())
87+ offsetX: @(data.offset ().x ())
88+ offsetY: @(data.offset ().y ())
89+ resizeMode: data.resizeMode ()
90+ displayWidth: @(data.displaySize ().has_value () ? data.displaySize ()->width () : DEFAULT_DISPLAY_SIZE)
91+ displayHeight: @(data.displaySize ().has_value () ? data.displaySize ()->height () : DEFAULT_DISPLAY_SIZE)
92+ quality: @(data.quality ().has_value () ? *data.quality () : DEFAULT_COMPRESSION_QUALITY)];
6993#else
7094RCT_EXPORT_METHOD (cropImage:(NSURLRequest *)imageRequest
7195 cropData:(NSDictionary *)cropData
7296 resolve:(RCTPromiseResolveBlock)resolve
7397 reject:(RCTPromiseRejectBlock)reject)
7498{
75- NSString *format = cropData[@" format" ];
76- CGSize size = [RCTConvert CGSize: cropData[@" size" ]];
77- CGPoint offset = [RCTConvert CGPoint: cropData[@" offset" ]];
78- RCTResizeMode resizeMode = [RCTConvert RCTResizeMode: cropData[@" resizeMode" ] ?: @(DEFAULT_RESIZE_MODE)];
79- CGSize displaySize = CGSizeZero;
80- BOOL hasDisplaySizeValue = cropData[@" displaySize" ];
81- if (hasDisplaySizeValue){
82- displaySize = [RCTConvert CGSize: cropData[@" displaySize" ]];
83- }
84- CGFloat compressionQuality = DEFAULT_COMPRESSION_QUALITY;
85- if (cropData[@" quality" ]){
86- compressionQuality = [RCTConvert CGFloat: cropData[@" quality" ]];
87- }
99+ auto params = [self adaptParamsWithFormat: cropData[@" format" ]
100+ width: cropData[@" size" ][@" width" ]
101+ height: cropData[@" size" ][@" height" ]
102+ offsetX: cropData[@" offset" ][@" x" ]
103+ offsetY: cropData[@" offset" ][@" y" ]
104+ resizeMode: cropData[@" resizeMode" ]
105+ displayWidth: cropData[@" displaySize" ] ? cropData[@" displaySize" ][@" width" ] : @(DEFAULT_DISPLAY_SIZE)
106+ displayHeight: cropData[@" displaySize" ] ? cropData[@" displaySize" ][@" height" ] : @(DEFAULT_DISPLAY_SIZE)
107+ quality: cropData[@" quality" ] ? cropData[@" quality" ] : @(DEFAULT_COMPRESSION_QUALITY)];
108+
88109#endif
89- CGRect rect = {offset,size};
90110 NSURL *url = [imageRequest URL ];
91111 NSString *urlPath = [url path ];
92112 NSString *extension = [urlPath pathExtension ];
93- if ([format isEqualToString: @" png" ] || [format isEqualToString: @" jpeg" ]){
94- extension = format;
113+ if ([params. format isEqualToString: @" png" ] || [params. format isEqualToString: @" jpeg" ]){
114+ extension = params. format ;
95115 }
96116
97117 [[_bridge moduleForName: @" ImageLoader" lazilyLoadIfNecessary: YES ] loadImageWithURLRequest: imageRequest callback: ^(NSError *error, UIImage *image) {
98118 if (error) {
99119 reject (@(error.code ).stringValue , error.description , error);
100120 return ;
101121 }
102- if (compressionQuality > 1 || compressionQuality < 0 ) {
122+ if (params. quality > 1 || params. quality < 0 ) {
103123 reject (RCTErrorUnspecified, @(" quality must be a number between 0 and 1" ), nil );
104124 return ;
105125 }
106126
107127 // Crop image
108- CGSize targetSize = rect .size ;
109- CGRect targetRect = {{-rect. origin .x , -rect. origin .y }, image.size };
128+ CGSize targetSize = params .size ;
129+ CGRect targetRect = {{-params. offset .x , -params. offset .y }, image.size };
110130 CGAffineTransform transform = RCTTransformFromTargetRect (image.size , targetRect);
111131 UIImage *croppedImage = RCTTransformImage (image, targetSize, image.scale , transform);
112132
113133 // Scale image
114- if (hasDisplaySizeValue ) {
115- targetSize = displaySize;
116- targetRect = RCTTargetRect (croppedImage.size , targetSize, 1 , resizeMode);
134+ if (params. displaySize . width != DEFAULT_DISPLAY_SIZE && params. displaySize . height != DEFAULT_DISPLAY_SIZE ) {
135+ targetSize = params. displaySize ;
136+ targetRect = RCTTargetRect (croppedImage.size , targetSize, 1 , params. resizeMode );
117137 transform = RCTTransformFromTargetRect (croppedImage.size , targetRect);
118138 croppedImage = RCTTransformImage (croppedImage, targetSize, image.scale , transform);
119139 }
@@ -127,7 +147,7 @@ - (void) cropImage:(NSString *)uri
127147 path = [RNCFileSystem generatePathInDirectory: [[RNCFileSystem cacheDirectoryPath ] stringByAppendingPathComponent: @" ReactNative_cropped_image_" ] withExtension: @" .png" ];
128148 }
129149 else {
130- imageData = UIImageJPEGRepresentation (croppedImage, compressionQuality );
150+ imageData = UIImageJPEGRepresentation (croppedImage, params. quality );
131151 path = [RNCFileSystem generatePathInDirectory: [[RNCFileSystem cacheDirectoryPath ] stringByAppendingPathComponent: @" ReactNative_cropped_image_" ] withExtension: @" .jpg" ];
132152 }
133153
0 commit comments