// // UIImage+Common.m // CommonLibrary // // Created by Alexi on 13-11-6. // Copyright (c) 2013年 ywchen. All rights reserved. // #import "UIImage+Common.h" #import "UIImage+Alpha.h" #import "PathUtility.h" #import "NSString+Common.h" @implementation UIImage (Common) - (UIImage *)fixOrientation { // No-op if the orientation is already correct if (self.imageOrientation == UIImageOrientationUp) return self; // We need to calculate the proper transformation to make the image upright. // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored. CGAffineTransform transform = CGAffineTransformIdentity; switch (self.imageOrientation) { case UIImageOrientationDown: case UIImageOrientationDownMirrored: transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height); transform = CGAffineTransformRotate(transform, M_PI); break; case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: transform = CGAffineTransformTranslate(transform, self.size.width, 0); transform = CGAffineTransformRotate(transform, M_PI_2); break; case UIImageOrientationRight: case UIImageOrientationRightMirrored: transform = CGAffineTransformTranslate(transform, 0, self.size.height); transform = CGAffineTransformRotate(transform, -M_PI_2); break; default: break; } switch (self.imageOrientation) { case UIImageOrientationUpMirrored: case UIImageOrientationDownMirrored: transform = CGAffineTransformTranslate(transform, self.size.width, 0); transform = CGAffineTransformScale(transform, -1, 1); break; case UIImageOrientationLeftMirrored: case UIImageOrientationRightMirrored: transform = CGAffineTransformTranslate(transform, self.size.height, 0); transform = CGAffineTransformScale(transform, -1, 1); break; default: break; } // Now we draw the underlying CGImage into a new context, applying the transform // calculated above. CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height, CGImageGetBitsPerComponent(self.CGImage), 0, CGImageGetColorSpace(self.CGImage), CGImageGetBitmapInfo(self.CGImage)); CGContextConcatCTM(ctx, transform); switch (self.imageOrientation) { case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: case UIImageOrientationRight: case UIImageOrientationRightMirrored: // Grr... CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage); break; default: CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage); break; } // And now we just create a new UIImage from the drawing context CGImageRef cgimg = CGBitmapContextCreateImage(ctx); UIImage *img = [UIImage imageWithCGImage:cgimg]; CGContextRelease(ctx); CGImageRelease(cgimg); return img; } - (UIImage *)thumbnailWithSize:(CGSize)asize { UIImage *newimage = nil; UIGraphicsBeginImageContext(asize); [self drawInRect:CGRectMake(0, 0, asize.width, asize.height)]; newimage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newimage; } - (UIImage *)rescaleImageToSize:(CGSize)size { CGFloat scale = [[UIScreen mainScreen] scale]; CGRect rect = CGRectMake(0.0, 0.0, size.width * scale, size.height * scale); UIGraphicsBeginImageContext(rect.size); [self drawInRect:rect]; // scales image to rect UIImage *resImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return resImage; } - (UIImage *)cropImageToRect:(CGRect)cropRect { // Begin the drawing (again) UIGraphicsBeginImageContext(cropRect.size); CGContextRef ctx = UIGraphicsGetCurrentContext(); // Tanslate and scale upside-down to compensate for Quartz's inverted coordinate system CGContextTranslateCTM(ctx, 0.0, cropRect.size.height); CGContextScaleCTM(ctx, 1.0, -1.0); // Draw view into context CGRect drawRect = CGRectMake(-cropRect.origin.x, cropRect.origin.y - (self.size.height - cropRect.size.height) , self.size.width, self.size.height); CGContextDrawImage(ctx, drawRect, self.CGImage); // Create the new UIImage from the context UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); // End the drawing UIGraphicsEndImageContext(); return newImage; } - (CGSize)calculateNewSizeForCroppingBox:(CGSize)croppingBox { // Make the shortest side be equivalent to the cropping box. CGFloat newHeight, newWidth; if (self.size.width < self.size.height) { newWidth = croppingBox.width; newHeight = (self.size.height / self.size.width) * croppingBox.width; } else { newHeight = croppingBox.height; newWidth = (self.size.width / self.size.height) *croppingBox.height; } return CGSizeMake(newWidth, newHeight); } - (UIImage *)cropCenterAndScaleImageToSize:(CGSize)cropSize { UIImage *scaledImage = [self rescaleImageToSize:[self calculateNewSizeForCroppingBox:cropSize]]; return [scaledImage cropImageToRect:CGRectMake((scaledImage.size.width-cropSize.width)/2, (scaledImage.size.height-cropSize.height)/2, cropSize.width, cropSize.height)]; } - (UIImage *)cropToSquareImage { CGSize theimageSize = self.size; if (theimageSize.width != theimageSize.height) { CGFloat theimageHeight = theimageSize.width > theimageSize.height ? theimageSize.height : theimageSize.width; return [self cropCenterAndScaleImageToSize:CGSizeMake(theimageHeight, theimageHeight)]; } else { return self; } } - (void)saveToCacheWithKey:(NSString *)key { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSString *tmpPath = [PathUtility imageCachePath]; NSString *imagePath = [NSString stringWithFormat:@"%@/%@", tmpPath, [key md5]]; NSData *data = nil; if (UIImagePNGRepresentation(self) == nil) { data = UIImageJPEGRepresentation(self, 1); } else { data = UIImagePNGRepresentation(self); } [data writeToFile:imagePath atomically:YES]; }); } + (UIImage *)loadFromCacheWithKey:(NSString *)key { NSString *tmpPath = [PathUtility imageCachePath]; NSString *imagePath = [NSString stringWithFormat:@"%@/%@", tmpPath, [key md5]]; return [UIImage imageWithContentsOfFile:imagePath]; } + (UIImage *)imageWithColor:(UIColor *)color { return [UIImage imageWithColor:color size:CGSizeMake(1, 1)]; } + (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size { if (color == nil) { return nil; } CGRect rect=CGRectMake(0.0f, 0.0f, size.width, size.height); UIGraphicsBeginImageContext(rect.size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(context, [color CGColor]); CGContextFillRect(context, rect); UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return theImage; } + (UIImage *)randomColorImageWith:(CGSize)size { UIColor *randomColor = [UIColor randomFlatColor]; return [UIImage imageWithColor:randomColor size:size]; } - (UIImage *)croppedImage:(CGRect)bounds { CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], bounds); UIImage *croppedImage = [UIImage imageWithCGImage:imageRef]; CGImageRelease(imageRef); return croppedImage; } @end //======================================================= @implementation UIImage (Cut) - (UIImage *)clipImageWithScaleWithsize:(CGSize)asize { UIImage *newimage; UIImage *image = self; if (nil == image) { return nil; } CGSize oldsize = image.size; CGRect rect; if (asize.width/asize.height > oldsize.width/oldsize.height) { rect.size.width = asize.width; rect.size.height = asize.width*oldsize.height/oldsize.width; rect.origin.x = 0; rect.origin.y = (asize.height - rect.size.height)/2; } else { rect.size.width = asize.height*oldsize.width/oldsize.height; rect.size.height = asize.height; rect.origin.x = (asize.width - rect.size.width)/2; rect.origin.y = 0; } UIGraphicsBeginImageContext(asize); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextClipToRect(context, CGRectMake(0, 0, asize.width, asize.height)); CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]); UIRectFill(CGRectMake(0, 0, asize.width, asize.height));//clear background [image drawInRect:rect]; newimage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newimage; } - (UIImage *)clipImageWithScaleWithsize:(CGSize)asize roundedCornerImage:(NSInteger)roundedCornerImage borderSize:(NSInteger)borderSize { UIImage *image = [self clipImageWithScaleWithsize:asize]; return [image roundedCornerImage:roundedCornerImage borderSize:borderSize]; } @end //============================================= @implementation UIImage (Resize) // 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 copy of this image that is squared to the thumbnail size. // If transparentBorder is non-zero, a transparent border of the given size will be added around the edges of the thumbnail. (Adding a transparent border of at least one pixel in size has the side-effect of antialiasing the edges of the image when rotating it using Core Animation.) - (UIImage *)thumbnailImage:(NSInteger)thumbnailSize transparentBorder:(NSUInteger)borderSize cornerRadius:(NSUInteger)cornerRadius interpolationQuality:(CGInterpolationQuality)quality { UIImage *resizedImage = [self resizedImageWithContentMode:UIViewContentModeScaleAspectFill bounds:CGSizeMake(thumbnailSize, thumbnailSize) interpolationQuality:quality]; // Crop out any part of the image that's larger than the thumbnail size // The cropped rect must be centered on the resized image // Round the origin points so that the size isn't altered when CGRectIntegral is later invoked CGRect cropRect = CGRectMake(round((resizedImage.size.width - thumbnailSize) / 2), round((resizedImage.size.height - thumbnailSize) / 2), thumbnailSize, thumbnailSize); UIImage *croppedImage = [resizedImage croppedImage:cropRect]; UIImage *transparentBorderImage = borderSize ? [croppedImage transparentBorderImage:borderSize] : croppedImage; return [transparentBorderImage roundedCornerImage:cornerRadius borderSize:borderSize]; } // 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 = 1.0; switch (contentMode) { case UIViewContentModeScaleAspectFill: ratio = MAX(horizontalRatio, verticalRatio); break; case UIViewContentModeScaleAspectFit: ratio = MIN(horizontalRatio, verticalRatio); break; default: break; } CGSize newSize = CGSizeMake(self.size.width * ratio, self.size.height * ratio); return [self resizedImage:newSize interpolationQuality:quality]; } #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; } - (UIImage *)resizedImageInRect:(CGRect)newRect transform:(CGAffineTransform)transform drawTransposed:(BOOL)transpose interpolationQuality:(CGInterpolationQuality)quality { 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; default: 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; default: break; } return transform; } @end //================================================= @implementation UIImage (RoundedCorner) // Creates a copy of this image with rounded corners // If borderSize is non-zero, a transparent border of the given size will also be added // Original author: Björn Sållarp. Used with permission. See: http://blog.sallarp.com/iphone-uiimage-round-corners/ - (UIImage *)roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize { // If the image does not have an alpha layer, add one UIImage *image = [self imageWithAlpha]; // Build a context that's the same dimensions as the new size CGContextRef context = CGBitmapContextCreate(NULL, image.size.width, image.size.height, CGImageGetBitsPerComponent(image.CGImage), 0, CGImageGetColorSpace(image.CGImage), CGImageGetBitmapInfo(image.CGImage)); // Create a clipping path with rounded corners CGContextBeginPath(context); [self addRoundedRectToPath:CGRectMake(borderSize, borderSize, image.size.width - borderSize * 2, image.size.height - borderSize * 2) context:context ovalWidth:cornerSize ovalHeight:cornerSize]; CGContextClosePath(context); CGContextClip(context); // Draw the image to the context; the clipping path will make anything outside the rounded rect transparent CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage); // Create a CGImage from the context CGImageRef clippedImage = CGBitmapContextCreateImage(context); CGContextRelease(context); // Create a UIImage from the CGImage UIImage *roundedImage = [UIImage imageWithCGImage:clippedImage]; CGImageRelease(clippedImage); return roundedImage; } #pragma mark - #pragma mark Private helper methods // Adds a rectangular path to the given context and rounds its corners by the given extents // Original author: Björn Sållarp. Used with permission. See: http://blog.sallarp.com/iphone-uiimage-round-corners/ - (void)addRoundedRectToPath:(CGRect)rect context:(CGContextRef)context ovalWidth:(CGFloat)ovalWidth ovalHeight:(CGFloat)ovalHeight { if (ovalWidth == 0 || ovalHeight == 0) { CGContextAddRect(context, rect); return; } CGContextSaveGState(context); CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect)); CGContextScaleCTM(context, ovalWidth, ovalHeight); CGFloat fw = CGRectGetWidth(rect) / ovalWidth; CGFloat fh = CGRectGetHeight(rect) / ovalHeight; CGContextMoveToPoint(context, fw, fh/2); CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); CGContextClosePath(context); CGContextRestoreGState(context); } @end //=========================================== @implementation UIImage (SplitImageIntoTwoParts) #define SAWTOOTH_COUNT 10 #define SAWTOOTH_WIDTH_FACTOR 20 + (NSArray *)splitImageIntoTwoParts:(UIImage *)image { CGFloat scale = [[UIScreen mainScreen] scale]; NSMutableArray *array = [NSMutableArray arrayWithCapacity:2]; CGFloat width, height, widthgap, heightgap; int piceCount = SAWTOOTH_COUNT; width = image.size.width; height = image.size.height; widthgap = width/SAWTOOTH_WIDTH_FACTOR; heightgap = height/piceCount; // CGRect rect = CGRectMake(0, 0, width, height); CGContextRef context; CGImageRef imageMasked; UIImage *leftImage,*rightImage; //part one UIGraphicsBeginImageContext(CGSizeMake(width*scale, height*scale)); context = UIGraphicsGetCurrentContext(); CGContextScaleCTM(context, scale, scale); CGContextMoveToPoint(context, 0, 0); int a=-1; for (int i=0; i