Skip to content

Commit c59e226

Browse files
authored
Merge pull request #138 from callstack/fix/retyui/resizeMode-logic
fix: Restore resizeMode logic after New Arch update
2 parents 8ee9eb2 + d9c6687 commit c59e226

File tree

3 files changed

+63
-38
lines changed

3 files changed

+63
-38
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ ImageEditor.cropImage(uri, cropData).then(
6363
| `offset` | Yes | The top-left corner of the cropped image, specified in the original image's coordinate space |
6464
| `size` | Yes | Size (dimensions) of the cropped image |
6565
| `displaySize` | No | Size to which you want to scale the cropped image |
66-
| `resizeMode` | No | Resizing mode to use when scaling the image (iOS only, Android resize mode is always 'cover', Web - no support) **Default value**: 'contain' |
66+
| `resizeMode` | No | Resizing mode to use when scaling the image (iOS only, Android resize mode is always `'cover'`, Web - no support) **Default value**: `'cover'` |
6767
| `quality` | No | The quality of the resulting image, expressed as a value from `0.0` to `1.0`. <br/>The value `0.0` represents the maximum compression (or lowest quality) while the value `1.0` represents the least compression (or best quality).<br/>iOS supports only `JPEG` format, while Android/Web supports both `JPEG`, `WEBP` and `PNG` formats.<br/>**Default value**: `0.9` |
6868
| `format` | No | The format of the resulting image, possible values are `jpeg`, `png`, `webp`. <br/> **Default value**: based on the provided image; if value determination is not possible, `jpeg` will be used as a fallback. <br/> `webp` isn't supported by iOS. |
6969

ios/RNCImageEditor.mm

Lines changed: 61 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,46 @@
2323
#import "RCTImageUtils.h"
2424
#endif
2525

26+
#define DEFAULT_DISPLAY_SIZE 0
2627
#define DEFAULT_COMPRESSION_QUALITY 0.9
28+
#define DEFAULT_RESIZE_MODE "cover"
29+
30+
struct Params {
31+
public:
32+
CGPoint offset;
33+
CGSize size;
34+
CGSize displaySize;
35+
RCTResizeMode resizeMode;
36+
CGFloat quality;
37+
NSString *format;
38+
};
2739

2840
@implementation RNCImageEditor
2941

3042
RCT_EXPORT_MODULE()
3143

3244
@synthesize bridge = _bridge;
3345

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+
3466
/**
3567
* Crops an image and saves the result to temporary file. Consider using
3668
* CameraRoll API or other third-party module to save it in gallery.
@@ -48,67 +80,60 @@ - (void) cropImage:(NSString *)uri
4880
resolve:(RCTPromiseResolveBlock)resolve
4981
reject:(RCTPromiseRejectBlock)reject
5082
{
51-
NSString *format = data.format();
52-
CGSize size = [RCTConvert CGSize:@{ @"width": @(data.size().width()), @"height": @(data.size().height()) }];
53-
CGPoint offset = [RCTConvert CGPoint:@{ @"x": @(data.offset().x()), @"y": @(data.offset().y()) }];
54-
CGSize targetSize = size;
55-
if (data.displaySize().has_value()) {
56-
JS::NativeRNCImageEditor::SpecCropImageCropDataDisplaySize displaySize = *data.displaySize(); // Extract the value from the optional
57-
// in pixels
58-
targetSize = [RCTConvert CGSize:@{ @"width": @(displaySize.width()), @"height": @(displaySize.height()) }];
59-
}
60-
NSString *displaySize = data.resizeMode();
61-
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:[NSURL URLWithString: uri]];
62-
CGFloat compressionQuality = DEFAULT_COMPRESSION_QUALITY;
63-
if (data.quality().has_value()) {
64-
compressionQuality = *data.quality();
65-
}
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)];
6693
#else
6794
RCT_EXPORT_METHOD(cropImage:(NSURLRequest *)imageRequest
6895
cropData:(NSDictionary *)cropData
6996
resolve:(RCTPromiseResolveBlock)resolve
7097
reject:(RCTPromiseRejectBlock)reject)
7198
{
72-
NSString *format = cropData[@"format"];
73-
CGSize size = [RCTConvert CGSize:cropData[@"size"]];
74-
CGPoint offset = [RCTConvert CGPoint:cropData[@"offset"]];
75-
CGSize targetSize = size;
76-
NSString *displaySize = cropData[@"resizeMode"];
77-
if(displaySize){
78-
targetSize = [RCTConvert CGSize:cropData[@"displaySize"]];
79-
}
80-
CGFloat compressionQuality = DEFAULT_COMPRESSION_QUALITY;
81-
if(cropData[@"quality"]){
82-
compressionQuality = [RCTConvert CGFloat:cropData[@"quality"]];
83-
}
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+
84109
#endif
85-
CGRect rect = {offset,size};
86110
NSURL *url = [imageRequest URL];
87111
NSString *urlPath = [url path];
88112
NSString *extension = [urlPath pathExtension];
89-
if([format isEqualToString:@"png"] || [format isEqualToString:@"jpeg"]){
90-
extension = format;
113+
if([params.format isEqualToString:@"png"] || [params.format isEqualToString:@"jpeg"]){
114+
extension = params.format;
91115
}
92116

93117
[[_bridge moduleForName:@"ImageLoader" lazilyLoadIfNecessary:YES] loadImageWithURLRequest:imageRequest callback:^(NSError *error, UIImage *image) {
94118
if (error) {
95119
reject(@(error.code).stringValue, error.description, error);
96120
return;
97121
}
98-
if (compressionQuality > 1 || compressionQuality < 0) {
122+
if (params.quality > 1 || params.quality < 0) {
99123
reject(RCTErrorUnspecified, @("quality must be a number between 0 and 1"), nil);
100124
return;
101125
}
102126

103127
// Crop image
104-
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};
105130
CGAffineTransform transform = RCTTransformFromTargetRect(image.size, targetRect);
106131
UIImage *croppedImage = RCTTransformImage(image, targetSize, image.scale, transform);
107132

108133
// Scale image
109-
if (displaySize) {
110-
RCTResizeMode resizeMode = [RCTConvert RCTResizeMode:displaySize ?: @"contain"];
111-
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);
112137
transform = RCTTransformFromTargetRect(croppedImage.size, targetRect);
113138
croppedImage = RCTTransformImage(croppedImage, targetSize, image.scale, transform);
114139
}
@@ -122,7 +147,7 @@ - (void) cropImage:(NSString *)uri
122147
path = [RNCFileSystem generatePathInDirectory:[[RNCFileSystem cacheDirectoryPath] stringByAppendingPathComponent:@"ReactNative_cropped_image_"] withExtension:@".png"];
123148
}
124149
else{
125-
imageData = UIImageJPEGRepresentation(croppedImage, compressionQuality);
150+
imageData = UIImageJPEGRepresentation(croppedImage, params.quality);
126151
path = [RNCFileSystem generatePathInDirectory:[[RNCFileSystem cacheDirectoryPath] stringByAppendingPathComponent:@"ReactNative_cropped_image_"] withExtension:@".jpg"];
127152
}
128153

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ type ImageCropDataFromSpec = Parameters<Spec['cropImage']>[1];
55
export interface ImageCropData
66
extends Omit<ImageCropDataFromSpec, 'resizeMode' | 'format'> {
77
format?: 'png' | 'jpeg' | 'webp';
8-
resizeMode?: 'contain' | 'cover' | 'stretch';
8+
resizeMode?: 'contain' | 'cover' | 'stretch' | 'center';
99
// ^^^ codegen doesn't support union types yet
1010
// so to provide more type safety we override the type here
1111
}

0 commit comments

Comments
 (0)