Skip to content
Open
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
21 changes: 20 additions & 1 deletion UIImage+Transforms.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,33 @@

+ (UIImage *)blankImage;
+ (UIImage *)imageOfColor:(UIColor *)color;
+ (UIImage*) grayishImage: (UIImage*) inputImage;
- (UIImage *)tintedGradientImageWithColor:(UIColor *)tintColor;
- (UIImage *)tintedImageWithColor:(UIColor *)tintColor;
- (UIImage *)imageScaledToSize:(CGSize)size;
- (UIImage *)imageSmoothlyScaledToSize:(CGSize)size;
+ (UIImage *)imageFromLayer:(CALayer *)layer;
+ (UIImage *)paddedImage:(UIImage *)image paddingInsets:(UIEdgeInsets)insets;
+ (UIImage *)stitchImages:(NSArray *)images vertically:(BOOL)vertically;
- (UIImage *)colorizeImageWithColor:(UIColor *)color;
- (UIImage *)colorizeImageWithColor:(UIColor *)color withBlendMode:(CGBlendMode)blendMode;
+ (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage ;





- (UIImage *)croppedImage:(CGRect)bounds;
- (UIImage *)thumbnailImage:(NSInteger)thumbnailSize
transparentBorder:(NSUInteger)borderSize
cornerRadius:(NSUInteger)cornerRadius
interpolationQuality:(CGInterpolationQuality)quality;
- (UIImage *)resizedImage:(CGSize)newSize
interpolationQuality:(CGInterpolationQuality)quality;
- (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode
bounds:(CGSize)bounds
interpolationQuality:(CGInterpolationQuality)quality;
- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize;



@end
295 changes: 274 additions & 21 deletions UIImage+Transforms.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@

#import "UIImage+Transforms.h"


@interface UIImage ()
- (UIImage *)resizedImage:(CGSize)newSize
transform:(CGAffineTransform)transform
drawTransposed:(BOOL)transpose
interpolationQuality:(CGInterpolationQuality)quality;
- (CGAffineTransform)transformForOrientation:(CGSize)newSize;
@end


@implementation UIImage (Transforms)

+ (UIImage *)blankImage
Expand All @@ -32,6 +42,23 @@ + (UIImage *)imageOfColor:(UIColor *)color

return image;
}
+ (UIImage*) grayishImage: (UIImage*) inputImage {

// Create a graphic context.
UIGraphicsBeginImageContextWithOptions(inputImage.size, YES, 1.0);
CGRect imageRect = CGRectMake(0, 0, inputImage.size.width, inputImage.size.height);

// Draw the image with the luminosity blend mode.
// On top of a white background, this will give a black and white image.
[inputImage drawInRect:imageRect blendMode:kCGBlendModeLuminosity alpha:1.0];

// Get the resulting image.
UIImage *filteredImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return filteredImage;

}

- (UIImage *)tintedGradientImageWithColor:(UIColor *)tintColor
{
Expand Down Expand Up @@ -173,27 +200,6 @@ - (UIImage *)colorizeImageWithColor:(UIColor *)color withBlendMode:(CGBlendMode)

}

+ (UIImage *)paddedImage:(UIImage *)image paddingInsets:(UIEdgeInsets)insets
{
// UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)
// leftPadding:(CGFloat)left rightPadding:(CGFloat)right topPadding:(CGFloat)top bottomPadding:(CGFloat)bottom
CGFloat const width = image.size.width+insets.left+insets.right;
CGFloat const height = image.size.height+insets.top+insets.bottom;

UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
UIGraphicsPushContext(context);

CGPoint origin = CGPointMake(insets.left, insets.top);
[image drawAtPoint:origin];

UIGraphicsPopContext();
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return newImage;
}


////////////////////////////////////////////////////////////////////////////////
#pragma mark - Private methods
Expand All @@ -215,4 +221,251 @@ - (UIImage *)tintedImageWithColor:(UIColor *)tintColor blendingMode:(CGBlendMode
return tintedImage;
}

+ (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {

CGImageRef maskRef = maskImage.CGImage;

CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);

CGImageRef masked = CGImageCreateWithMask([image CGImage], mask);
return [UIImage imageWithCGImage:masked];
}















// Returns a copy of this image that is cropped to the given bounds.
// The bounds will be adjusted using CGRectIntegral.
// This method ignores the image's imageOrientation setting.
- (UIImage *)croppedImage:(CGRect)bounds {
CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], bounds);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return croppedImage;
}


