Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 33 additions & 28 deletions iPhone/GTMUIImage+Resize.m
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,14 @@ - (UIImage *)gtm_imageByResizingToSize:(CGSize)targetSize

// Resize photo. Use UIImage drawing methods because they respect
// UIImageOrientation as opposed to CGContextDrawImage().
UIGraphicsBeginImageContext(targetSize);
[self drawInRect:projectTo];
UIImage* resizedPhoto = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIGraphicsImageRendererFormat *rendererFormat = [[UIGraphicsImageRendererFormat alloc] init];
rendererFormat.scale = self.scale;
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:targetSize
format:rendererFormat];
UIImage *resizedPhoto =
[renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull rendererContext) {
[self drawInRect:projectTo];
}];
return resizedPhoto;
}

Expand Down Expand Up @@ -156,30 +160,31 @@ - (UIImage *)gtm_imageByRotating:(UIImageOrientation)orientation {
return nil;
}

UIGraphicsBeginImageContextWithOptions(bounds.size, NO, self.scale);
CGContextRef context = UIGraphicsGetCurrentContext();

switch (orientation) {
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
CGContextScaleCTM(context, -1.0, 1.0);
CGContextTranslateCTM(context, -rect.size.height, 0.0);
break;

default:
CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0.0, -rect.size.height);
break;
}

CGContextConcatCTM(context, transform);
CGContextDrawImage(context, rect, [self CGImage]);

UIImage *rotatedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

UIGraphicsImageRendererFormat *rendererFormat = [[UIGraphicsImageRendererFormat alloc] init];
rendererFormat.scale = self.scale;
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:bounds.size
format:rendererFormat];
UIImage *rotatedImage =
[renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull rendererContext) {
CGContextRef context = rendererContext.CGContext;
switch (orientation) {
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
CGContextScaleCTM(context, -1.0, 1.0);
CGContextTranslateCTM(context, -rect.size.height, 0.0);
break;

default:
CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0.0, -rect.size.height);
break;
}

CGContextConcatCTM(context, transform);
CGContextDrawImage(context, rect, [self CGImage]);
}];
return rotatedImage;
}

