// // GTMUIImage+Resize.m // // Copyright 2009 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. // #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) - (UIImage *)gtm_imageByResizingToSize:(CGSize)targetSize preserveAspectRatio:(BOOL)preserveAspectRatio trimToFit:(BOOL)trimToFit { CGSize imageSize = [self size]; if (imageSize.height < 1 || imageSize.width < 1) { return nil; } if (targetSize.height < 1 || targetSize.width < 1) { return nil; } CGFloat aspectRatio = imageSize.width / imageSize.height; CGFloat targetAspectRatio = targetSize.width / targetSize.height; CGRect projectTo = CGRectZero; if (preserveAspectRatio) { if (trimToFit) { // Scale and clip image so that the aspect ratio is preserved and the // target size is filled. if (targetAspectRatio < aspectRatio) { // clip the x-axis. projectTo.size.width = targetSize.height * aspectRatio; projectTo.size.height = targetSize.height; projectTo.origin.x = (targetSize.width - projectTo.size.width) / 2; projectTo.origin.y = 0; } else { // clip the y-axis. projectTo.size.width = targetSize.width; projectTo.size.height = targetSize.width / aspectRatio; projectTo.origin.x = 0; projectTo.origin.y = (targetSize.height - projectTo.size.height) / 2; } } else { // Scale image to ensure it fits inside the specified targetSize. if (targetAspectRatio < aspectRatio) { // target is less wide than the original. projectTo.size.width = targetSize.width; projectTo.size.height = projectTo.size.width / aspectRatio; targetSize = projectTo.size; } else { // target is wider than the original. projectTo.size.height = targetSize.height; projectTo.size.width = projectTo.size.height * aspectRatio; targetSize = projectTo.size; } } // if (clip) } else { // Don't preserve the aspect ratio. projectTo.size = targetSize; } projectTo = CGRectIntegral(projectTo); // There's no CGSizeIntegral, so we fake our own. CGRect integralRect = CGRectZero; integralRect.size = targetSize; targetSize = CGRectIntegral(integralRect).size; // Resize photo. Use UIImage drawing methods because they respect // UIImageOrientation as opposed to CGContextDrawImage(). UIGraphicsBeginImageContext(targetSize); [self drawInRect:projectTo]; UIImage* resizedPhoto = UIGraphicsGetImageFromCurrentImageContext(); 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 %ld", (long)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(); return rotatedImage; } @end