UIImage+Common.m 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. //
  2. // UIImage+Common.m
  3. // CommonLibrary
  4. //
  5. // Created by Alexi on 13-11-6.
  6. // Copyright (c) 2013年 ywchen. All rights reserved.
  7. //
  8. #import "UIImage+Common.h"
  9. #import "UIImage+Alpha.h"
  10. #import "PathUtility.h"
  11. #import "NSString+Common.h"
  12. @implementation UIImage (Common)
  13. - (UIImage *)fixOrientation
  14. {
  15. // No-op if the orientation is already correct
  16. if (self.imageOrientation == UIImageOrientationUp) return self;
  17. // We need to calculate the proper transformation to make the image upright.
  18. // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
  19. CGAffineTransform transform = CGAffineTransformIdentity;
  20. switch (self.imageOrientation)
  21. {
  22. case UIImageOrientationDown:
  23. case UIImageOrientationDownMirrored:
  24. transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);
  25. transform = CGAffineTransformRotate(transform, M_PI);
  26. break;
  27. case UIImageOrientationLeft:
  28. case UIImageOrientationLeftMirrored:
  29. transform = CGAffineTransformTranslate(transform, self.size.width, 0);
  30. transform = CGAffineTransformRotate(transform, M_PI_2);
  31. break;
  32. case UIImageOrientationRight:
  33. case UIImageOrientationRightMirrored:
  34. transform = CGAffineTransformTranslate(transform, 0, self.size.height);
  35. transform = CGAffineTransformRotate(transform, -M_PI_2);
  36. break;
  37. default:
  38. break;
  39. }
  40. switch (self.imageOrientation)
  41. {
  42. case UIImageOrientationUpMirrored:
  43. case UIImageOrientationDownMirrored:
  44. transform = CGAffineTransformTranslate(transform, self.size.width, 0);
  45. transform = CGAffineTransformScale(transform, -1, 1);
  46. break;
  47. case UIImageOrientationLeftMirrored:
  48. case UIImageOrientationRightMirrored:
  49. transform = CGAffineTransformTranslate(transform, self.size.height, 0);
  50. transform = CGAffineTransformScale(transform, -1, 1);
  51. break;
  52. default:
  53. break;
  54. }
  55. // Now we draw the underlying CGImage into a new context, applying the transform
  56. // calculated above.
  57. CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height, CGImageGetBitsPerComponent(self.CGImage), 0, CGImageGetColorSpace(self.CGImage), CGImageGetBitmapInfo(self.CGImage));
  58. CGContextConcatCTM(ctx, transform);
  59. switch (self.imageOrientation)
  60. {
  61. case UIImageOrientationLeft:
  62. case UIImageOrientationLeftMirrored:
  63. case UIImageOrientationRight:
  64. case UIImageOrientationRightMirrored:
  65. // Grr...
  66. CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);
  67. break;
  68. default:
  69. CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage);
  70. break;
  71. }
  72. // And now we just create a new UIImage from the drawing context
  73. CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
  74. UIImage *img = [UIImage imageWithCGImage:cgimg];
  75. CGContextRelease(ctx);
  76. CGImageRelease(cgimg);
  77. return img;
  78. }
  79. - (UIImage *)thumbnailWithSize:(CGSize)asize
  80. {
  81. UIImage *newimage = nil;
  82. UIGraphicsBeginImageContext(asize);
  83. [self drawInRect:CGRectMake(0, 0, asize.width, asize.height)];
  84. newimage = UIGraphicsGetImageFromCurrentImageContext();
  85. UIGraphicsEndImageContext();
  86. return newimage;
  87. }
  88. - (UIImage *)rescaleImageToSize:(CGSize)size
  89. {
  90. CGFloat scale = [[UIScreen mainScreen] scale];
  91. CGRect rect = CGRectMake(0.0, 0.0, size.width * scale, size.height * scale);
  92. UIGraphicsBeginImageContext(rect.size);
  93. [self drawInRect:rect]; // scales image to rect
  94. UIImage *resImage = UIGraphicsGetImageFromCurrentImageContext();
  95. UIGraphicsEndImageContext();
  96. return resImage;
  97. }
  98. - (UIImage *)cropImageToRect:(CGRect)cropRect
  99. {
  100. // Begin the drawing (again)
  101. UIGraphicsBeginImageContext(cropRect.size);
  102. CGContextRef ctx = UIGraphicsGetCurrentContext();
  103. // Tanslate and scale upside-down to compensate for Quartz's inverted coordinate system
  104. CGContextTranslateCTM(ctx, 0.0, cropRect.size.height);
  105. CGContextScaleCTM(ctx, 1.0, -1.0);
  106. // Draw view into context
  107. CGRect drawRect = CGRectMake(-cropRect.origin.x, cropRect.origin.y - (self.size.height - cropRect.size.height) , self.size.width, self.size.height);
  108. CGContextDrawImage(ctx, drawRect, self.CGImage);
  109. // Create the new UIImage from the context
  110. UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
  111. // End the drawing
  112. UIGraphicsEndImageContext();
  113. return newImage;
  114. }
  115. - (CGSize)calculateNewSizeForCroppingBox:(CGSize)croppingBox
  116. {
  117. // Make the shortest side be equivalent to the cropping box.
  118. CGFloat newHeight, newWidth;
  119. if (self.size.width < self.size.height) {
  120. newWidth = croppingBox.width;
  121. newHeight = (self.size.height / self.size.width) * croppingBox.width;
  122. } else {
  123. newHeight = croppingBox.height;
  124. newWidth = (self.size.width / self.size.height) *croppingBox.height;
  125. }
  126. return CGSizeMake(newWidth, newHeight);
  127. }
  128. - (UIImage *)cropCenterAndScaleImageToSize:(CGSize)cropSize
  129. {
  130. UIImage *scaledImage = [self rescaleImageToSize:[self calculateNewSizeForCroppingBox:cropSize]];
  131. return [scaledImage cropImageToRect:CGRectMake((scaledImage.size.width-cropSize.width)/2, (scaledImage.size.height-cropSize.height)/2, cropSize.width, cropSize.height)];
  132. }
  133. - (UIImage *)cropToSquareImage
  134. {
  135. CGSize theimageSize = self.size;
  136. if (theimageSize.width != theimageSize.height)
  137. {
  138. CGFloat theimageHeight = theimageSize.width > theimageSize.height ? theimageSize.height : theimageSize.width;
  139. return [self cropCenterAndScaleImageToSize:CGSizeMake(theimageHeight, theimageHeight)];
  140. }
  141. else
  142. {
  143. return self;
  144. }
  145. }
  146. - (void)saveToCacheWithKey:(NSString *)key
  147. {
  148. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  149. NSString *tmpPath = [PathUtility imageCachePath];
  150. NSString *imagePath = [NSString stringWithFormat:@"%@/%@", tmpPath, [key md5]];
  151. NSData *data = nil;
  152. if (UIImagePNGRepresentation(self) == nil)
  153. {
  154. data = UIImageJPEGRepresentation(self, 1);
  155. }
  156. else
  157. {
  158. data = UIImagePNGRepresentation(self);
  159. }
  160. [data writeToFile:imagePath atomically:YES];
  161. });
  162. }
  163. + (UIImage *)loadFromCacheWithKey:(NSString *)key
  164. {
  165. NSString *tmpPath = [PathUtility imageCachePath];
  166. NSString *imagePath = [NSString stringWithFormat:@"%@/%@", tmpPath, [key md5]];
  167. return [UIImage imageWithContentsOfFile:imagePath];
  168. }
  169. + (UIImage *)imageWithColor:(UIColor *)color
  170. {
  171. return [UIImage imageWithColor:color size:CGSizeMake(1, 1)];
  172. }
  173. + (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size
  174. {
  175. if (color == nil) {
  176. return nil;
  177. }
  178. CGRect rect=CGRectMake(0.0f, 0.0f, size.width, size.height);
  179. UIGraphicsBeginImageContext(rect.size);
  180. CGContextRef context = UIGraphicsGetCurrentContext();
  181. CGContextSetFillColorWithColor(context, [color CGColor]);
  182. CGContextFillRect(context, rect);
  183. UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
  184. UIGraphicsEndImageContext();
  185. return theImage;
  186. }
  187. + (UIImage *)randomColorImageWith:(CGSize)size
  188. {
  189. UIColor *randomColor = [UIColor randomFlatColor];
  190. return [UIImage imageWithColor:randomColor size:size];
  191. }
  192. - (UIImage *)croppedImage:(CGRect)bounds
  193. {
  194. CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], bounds);
  195. UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
  196. CGImageRelease(imageRef);
  197. return croppedImage;
  198. }
  199. @end
  200. //=======================================================
  201. @implementation UIImage (Cut)
  202. - (UIImage *)clipImageWithScaleWithsize:(CGSize)asize
  203. {
  204. UIImage *newimage;
  205. UIImage *image = self;
  206. if (nil == image)
  207. {
  208. return nil;
  209. }
  210. CGSize oldsize = image.size;
  211. CGRect rect;
  212. if (asize.width/asize.height > oldsize.width/oldsize.height)
  213. {
  214. rect.size.width = asize.width;
  215. rect.size.height = asize.width*oldsize.height/oldsize.width;
  216. rect.origin.x = 0;
  217. rect.origin.y = (asize.height - rect.size.height)/2;
  218. }
  219. else
  220. {
  221. rect.size.width = asize.height*oldsize.width/oldsize.height;
  222. rect.size.height = asize.height;
  223. rect.origin.x = (asize.width - rect.size.width)/2;
  224. rect.origin.y = 0;
  225. }
  226. UIGraphicsBeginImageContext(asize);
  227. CGContextRef context = UIGraphicsGetCurrentContext();
  228. CGContextClipToRect(context, CGRectMake(0, 0, asize.width, asize.height));
  229. CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
  230. UIRectFill(CGRectMake(0, 0, asize.width, asize.height));//clear background
  231. [image drawInRect:rect];
  232. newimage = UIGraphicsGetImageFromCurrentImageContext();
  233. UIGraphicsEndImageContext();
  234. return newimage;
  235. }
  236. - (UIImage *)clipImageWithScaleWithsize:(CGSize)asize roundedCornerImage:(NSInteger)roundedCornerImage borderSize:(NSInteger)borderSize
  237. {
  238. UIImage *image = [self clipImageWithScaleWithsize:asize];
  239. return [image roundedCornerImage:roundedCornerImage borderSize:borderSize];
  240. }
  241. @end
  242. //=============================================
  243. @implementation UIImage (Resize)
  244. // Returns a copy of this image that is cropped to the given bounds.
  245. // The bounds will be adjusted using CGRectIntegral.
  246. // This method ignores the image's imageOrientation setting.
  247. - (UIImage *)croppedImage:(CGRect)bounds
  248. {
  249. CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], bounds);
  250. UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
  251. CGImageRelease(imageRef);
  252. return croppedImage;
  253. }
  254. // Returns a copy of this image that is squared to the thumbnail size.
  255. // 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.)
  256. - (UIImage *)thumbnailImage:(NSInteger)thumbnailSize transparentBorder:(NSUInteger)borderSize cornerRadius:(NSUInteger)cornerRadius interpolationQuality:(CGInterpolationQuality)quality
  257. {
  258. UIImage *resizedImage = [self resizedImageWithContentMode:UIViewContentModeScaleAspectFill bounds:CGSizeMake(thumbnailSize, thumbnailSize) interpolationQuality:quality];
  259. // Crop out any part of the image that's larger than the thumbnail size
  260. // The cropped rect must be centered on the resized image
  261. // Round the origin points so that the size isn't altered when CGRectIntegral is later invoked
  262. CGRect cropRect = CGRectMake(round((resizedImage.size.width - thumbnailSize) / 2), round((resizedImage.size.height - thumbnailSize) / 2), thumbnailSize, thumbnailSize);
  263. UIImage *croppedImage = [resizedImage croppedImage:cropRect];
  264. UIImage *transparentBorderImage = borderSize ? [croppedImage transparentBorderImage:borderSize] : croppedImage;
  265. return [transparentBorderImage roundedCornerImage:cornerRadius borderSize:borderSize];
  266. }
  267. // Returns a rescaled copy of the image, taking into account its orientation
  268. // The image will be scaled disproportionately if necessary to fit the bounds specified by the parameter
  269. - (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality {
  270. BOOL drawTransposed;
  271. switch (self.imageOrientation)
  272. {
  273. case UIImageOrientationLeft:
  274. case UIImageOrientationLeftMirrored:
  275. case UIImageOrientationRight:
  276. case UIImageOrientationRightMirrored:
  277. drawTransposed = YES;
  278. break;
  279. default:
  280. drawTransposed = NO;
  281. }
  282. return [self resizedImage:newSize transform:[self transformForOrientation:newSize] drawTransposed:drawTransposed
  283. interpolationQuality:quality];
  284. }
  285. // Resizes the image according to the given content mode, taking into account the image's orientation
  286. - (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode bounds:(CGSize)bounds interpolationQuality:(CGInterpolationQuality)quality
  287. {
  288. CGFloat horizontalRatio = bounds.width / self.size.width;
  289. CGFloat verticalRatio = bounds.height / self.size.height;
  290. CGFloat ratio = 1.0;
  291. switch (contentMode)
  292. {
  293. case UIViewContentModeScaleAspectFill:
  294. ratio = MAX(horizontalRatio, verticalRatio);
  295. break;
  296. case UIViewContentModeScaleAspectFit:
  297. ratio = MIN(horizontalRatio, verticalRatio);
  298. break;
  299. default:
  300. break;
  301. }
  302. CGSize newSize = CGSizeMake(self.size.width * ratio, self.size.height * ratio);
  303. return [self resizedImage:newSize interpolationQuality:quality];
  304. }
  305. #pragma mark -
  306. #pragma mark Private helper methods
  307. // Returns a copy of the image that has been transformed using the given affine transform and scaled to the new size
  308. // The new image's orientation will be UIImageOrientationUp, regardless of the current image's orientation
  309. // If the new size is not integral, it will be rounded up
  310. - (UIImage *)resizedImage:(CGSize)newSize transform:(CGAffineTransform)transform drawTransposed:(BOOL)transpose interpolationQuality:(CGInterpolationQuality)quality
  311. {
  312. CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
  313. CGRect transposedRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width);
  314. CGImageRef imageRef = self.CGImage;
  315. // Build a context that's the same dimensions as the new size
  316. CGContextRef bitmap = CGBitmapContextCreate(NULL, newRect.size.width, newRect.size.height, CGImageGetBitsPerComponent(imageRef), 0, CGImageGetColorSpace(imageRef), CGImageGetBitmapInfo(imageRef));
  317. // Rotate and/or flip the image if required by its orientation
  318. CGContextConcatCTM(bitmap, transform);
  319. // Set the quality level to use when rescaling
  320. CGContextSetInterpolationQuality(bitmap, quality);
  321. // Draw into the context; this scales the image
  322. CGContextDrawImage(bitmap, transpose ? transposedRect : newRect, imageRef);
  323. // Get the resized image from the context and a UIImage
  324. CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
  325. UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
  326. // Clean up
  327. CGContextRelease(bitmap);
  328. CGImageRelease(newImageRef);
  329. return newImage;
  330. }
  331. - (UIImage *)resizedImageInRect:(CGRect)newRect transform:(CGAffineTransform)transform drawTransposed:(BOOL)transpose interpolationQuality:(CGInterpolationQuality)quality
  332. {
  333. CGRect transposedRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width);
  334. CGImageRef imageRef = self.CGImage;
  335. // Build a context that's the same dimensions as the new size
  336. CGContextRef bitmap = CGBitmapContextCreate(NULL, newRect.size.width, newRect.size.height, CGImageGetBitsPerComponent(imageRef), 0, CGImageGetColorSpace(imageRef), CGImageGetBitmapInfo(imageRef));
  337. // Rotate and/or flip the image if required by its orientation
  338. CGContextConcatCTM(bitmap, transform);
  339. // Set the quality level to use when rescaling
  340. CGContextSetInterpolationQuality(bitmap, quality);
  341. // Draw into the context; this scales the image
  342. CGContextDrawImage(bitmap, transpose ? transposedRect : newRect, imageRef);
  343. // Get the resized image from the context and a UIImage
  344. CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
  345. UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
  346. // Clean up
  347. CGContextRelease(bitmap);
  348. CGImageRelease(newImageRef);
  349. return newImage;
  350. }
  351. // Returns an affine transform that takes into account the image orientation when drawing a scaled image
  352. - (CGAffineTransform)transformForOrientation:(CGSize)newSize
  353. {
  354. CGAffineTransform transform = CGAffineTransformIdentity;
  355. switch (self.imageOrientation)
  356. {
  357. case UIImageOrientationDown: // EXIF = 3
  358. case UIImageOrientationDownMirrored: // EXIF = 4
  359. transform = CGAffineTransformTranslate(transform, newSize.width, newSize.height);
  360. transform = CGAffineTransformRotate(transform, M_PI);
  361. break;
  362. case UIImageOrientationLeft: // EXIF = 6
  363. case UIImageOrientationLeftMirrored: // EXIF = 5
  364. transform = CGAffineTransformTranslate(transform, newSize.width, 0);
  365. transform = CGAffineTransformRotate(transform, M_PI_2);
  366. break;
  367. case UIImageOrientationRight: // EXIF = 8
  368. case UIImageOrientationRightMirrored: // EXIF = 7
  369. transform = CGAffineTransformTranslate(transform, 0, newSize.height);
  370. transform = CGAffineTransformRotate(transform, -M_PI_2);
  371. break;
  372. default:
  373. break;
  374. }
  375. switch (self.imageOrientation)
  376. {
  377. case UIImageOrientationUpMirrored: // EXIF = 2
  378. case UIImageOrientationDownMirrored: // EXIF = 4
  379. transform = CGAffineTransformTranslate(transform, newSize.width, 0);
  380. transform = CGAffineTransformScale(transform, -1, 1);
  381. break;
  382. case UIImageOrientationLeftMirrored: // EXIF = 5
  383. case UIImageOrientationRightMirrored: // EXIF = 7
  384. transform = CGAffineTransformTranslate(transform, newSize.height, 0);
  385. transform = CGAffineTransformScale(transform, -1, 1);
  386. break;
  387. default:
  388. break;
  389. }
  390. return transform;
  391. }
  392. @end
  393. //=================================================
  394. @implementation UIImage (RoundedCorner)
  395. // Creates a copy of this image with rounded corners
  396. // If borderSize is non-zero, a transparent border of the given size will also be added
  397. // Original author: Björn Sållarp. Used with permission. See: http://blog.sallarp.com/iphone-uiimage-round-corners/
  398. - (UIImage *)roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize
  399. {
  400. // If the image does not have an alpha layer, add one
  401. UIImage *image = [self imageWithAlpha];
  402. // Build a context that's the same dimensions as the new size
  403. CGContextRef context = CGBitmapContextCreate(NULL, image.size.width, image.size.height, CGImageGetBitsPerComponent(image.CGImage), 0, CGImageGetColorSpace(image.CGImage), CGImageGetBitmapInfo(image.CGImage));
  404. // Create a clipping path with rounded corners
  405. CGContextBeginPath(context);
  406. [self addRoundedRectToPath:CGRectMake(borderSize, borderSize, image.size.width - borderSize * 2, image.size.height - borderSize * 2) context:context ovalWidth:cornerSize ovalHeight:cornerSize];
  407. CGContextClosePath(context);
  408. CGContextClip(context);
  409. // Draw the image to the context; the clipping path will make anything outside the rounded rect transparent
  410. CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
  411. // Create a CGImage from the context
  412. CGImageRef clippedImage = CGBitmapContextCreateImage(context);
  413. CGContextRelease(context);
  414. // Create a UIImage from the CGImage
  415. UIImage *roundedImage = [UIImage imageWithCGImage:clippedImage];
  416. CGImageRelease(clippedImage);
  417. return roundedImage;
  418. }
  419. #pragma mark -
  420. #pragma mark Private helper methods
  421. // Adds a rectangular path to the given context and rounds its corners by the given extents
  422. // Original author: Björn Sållarp. Used with permission. See: http://blog.sallarp.com/iphone-uiimage-round-corners/
  423. - (void)addRoundedRectToPath:(CGRect)rect context:(CGContextRef)context ovalWidth:(CGFloat)ovalWidth ovalHeight:(CGFloat)ovalHeight
  424. {
  425. if (ovalWidth == 0 || ovalHeight == 0) {
  426. CGContextAddRect(context, rect);
  427. return;
  428. }
  429. CGContextSaveGState(context);
  430. CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect));
  431. CGContextScaleCTM(context, ovalWidth, ovalHeight);
  432. CGFloat fw = CGRectGetWidth(rect) / ovalWidth;
  433. CGFloat fh = CGRectGetHeight(rect) / ovalHeight;
  434. CGContextMoveToPoint(context, fw, fh/2);
  435. CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
  436. CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
  437. CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
  438. CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
  439. CGContextClosePath(context);
  440. CGContextRestoreGState(context);
  441. }
  442. @end
  443. //===========================================
  444. @implementation UIImage (SplitImageIntoTwoParts)
  445. #define SAWTOOTH_COUNT 10
  446. #define SAWTOOTH_WIDTH_FACTOR 20
  447. + (NSArray *)splitImageIntoTwoParts:(UIImage *)image
  448. {
  449. CGFloat scale = [[UIScreen mainScreen] scale];
  450. NSMutableArray *array = [NSMutableArray arrayWithCapacity:2];
  451. CGFloat width, height, widthgap, heightgap;
  452. int piceCount = SAWTOOTH_COUNT;
  453. width = image.size.width;
  454. height = image.size.height;
  455. widthgap = width/SAWTOOTH_WIDTH_FACTOR;
  456. heightgap = height/piceCount;
  457. // CGRect rect = CGRectMake(0, 0, width, height);
  458. CGContextRef context;
  459. CGImageRef imageMasked;
  460. UIImage *leftImage,*rightImage;
  461. //part one
  462. UIGraphicsBeginImageContext(CGSizeMake(width*scale, height*scale));
  463. context = UIGraphicsGetCurrentContext();
  464. CGContextScaleCTM(context, scale, scale);
  465. CGContextMoveToPoint(context, 0, 0);
  466. int a=-1;
  467. for (int i=0; i<piceCount+1; i++) {
  468. CGContextAddLineToPoint(context, width/2+(widthgap*a), heightgap*i);
  469. a= a*-1;
  470. }
  471. CGContextAddLineToPoint(context, 0, height);
  472. CGContextClosePath(context);
  473. CGContextClip(context);
  474. [image drawAtPoint:CGPointMake(0, 0)];
  475. imageMasked = CGBitmapContextCreateImage(context);
  476. leftImage = [UIImage imageWithCGImage:imageMasked scale:scale orientation:UIImageOrientationUp];
  477. [array addObject:leftImage];
  478. UIGraphicsEndImageContext();
  479. //part two
  480. UIGraphicsBeginImageContext(CGSizeMake(width*scale, height*scale));
  481. context = UIGraphicsGetCurrentContext();
  482. CGContextScaleCTM(context, scale, scale);
  483. CGContextMoveToPoint(context, width, 0);
  484. a=-1;
  485. for (int i=0; i<piceCount+1; i++)
  486. {
  487. CGContextAddLineToPoint(context, width/2+(widthgap*a), heightgap*i);
  488. a= a*-1;
  489. }
  490. CGContextAddLineToPoint(context, width, height);
  491. CGContextClosePath(context);
  492. CGContextClip(context);
  493. [image drawAtPoint:CGPointMake(0, 0)];
  494. imageMasked = CGBitmapContextCreateImage(context);
  495. rightImage = [UIImage imageWithCGImage:imageMasked scale:scale orientation:UIImageOrientationUp];
  496. [array addObject:rightImage];
  497. UIGraphicsEndImageContext();
  498. return array;
  499. }
  500. @end