aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2010-05-26 18:06:02 +0000
committerGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2010-05-26 18:06:02 +0000
commitc8b442e4af5f12d91450e9b1fcce1468aa49de4e (patch)
tree6b4025ace69838de8fedcb96de8db0b0aa14d58a
parent69491c3dd52dffcb3fdbaffeffb63483fbd15088 (diff)
[Author: caseyho]
UIImage rotate method plus tests. R=altse APPROVED=altse DELTA=152 (152 added, 0 deleted, 0 changed)
-rw-r--r--GTMiPhone.xcodeproj/project.pbxproj8
-rw-r--r--ReleaseNotes.txt7
-rw-r--r--iPhone/GTMUIImage+Resize.h11
-rw-r--r--iPhone/GTMUIImage+Resize.m100
-rw-r--r--iPhone/GTMUIImage+ResizeTest.m26
-rw-r--r--iPhone/TestData/GTMUIImage+Resize_100x50_flipped.pngbin0 -> 1178 bytes
-rw-r--r--iPhone/TestData/GTMUIImage+Resize_50x100_flipped.pngbin0 -> 1197 bytes
7 files changed, 151 insertions, 1 deletions
diff --git a/GTMiPhone.xcodeproj/project.pbxproj b/GTMiPhone.xcodeproj/project.pbxproj
index 842dca2..42e0ec4 100644
--- a/GTMiPhone.xcodeproj/project.pbxproj
+++ b/GTMiPhone.xcodeproj/project.pbxproj
@@ -32,6 +32,8 @@
1D3623EC0D0F72F000981E51 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */; };
1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
+ 448D61FB11AC1F1B0097ACBC /* GTMUIImage+Resize_100x50_flipped.png in Resources */ = {isa = PBXBuildFile; fileRef = 448D61B111AC1AAD0097ACBC /* GTMUIImage+Resize_100x50_flipped.png */; };
+ 448D61FC11AC1F250097ACBC /* GTMUIImage+Resize_50x100_flipped.png in Resources */ = {isa = PBXBuildFile; fileRef = 448D61B011AC1AAD0097ACBC /* GTMUIImage+Resize_50x100_flipped.png */; };
6294461C0EDE178D009295EA /* GTMNSArray+MergeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 629446190EDE177A009295EA /* GTMNSArray+MergeTest.m */; };
6294461D0EDE17A0009295EA /* GTMNSArray+Merge.m in Sources */ = {isa = PBXBuildFile; fileRef = 629446180EDE177A009295EA /* GTMNSArray+Merge.m */; };
64D0F5C80FD3E65C00506CC7 /* GTMUIImage+ResizeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 64D0F5C60FD3E65C00506CC7 /* GTMUIImage+ResizeTest.m */; };
@@ -157,6 +159,8 @@
1D6058910D05DD3D006BFB54 /* GTMiPhoneTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GTMiPhoneTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
32CA4F630368D1EE00C91783 /* GTM_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTM_Prefix.pch; sourceTree = "<group>"; };
+ 448D61B011AC1AAD0097ACBC /* GTMUIImage+Resize_50x100_flipped.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "GTMUIImage+Resize_50x100_flipped.png"; path = "TestData/GTMUIImage+Resize_50x100_flipped.png"; sourceTree = "<group>"; };
+ 448D61B111AC1AAD0097ACBC /* GTMUIImage+Resize_100x50_flipped.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "GTMUIImage+Resize_100x50_flipped.png"; path = "TestData/GTMUIImage+Resize_100x50_flipped.png"; sourceTree = "<group>"; };
629446170EDE177A009295EA /* GTMNSArray+Merge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSArray+Merge.h"; sourceTree = "<group>"; };
629446180EDE177A009295EA /* GTMNSArray+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSArray+Merge.m"; sourceTree = "<group>"; };
629446190EDE177A009295EA /* GTMNSArray+MergeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSArray+MergeTest.m"; sourceTree = "<group>"; };
@@ -385,6 +389,7 @@
children = (
64D0F5CC0FD3E68400506CC7 /* GTMUIImage+Resize_100x100_to_60x40.png */,
64D0F5CD0FD3E68400506CC7 /* GTMUIImage+Resize_50x100.png */,
+ 448D61B011AC1AAD0097ACBC /* GTMUIImage+Resize_50x100_flipped.png */,
64D0F5CE0FD3E68400506CC7 /* GTMUIImage+Resize_50x100_to_40x60_clip.png */,
64D0F5CF0FD3E68400506CC7 /* GTMUIImage+Resize_50x100_to_40x60_noclip.png */,
64D0F5D00FD3E68400506CC7 /* GTMUIImage+Resize_50x100_to_50x50_clip.png */,
@@ -392,6 +397,7 @@
64D0F5D20FD3E68400506CC7 /* GTMUIImage+Resize_50x100_to_60x40_clip.png */,
64D0F5D30FD3E68400506CC7 /* GTMUIImage+Resize_50x100_to_60x40_noclip.png */,
64D0F5D40FD3E68400506CC7 /* GTMUIImage+Resize_100x50.png */,
+ 448D61B111AC1AAD0097ACBC /* GTMUIImage+Resize_100x50_flipped.png */,
64D0F5D50FD3E68400506CC7 /* GTMUIImage+Resize_100x50_to_40x60_clip.png */,
64D0F5D60FD3E68400506CC7 /* GTMUIImage+Resize_100x50_to_40x60_noclip.png */,
64D0F5D70FD3E68400506CC7 /* GTMUIImage+Resize_100x50_to_50x50_clip.png */,
@@ -698,6 +704,7 @@
8BFE15C90FB0F764001BE894 /* phone.png in Resources */,
64D0F5DE0FD3E68400506CC7 /* GTMUIImage+Resize_100x100_to_60x40.png in Resources */,
64D0F5DF0FD3E68400506CC7 /* GTMUIImage+Resize_50x100.png in Resources */,
+ 448D61FC11AC1F250097ACBC /* GTMUIImage+Resize_50x100_flipped.png in Resources */,
64D0F5E00FD3E68400506CC7 /* GTMUIImage+Resize_50x100_to_40x60_clip.png in Resources */,
64D0F5E10FD3E68400506CC7 /* GTMUIImage+Resize_50x100_to_40x60_noclip.png in Resources */,
64D0F5E20FD3E68400506CC7 /* GTMUIImage+Resize_50x100_to_50x50_clip.png in Resources */,
@@ -705,6 +712,7 @@
64D0F5E40FD3E68400506CC7 /* GTMUIImage+Resize_50x100_to_60x40_clip.png in Resources */,
64D0F5E50FD3E68400506CC7 /* GTMUIImage+Resize_50x100_to_60x40_noclip.png in Resources */,
64D0F5E60FD3E68400506CC7 /* GTMUIImage+Resize_100x50.png in Resources */,
+ 448D61FB11AC1F1B0097ACBC /* GTMUIImage+Resize_100x50_flipped.png in Resources */,
64D0F5E70FD3E68400506CC7 /* GTMUIImage+Resize_100x50_to_40x60_clip.png in Resources */,
64D0F5E80FD3E68400506CC7 /* GTMUIImage+Resize_100x50_to_40x60_noclip.png in Resources */,
64D0F5E90FD3E68400506CC7 /* GTMUIImage+Resize_100x50_to_50x50_clip.png in Resources */,
diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt
index 3225d3a..d2434ae 100644
--- a/ReleaseNotes.txt
+++ b/ReleaseNotes.txt
@@ -399,7 +399,7 @@ Changes since 1.5.1
- Removed GTMTheme because it wasn't generic enough for inclusion in GTM, and
was never fully implemented
-- Added GTM_NONNULL, NS_RETURNS_RETAINED, and CF_RETURNS_RETAINED macrs to
+- Added GTM_NONNULL, NS_RETURNS_RETAINED, and CF_RETURNS_RETAINED macrs to
support clang analysis.
- Changed GTMStackTrace to put out a cleaner trace, and to work on 64 bit.
@@ -412,6 +412,11 @@ Changes since 1.5.1
- Added GTMNSAnimatablePropertyContainer methods that allow you to stop
animations properly in 10.5.
+- Added gtm_imageByRotating for rotating a UIImage. Based on code by Trevor
+ Harmon:
+ http://vocaro.com/trevor/blog/wp-content/uploads/2009/10/UIImage+Resize.h
+ http://vocaro.com/trevor/blog/wp-content/uploads/2009/10/UIImage+Resize.m
+
Release 1.5.1
Changes since 1.5.0
diff --git a/iPhone/GTMUIImage+Resize.h b/iPhone/GTMUIImage+Resize.h
index 25e2125..a1d4ed3 100644
--- a/iPhone/GTMUIImage+Resize.h
+++ b/iPhone/GTMUIImage+Resize.h
@@ -37,4 +37,15 @@
- (UIImage *)gtm_imageByResizingToSize:(CGSize)targetSize
preserveAspectRatio:(BOOL)preserveAspectRatio
trimToFit:(BOOL)trimToFit;
+
+// Returns an image rotated by |orientation| where the current orientation is
+// taken as UIImageOrientationUp. Nil if |orientation| is invalid.
+//
+// For example, UIImageOrientationRight is a 90 degree rotation clockwise,
+// UIImageOrientationDown is a 180 degree rotation closewise.
+//
+// Supplying UIImageOrientationUp to |orientation| will return a copy of the
+// image.
+- (UIImage *)gtm_imageByRotating:(UIImageOrientation)orientation;
+
@end
diff --git a/iPhone/GTMUIImage+Resize.m b/iPhone/GTMUIImage+Resize.m
index 9dd2144..49b82c8 100644
--- a/iPhone/GTMUIImage+Resize.m
+++ b/iPhone/GTMUIImage+Resize.m
@@ -17,6 +17,16 @@
//
#import "GTMUIImage+Resize.h"
+#import "GTMDefines.h"
+
+GTM_INLINE CGSize swapWidthAndHeight(CGSize size) {
+ CGFloat tempWidth = size.width;
+
+ size.width = size.height;
+ size.height = tempWidth;
+
+ return size;
+}
@implementation UIImage (GTMUIImageResizeAdditions)
@@ -83,4 +93,94 @@
UIGraphicsEndImageContext();
return resizedPhoto;
}
+
+// Based on code by Trevor Harmon:
+// http://vocaro.com/trevor/blog/wp-content/uploads/2009/10/UIImage+Resize.h
+// http://vocaro.com/trevor/blog/wp-content/uploads/2009/10/UIImage+Resize.m
+- (UIImage *)gtm_imageByRotating:(UIImageOrientation)orientation {
+ CGRect bounds = CGRectZero;
+ CGRect rect = CGRectZero;
+ CGAffineTransform transform = CGAffineTransformIdentity;
+
+ bounds.size = [self size];
+ rect.size = [self size];
+
+ switch (orientation) {
+ case UIImageOrientationUp:
+ return [UIImage imageWithCGImage:[self CGImage]];
+
+ case UIImageOrientationUpMirrored:
+ transform = CGAffineTransformMakeTranslation(rect.size.width, 0.0);
+ transform = CGAffineTransformScale(transform, -1.0, 1.0);
+ break;
+
+ case UIImageOrientationDown:
+ transform = CGAffineTransformMakeTranslation(rect.size.width,
+ rect.size.height);
+ transform = CGAffineTransformRotate(transform, M_PI);
+ break;
+
+ case UIImageOrientationDownMirrored:
+ transform = CGAffineTransformMakeTranslation(0.0, rect.size.height);
+ transform = CGAffineTransformScale(transform, 1.0, -1.0);
+ break;
+
+ case UIImageOrientationLeft:
+ bounds.size = swapWidthAndHeight(bounds.size);
+ transform = CGAffineTransformMakeTranslation(0.0, rect.size.width);
+ transform = CGAffineTransformRotate(transform, -M_PI_2);
+ break;
+
+ case UIImageOrientationLeftMirrored:
+ bounds.size = swapWidthAndHeight(bounds.size);
+ transform = CGAffineTransformMakeTranslation(rect.size.height,
+ rect.size.width);
+ transform = CGAffineTransformScale(transform, -1.0, 1.0);
+ transform = CGAffineTransformRotate(transform, -M_PI_2);
+ break;
+
+ case UIImageOrientationRight:
+ bounds.size = swapWidthAndHeight(bounds.size);
+ transform = CGAffineTransformMakeTranslation(rect.size.height, 0.0);
+ transform = CGAffineTransformRotate(transform, M_PI_2);
+ break;
+
+ case UIImageOrientationRightMirrored:
+ bounds.size = swapWidthAndHeight(bounds.size);
+ transform = CGAffineTransformMakeScale(-1.0, 1.0);
+ transform = CGAffineTransformRotate(transform, M_PI_2);
+ break;
+
+ default:
+ _GTMDevAssert(false, @"Invalid orientation %d", orientation);
+ return nil;
+ }
+
+ UIGraphicsBeginImageContext(bounds.size);
+ 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();
+
+ return rotatedImage;
+}
+
@end
diff --git a/iPhone/GTMUIImage+ResizeTest.m b/iPhone/GTMUIImage+ResizeTest.m
index 4678511..8318104 100644
--- a/iPhone/GTMUIImage+ResizeTest.m
+++ b/iPhone/GTMUIImage+ResizeTest.m
@@ -253,4 +253,30 @@
GTMUIImageResizeAssertImageEqual(actual, @"50x100_to_40x60_clip");
}
+- (void)testImageByRotating {
+ UIImage *actual = nil;
+ UIImage *landscapeImage =
+ [UIImage imageNamed:@"GTMUIImage+Resize_100x50.png"];
+ STAssertNotNil(landscapeImage, @"Unable to read image.");
+
+ // Rotate 90 degrees.
+ actual = [landscapeImage gtm_imageByRotating:UIImageOrientationRight];
+ GTMUIImageResizeAssertImageEqual(actual, @"50x100");
+
+ // Rotate 180 degrees.
+ actual = [landscapeImage gtm_imageByRotating:UIImageOrientationDown];
+ GTMUIImageResizeAssertImageEqual(actual,
+ @"100x50_flipped");
+
+
+ // Rotate 270 degrees.
+ actual = [landscapeImage gtm_imageByRotating:UIImageOrientationLeft];
+ GTMUIImageResizeAssertImageEqual(actual,
+ @"50x100_flipped");
+
+ // Rotate 360 degrees.
+ actual = [landscapeImage gtm_imageByRotating:UIImageOrientationUp];
+ GTMUIImageResizeAssertImageEqual(actual, @"100x50");
+}
+
@end
diff --git a/iPhone/TestData/GTMUIImage+Resize_100x50_flipped.png b/iPhone/TestData/GTMUIImage+Resize_100x50_flipped.png
new file mode 100644
index 0000000..c6b1d8f
--- /dev/null
+++ b/iPhone/TestData/GTMUIImage+Resize_100x50_flipped.png
Binary files differ
diff --git a/iPhone/TestData/GTMUIImage+Resize_50x100_flipped.png b/iPhone/TestData/GTMUIImage+Resize_50x100_flipped.png
new file mode 100644
index 0000000..bdce5a2
--- /dev/null
+++ b/iPhone/TestData/GTMUIImage+Resize_50x100_flipped.png
Binary files differ