// Returns a rescaled copy of the image, taking into account its orientation
// The image will be scaled disproportionately if necessary to fit the bounds specified by the parameter
- (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality {
BOOL drawTransposed;

switch (self.imageOrientation) {
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
drawTransposed = YES;
break;

default:
drawTransposed = NO;
}

return [self resizedImage:newSize
transform:[self transformForOrientation:newSize]
drawTransposed:drawTransposed
interpolationQuality:quality];
}

// Resizes the image according to the given content mode, taking into account the image's orientation
- (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode
bounds:(CGSize)bounds
interpolationQuality:(CGInterpolationQuality)quality {
CGFloat horizontalRatio = bounds.width / self.size.width;
CGFloat verticalRatio = bounds.height / self.size.height;
CGFloat ratio;

switch (contentMode) {
case UIViewContentModeScaleAspectFill:
ratio = MAX(horizontalRatio, verticalRatio);
break;

case UIViewContentModeScaleAspectFit:
ratio = MIN(horizontalRatio, verticalRatio);
break;

default:
[NSException raise:NSInvalidArgumentException format:@"Unsupported content mode: %d", contentMode];
}

CGSize newSize = CGSizeMake(self.size.width * ratio, self.size.height * ratio);

return [self resizedImage:newSize interpolationQuality:quality];
}



- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize
{
UIImage *sourceImage = self;
UIImage *newImage = nil;
CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

if (CGSizeEqualToSize(imageSize, targetSize) == NO)
{
CGFloat widthFactor = targetWidth / width;
CGFloat heightFactor = targetHeight / height;

if (widthFactor > heightFactor)
{
scaleFactor = widthFactor; // scale to fit height
}
else
{
scaleFactor = heightFactor; // scale to fit width
}

scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;

// center the image
if (widthFactor > heightFactor)
{
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
}
else
{
if (widthFactor < heightFactor)
{
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
}
}

UIGraphicsBeginImageContext(targetSize); // this will crop

CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width = scaledWidth;
thumbnailRect.size.height = scaledHeight;

[sourceImage drawInRect:thumbnailRect];

newImage = UIGraphicsGetImageFromCurrentImageContext();

if(newImage == nil)
{
NSLog(@"could not scale image");
}

//pop the context to get back to the default
UIGraphicsEndImageContext();

return newImage;
}

#pragma mark -
#pragma mark Private helper methods

// Returns a copy of the image that has been transformed using the given affine transform and scaled to the new size
// The new image's orientation will be UIImageOrientationUp, regardless of the current image's orientation
// If the new size is not integral, it will be rounded up
- (UIImage *)resizedImage:(CGSize)newSize
transform:(CGAffineTransform)transform
drawTransposed:(BOOL)transpose
interpolationQuality:(CGInterpolationQuality)quality {
CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
CGRect transposedRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width);
CGImageRef imageRef = self.CGImage;

// Build a context that's the same dimensions as the new size
CGContextRef bitmap = CGBitmapContextCreate(NULL,
newRect.size.width,
newRect.size.height,
CGImageGetBitsPerComponent(imageRef),
0,
CGImageGetColorSpace(imageRef),
CGImageGetBitmapInfo(imageRef));

// Rotate and/or flip the image if required by its orientation
CGContextConcatCTM(bitmap, transform);

// Set the quality level to use when rescaling
CGContextSetInterpolationQuality(bitmap, quality);

// Draw into the context; this scales the image
CGContextDrawImage(bitmap, transpose ? transposedRect : newRect, imageRef);

// Get the resized image from the context and a UIImage
CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

// Clean up
CGContextRelease(bitmap);
CGImageRelease(newImageRef);

return newImage;
}

// Returns an affine transform that takes into account the image orientation when drawing a scaled image
- (CGAffineTransform)transformForOrientation:(CGSize)newSize {
CGAffineTransform transform = CGAffineTransformIdentity;

switch (self.imageOrientation) {
case UIImageOrientationDown: // EXIF = 3
case UIImageOrientationDownMirrored: // EXIF = 4
transform = CGAffineTransformTranslate(transform, newSize.width, newSize.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;

case UIImageOrientationLeft: // EXIF = 6
case UIImageOrientationLeftMirrored: // EXIF = 5
transform = CGAffineTransformTranslate(transform, newSize.width, 0);
transform = CGAffineTransformRotate(transform, M_PI_2);
break;

case UIImageOrientationRight: // EXIF = 8
case UIImageOrientationRightMirrored: // EXIF = 7
transform = CGAffineTransformTranslate(transform, 0, newSize.height);
transform = CGAffineTransformRotate(transform, -M_PI_2);
break;
}

switch (self.imageOrientation) {
case UIImageOrientationUpMirrored: // EXIF = 2
case UIImageOrientationDownMirrored: // EXIF = 4
transform = CGAffineTransformTranslate(transform, newSize.width, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;

case UIImageOrientationLeftMirrored: // EXIF = 5
case UIImageOrientationRightMirrored: // EXIF = 7
transform = CGAffineTransformTranslate(transform, newSize.height, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;
}

return transform;
}






@end