Expand Down
118 changes: 118 additions & 0 deletions iPhone/GTMUIImage+ResizeTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,20 @@ - (void)testImageByResizingWithoutPreservingAspectRatio {

// Resize with same aspect ratio.
CGSize size50x50 = CGSizeMake(50, 50);
CGFloat expectedScale = [originalImage scale];
actual = [originalImage gtm_imageByResizingToSize:size50x50
preserveAspectRatio:NO
trimToFit:NO];
XCTAssertTrue(CGSizeEqualToSize([actual size], size50x50),
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(size50x50),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Resize with different aspect ratio
CGSize size60x40 = CGSizeMake(60, 40);
Expand All @@ -85,6 +92,12 @@ - (void)testImageByResizingWithoutPreservingAspectRatio {
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(size60x40),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

CGSize size40x60 = CGSizeMake(40, 60);
actual = [originalImage gtm_imageByResizingToSize:size40x60
Expand All @@ -94,6 +107,12 @@ - (void)testImageByResizingWithoutPreservingAspectRatio {
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(size40x60),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);
}

- (void)testImageByResizingPreservingAspectRatioWithoutClip {
Expand All @@ -104,13 +123,20 @@ - (void)testImageByResizingPreservingAspectRatioWithoutClip {
// Landscape resize to 50x50, but clipped to 50x25.
CGSize size50x50 = CGSizeMake(50, 50);
CGSize expected50x25 = CGSizeMake(50, 25);
CGFloat expectedScale = [landscapeImage scale];
actual = [landscapeImage gtm_imageByResizingToSize:size50x50
preserveAspectRatio:YES
trimToFit:NO];
XCTAssertTrue(CGSizeEqualToSize([actual size], expected50x25),
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(expected50x25),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Landscape resize to 60x40, but clipped to 60x30.
CGSize size60x40 = CGSizeMake(60, 40);
Expand All @@ -123,6 +149,12 @@ - (void)testImageByResizingPreservingAspectRatioWithoutClip {
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(expected60x30),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Landscape resize to 40x60, but clipped to 40x20.
CGSize expected40x20 = CGSizeMake(40, 20);
Expand All @@ -134,6 +166,12 @@ - (void)testImageByResizingPreservingAspectRatioWithoutClip {
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(expected40x20),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Portrait Image
UIImage *portraitImage = [self testImageNamed:@"GTMUIImage+Resize_50x100"];
Expand All @@ -147,6 +185,12 @@ - (void)testImageByResizingPreservingAspectRatioWithoutClip {
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(expected25x50),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Portrait resize to 60x40, but clipped to 20x40.
CGSize expected20x40 = CGSizeMake(20, 40);
Expand All @@ -157,6 +201,12 @@ - (void)testImageByResizingPreservingAspectRatioWithoutClip {
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(expected20x40),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Portrait resize to 40x60, but clipped to 30x60.
CGSize expected30x60 = CGSizeMake(30, 60);
Expand All @@ -167,6 +217,12 @@ - (void)testImageByResizingPreservingAspectRatioWithoutClip {
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(expected30x60),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);
}

- (void)testImageByResizingPreservingAspectRatioWithClip {
Expand All @@ -176,13 +232,20 @@ - (void)testImageByResizingPreservingAspectRatioWithClip {

// Landscape resize to 50x50
CGSize size50x50 = CGSizeMake(50, 50);
CGFloat expectedScale = [landscapeImage scale];
actual = [landscapeImage gtm_imageByResizingToSize:size50x50
preserveAspectRatio:YES
trimToFit:YES];
XCTAssertTrue(CGSizeEqualToSize([actual size], size50x50),
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(size50x50),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Landscape resize to 60x40
CGSize size60x40 = CGSizeMake(60, 40);
Expand All @@ -193,6 +256,12 @@ - (void)testImageByResizingPreservingAspectRatioWithClip {
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(size60x40),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Landscape resize to 40x60
CGSize size40x60 = CGSizeMake(40, 60);
Expand All @@ -203,6 +272,12 @@ - (void)testImageByResizingPreservingAspectRatioWithClip {
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(size40x60),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Portrait Image.
UIImage *portraitImage = [self testImageNamed:@"GTMUIImage+Resize_50x100"];
Expand All @@ -215,6 +290,12 @@ - (void)testImageByResizingPreservingAspectRatioWithClip {
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(size50x50),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Portrait resize to 60x40
actual = [portraitImage gtm_imageByResizingToSize:size60x40
Expand All @@ -224,6 +305,12 @@ - (void)testImageByResizingPreservingAspectRatioWithClip {
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(size60x40),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Portrait resize to 40x60.
actual = [portraitImage gtm_imageByResizingToSize:size40x60
Expand All @@ -233,6 +320,12 @@ - (void)testImageByResizingPreservingAspectRatioWithClip {
@"Resized image should equal size: %@ actual: %@",
NSStringFromCGSize(size40x60),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);
}

- (void)testImageByRotating {
Expand All @@ -241,34 +334,59 @@ - (void)testImageByRotating {

CGSize size50x100 = CGSizeMake(50, 100);
CGSize size100x50 = CGSizeMake(100, 50);
CGFloat expectedScale = [landscapeImage scale];

// Rotate 90 degrees.
UIImage *actual = [landscapeImage gtm_imageByRotating:UIImageOrientationRight];
XCTAssertNotNil(actual);
XCTAssertTrue(CGSizeEqualToSize([actual size], size50x100),
@"Resized image should equal size: %@ actual: %@", NSStringFromCGSize(size50x100),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Rotate 180 degrees.
actual = [landscapeImage gtm_imageByRotating:UIImageOrientationDown];
XCTAssertNotNil(actual);
XCTAssertTrue(CGSizeEqualToSize([actual size], size100x50),
@"Resized image should equal size: %@ actual: %@", NSStringFromCGSize(size100x50),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Rotate 270 degrees.
actual = [landscapeImage gtm_imageByRotating:UIImageOrientationLeft];
XCTAssertNotNil(actual);
XCTAssertTrue(CGSizeEqualToSize([actual size], size50x100),
@"Resized image should equal size: %@ actual: %@", NSStringFromCGSize(size50x100),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);

// Rotate 360 degrees.
actual = [landscapeImage gtm_imageByRotating:UIImageOrientationUp];
XCTAssertNotNil(actual);
XCTAssertTrue(CGSizeEqualToSize([actual size], size100x50),
@"Resized image should equal size: %@ actual: %@", NSStringFromCGSize(size100x50),
NSStringFromCGSize([actual size]));
XCTAssertEqualWithAccuracy([actual scale],
expectedScale,
0.000000001,
@"Resized image should have scale: %f actual: %f",
expectedScale,
[actual scale]);
}

@end