UIImage+Alpha.m 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // UIImage+Alpha.m
  2. // Created by Trevor Harmon on 9/20/09.
  3. // Free for personal or commercial use, with or without modification.
  4. // No warranty is expressed or implied.
  5. #import "UIImage+Alpha.h"
  6. @implementation UIImage (Alpha)
  7. // Returns true if the image has an alpha layer
  8. - (BOOL)hasAlpha
  9. {
  10. CGImageAlphaInfo alpha = CGImageGetAlphaInfo(self.CGImage);
  11. return (alpha == kCGImageAlphaFirst || alpha == kCGImageAlphaLast || alpha == kCGImageAlphaPremultipliedFirst || alpha == kCGImageAlphaPremultipliedLast);
  12. }
  13. // Returns a copy of the given image, adding an alpha channel if it doesn't already have one
  14. - (UIImage *)imageWithAlpha
  15. {
  16. if ([self hasAlpha])
  17. {
  18. return self;
  19. }
  20. CGImageRef imageRef = self.CGImage;
  21. size_t width = CGImageGetWidth(imageRef);
  22. size_t height = CGImageGetHeight(imageRef);
  23. // The bitsPerComponent and bitmapInfo values are hard-coded to prevent an "unsupported parameter combination" error
  24. CGContextRef offscreenContext = CGBitmapContextCreate(NULL, width, height, 8, 0, CGImageGetColorSpace(imageRef), kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
  25. // Draw the image into the context and retrieve the new image, which will now have an alpha layer
  26. CGContextDrawImage(offscreenContext, CGRectMake(0, 0, width, height), imageRef);
  27. CGImageRef imageRefWithAlpha = CGBitmapContextCreateImage(offscreenContext);
  28. UIImage *imageWithAlpha = [UIImage imageWithCGImage:imageRefWithAlpha];
  29. // Clean up
  30. CGContextRelease(offscreenContext);
  31. CGImageRelease(imageRefWithAlpha);
  32. return imageWithAlpha;
  33. }
  34. // Returns a copy of the image with a transparent border of the given size added around its edges.
  35. // If the image has no alpha layer, one will be added to it.
  36. - (UIImage *)transparentBorderImage:(NSUInteger)borderSize
  37. {
  38. // If the image does not have an alpha layer, add one
  39. UIImage *image = [self imageWithAlpha];
  40. CGRect newRect = CGRectMake(0, 0, image.size.width + borderSize * 2, image.size.height + borderSize * 2);
  41. // Build a context that's the same dimensions as the new size
  42. CGContextRef bitmap = CGBitmapContextCreate(NULL, newRect.size.width, newRect.size.height, CGImageGetBitsPerComponent(self.CGImage), 0, CGImageGetColorSpace(self.CGImage), CGImageGetBitmapInfo(self.CGImage));
  43. // Draw the image in the center of the context, leaving a gap around the edges
  44. CGRect imageLocation = CGRectMake(borderSize, borderSize, image.size.width, image.size.height);
  45. CGContextDrawImage(bitmap, imageLocation, self.CGImage);
  46. CGImageRef borderImageRef = CGBitmapContextCreateImage(bitmap);
  47. // Create a mask to make the border transparent, and combine it with the image
  48. CGImageRef maskImageRef = [self newBorderMask:borderSize size:newRect.size];
  49. CGImageRef transparentBorderImageRef = CGImageCreateWithMask(borderImageRef, maskImageRef);
  50. UIImage *transparentBorderImage = [UIImage imageWithCGImage:transparentBorderImageRef];
  51. // Clean up
  52. CGContextRelease(bitmap);
  53. CGImageRelease(borderImageRef);
  54. CGImageRelease(maskImageRef);
  55. CGImageRelease(transparentBorderImageRef);
  56. return transparentBorderImage;
  57. }
  58. #pragma mark -
  59. #pragma mark Private helper methods
  60. // Creates a mask that makes the outer edges transparent and everything else opaque
  61. // The size must include the entire mask (opaque part + transparent border)
  62. // The caller is responsible for releasing the returned reference by calling CGImageRelease
  63. - (CGImageRef)newBorderMask:(NSUInteger)borderSize size:(CGSize)size
  64. {
  65. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
  66. // Build a context that's the same dimensions as the new size
  67. CGContextRef maskContext = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaNone);
  68. // Start with a mask that's entirely transparent
  69. CGContextSetFillColorWithColor(maskContext, [UIColor blackColor].CGColor);
  70. CGContextFillRect(maskContext, CGRectMake(0, 0, size.width, size.height));
  71. // Make the inner part (within the border) opaque
  72. CGContextSetFillColorWithColor(maskContext, [UIColor whiteColor].CGColor);
  73. CGContextFillRect(maskContext, CGRectMake(borderSize, borderSize, size.width - borderSize * 2, size.height - borderSize * 2));
  74. // Get an image of the context
  75. CGImageRef maskImageRef = CGBitmapContextCreateImage(maskContext);
  76. // Clean up
  77. CGContextRelease(maskContext);
  78. CGColorSpaceRelease(colorSpace);
  79. return maskImageRef;
  80. }
  81. @end