123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- // UIImage+Alpha.m
- // Created by Trevor Harmon on 9/20/09.
- // Free for personal or commercial use, with or without modification.
- // No warranty is expressed or implied.
- #import "UIImage+Alpha.h"
- // Private helper methods
- @interface UIImage (PrivateAlpha)
- - (CGImageRef)newBorderMask:(NSUInteger)borderSize size:(CGSize)size;
- @end
- @implementation UIImage (Alpha)
- // Returns true if the image has an alpha layer
- - (BOOL)hasAlpha {
- CGImageAlphaInfo alpha = CGImageGetAlphaInfo(self.CGImage);
- return (alpha == kCGImageAlphaFirst ||
- alpha == kCGImageAlphaLast ||
- alpha == kCGImageAlphaPremultipliedFirst ||
- alpha == kCGImageAlphaPremultipliedLast);
- }
- // Returns a copy of the given image, adding an alpha channel if it doesn't already have one
- - (UIImage *)imageWithAlpha {
- if ([self hasAlpha]) {
- return self;
- }
-
- CGImageRef imageRef = self.CGImage;
- size_t width = CGImageGetWidth(imageRef);
- size_t height = CGImageGetHeight(imageRef);
-
- // The bitsPerComponent and bitmapInfo values are hard-coded to prevent an "unsupported parameter combination" error
- CGContextRef offscreenContext = CGBitmapContextCreate(NULL,
- width,
- height,
- 8,
- 0,
- CGImageGetColorSpace(imageRef),
- kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
-
- // Draw the image into the context and retrieve the new image, which will now have an alpha layer
- CGContextDrawImage(offscreenContext, CGRectMake(0, 0, width, height), imageRef);
- CGImageRef imageRefWithAlpha = CGBitmapContextCreateImage(offscreenContext);
- UIImage *imageWithAlpha = [UIImage imageWithCGImage:imageRefWithAlpha];
-
- // Clean up
- CGContextRelease(offscreenContext);
- CGImageRelease(imageRefWithAlpha);
-
- return imageWithAlpha;
- }
- // Returns a copy of the image with a transparent border of the given size added around its edges.
- // If the image has no alpha layer, one will be added to it.
- - (UIImage *)transparentBorderImage:(NSUInteger)borderSize {
- // If the image does not have an alpha layer, add one
- UIImage *image = [self imageWithAlpha];
-
- CGRect newRect = CGRectMake(0, 0, image.size.width + borderSize * 2, image.size.height + borderSize * 2);
-
- // Build a context that's the same dimensions as the new size
- CGContextRef bitmap = CGBitmapContextCreate(NULL,
- newRect.size.width,
- newRect.size.height,
- CGImageGetBitsPerComponent(self.CGImage),
- 0,
- CGImageGetColorSpace(self.CGImage),
- CGImageGetBitmapInfo(self.CGImage));
-
- // Draw the image in the center of the context, leaving a gap around the edges
- CGRect imageLocation = CGRectMake(borderSize, borderSize, image.size.width, image.size.height);
- CGContextDrawImage(bitmap, imageLocation, self.CGImage);
- CGImageRef borderImageRef = CGBitmapContextCreateImage(bitmap);
-
- // Create a mask to make the border transparent, and combine it with the image
- CGImageRef maskImageRef = [self newBorderMask:borderSize size:newRect.size];
- CGImageRef transparentBorderImageRef = CGImageCreateWithMask(borderImageRef, maskImageRef);
- UIImage *transparentBorderImage = [UIImage imageWithCGImage:transparentBorderImageRef];
-
- // Clean up
- CGContextRelease(bitmap);
- CGImageRelease(borderImageRef);
- CGImageRelease(maskImageRef);
- CGImageRelease(transparentBorderImageRef);
-
- return transparentBorderImage;
- }
- #pragma mark -
- #pragma mark Private helper methods
- // Creates a mask that makes the outer edges transparent and everything else opaque
- // The size must include the entire mask (opaque part + transparent border)
- // The caller is responsible for releasing the returned reference by calling CGImageRelease
- - (CGImageRef)newBorderMask:(NSUInteger)borderSize size:(CGSize)size {
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
-
- // Build a context that's the same dimensions as the new size
- CGContextRef maskContext = CGBitmapContextCreate(NULL,
- size.width,
- size.height,
- 8, // 8-bit grayscale
- 0,
- colorSpace,
- kCGBitmapByteOrderDefault | kCGImageAlphaNone);
-
- // Start with a mask that's entirely transparent
- CGContextSetFillColorWithColor(maskContext, [UIColor blackColor].CGColor);
- CGContextFillRect(maskContext, CGRectMake(0, 0, size.width, size.height));
-
- // Make the inner part (within the border) opaque
- CGContextSetFillColorWithColor(maskContext, [UIColor whiteColor].CGColor);
- CGContextFillRect(maskContext, CGRectMake(borderSize, borderSize, size.width - borderSize * 2, size.height - borderSize * 2));
-
- // Get an image of the context
- CGImageRef maskImageRef = CGBitmapContextCreateImage(maskContext);
-
- // Clean up
- CGContextRelease(maskContext);
- CGColorSpaceRelease(colorSpace);
-
- return maskImageRef;
- }
- @end
|