Skip to content

Commit 7d4652d

Browse files
samdarkAlexV525
andauthored
Use UIGraphicsImageRenderer instead of UIGraphicsBeginImageContext when available (#335)
Resolves #310 --------- Co-authored-by: Alex Li <github@alexv525.com>
1 parent 966a132 commit 7d4652d

1 file changed

Lines changed: 63 additions & 20 deletions

File tree

packages/flutter_image_compress_common/ios/Classes/UIImage+scale.m

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,27 @@ -(UIImage *)scaleWithMinWidth: (CGFloat)minWidth minHeight:(CGFloat)minHeight {
2424
actualHeight = floor(scaleRatio * actualHeight);
2525

2626
CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
27-
UIGraphicsBeginImageContext(rect.size);
28-
[self drawInRect:rect];
29-
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
30-
UIGraphicsEndImageContext();
27+
UIImage *newImage;
28+
if (@available(iOS 10.0, *)) {
29+
// Match the legacy UIGraphicsBeginImageContext behavior:
30+
// - scale = 1.0 keeps output in logical pixels (renderer default is device screen scale, e.g. 2x/3x).
31+
// - preferredRange = Standard keeps output in sRGB (renderer default is automatic, which produces
32+
// P3/extended-range bitmaps on wide-gamut devices and can inflate compressed file sizes).
33+
UIGraphicsImageRendererFormat *format = [[UIGraphicsImageRendererFormat alloc] init];
34+
format.scale = 1.0;
35+
if (@available(iOS 12.0, *)) {
36+
format.preferredRange = UIGraphicsImageRendererFormatRangeStandard;
37+
}
38+
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:rect.size format:format];
39+
newImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull context) {
40+
[self drawInRect:rect];
41+
}];
42+
} else {
43+
UIGraphicsBeginImageContext(rect.size);
44+
[self drawInRect:rect];
45+
newImage = UIGraphicsGetImageFromCurrentImageContext();
46+
UIGraphicsEndImageContext();
47+
}
3148

3249
if([ImageCompressPlugin showLog]){
3350
NSLog(@"scale = %.2f", scaleRatio);
@@ -52,22 +69,48 @@ - (UIImage *)imageRotatedByDegrees:(UIImage*)oldImage deg:(CGFloat)degrees{
5269
CGAffineTransform t = CGAffineTransformMakeRotation(degrees * M_PI / 180);
5370
rotatedViewBox.transform = t;
5471
CGSize rotatedSize = rotatedViewBox.frame.size;
55-
// Create the bitmap context
56-
UIGraphicsBeginImageContext(rotatedSize);
57-
CGContextRef bitmap = UIGraphicsGetCurrentContext();
58-
59-
// Move the origin to the middle of the image so we will rotate and scale around the center.
60-
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
61-
62-
// // Rotate the image context
63-
CGContextRotateCTM(bitmap, (degrees * M_PI / 180));
64-
65-
// Now, draw the rotated/scaled image into the context
66-
CGContextScaleCTM(bitmap, 1.0, -1.0);
67-
CGContextDrawImage(bitmap, CGRectMake(-oldImage.size.width / 2, -oldImage.size.height / 2, oldImage.size.width, oldImage.size.height), [oldImage CGImage]);
68-
69-
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
70-
UIGraphicsEndImageContext();
72+
73+
UIImage *newImage;
74+
if (@available(iOS 10.0, *)) {
75+
// See scaleWithMinWidth:minHeight: for why scale and preferredRange are pinned.
76+
UIGraphicsImageRendererFormat *format = [[UIGraphicsImageRendererFormat alloc] init];
77+
format.scale = 1.0;
78+
if (@available(iOS 12.0, *)) {
79+
format.preferredRange = UIGraphicsImageRendererFormatRangeStandard;
80+
}
81+
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:rotatedSize format:format];
82+
newImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull context) {
83+
CGContextRef bitmap = context.CGContext;
84+
85+
// Move the origin to the middle of the image so we will rotate and scale around the center.
86+
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
87+
88+
// Rotate the image context
89+
CGContextRotateCTM(bitmap, (degrees * M_PI / 180));
90+
91+
// Now, draw the rotated/scaled image into the context
92+
CGContextScaleCTM(bitmap, 1.0, -1.0);
93+
CGContextDrawImage(bitmap, CGRectMake(-oldImage.size.width / 2, -oldImage.size.height / 2, oldImage.size.width, oldImage.size.height), [oldImage CGImage]);
94+
}];
95+
} else {
96+
// Create the bitmap context
97+
UIGraphicsBeginImageContext(rotatedSize);
98+
CGContextRef bitmap = UIGraphicsGetCurrentContext();
99+
100+
// Move the origin to the middle of the image so we will rotate and scale around the center.
101+
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
102+
103+
// Rotate the image context
104+
CGContextRotateCTM(bitmap, (degrees * M_PI / 180));
105+
106+
// Now, draw the rotated/scaled image into the context
107+
CGContextScaleCTM(bitmap, 1.0, -1.0);
108+
CGContextDrawImage(bitmap, CGRectMake(-oldImage.size.width / 2, -oldImage.size.height / 2, oldImage.size.width, oldImage.size.height), [oldImage CGImage]);
109+
110+
newImage = UIGraphicsGetImageFromCurrentImageContext();
111+
UIGraphicsEndImageContext();
112+
}
113+
71114
return newImage;
72115
}
73116

0 commit comments

Comments
 (0)