// 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 (AlphaPrivateMethods) - (CGImageRef)newBorderMask:(NSUInteger)borderSize size:(CGSize)size; @end @implementation UIImage (Alpha) /** * @brief 是否有alpha通道 * * @return 是否有alpha通道 */ - (BOOL)hasAlpha { CGImageAlphaInfo alpha = CGImageGetAlphaInfo(self.CGImage); return (alpha == kCGImageAlphaFirst || alpha == kCGImageAlphaLast || alpha == kCGImageAlphaPremultipliedFirst || alpha == kCGImageAlphaPremultipliedLast); } /** * @brief 如果没有alpha通道 增加alpha通道 * * @return 如果没有alpha通道 增加alpha通道 */ - (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. /** * @brief 增加透明边框 * * @param borderSize 边框尺寸 * * @return 增加透明边框后的图片 */ - (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; } /** * @brief 裁切含透明图片为最小大小 * * @return 裁切后的图片 */ - (UIImage *)trimmedBetterSize { CGImageRef inImage = self.CGImage; CFDataRef m_DataRef; m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage)); UInt8 * m_PixelBuf = (UInt8 *) CFDataGetBytePtr(m_DataRef); // size_t width = CGImageGetWidth(inImage); // size_t height = CGImageGetHeight(inImage); CGFloat width = CGImageGetWidth(inImage); CGFloat height = CGImageGetHeight(inImage); CGPoint top,left,right,bottom; BOOL breakOut = NO; for (int x = 0;breakOut==NO && x < width; x++) { for (int y = 0; y < height; y++) { int loc = x + (y * width); loc *= 4; if (m_PixelBuf[loc + 3] != 0) { left = CGPointMake(x, y); breakOut = YES; break; } } } breakOut = NO; for (int y = 0;breakOut==NO && y < height; y++) { for (int x = 0; x < width; x++) { int loc = x + (y * width); loc *= 4; if (m_PixelBuf[loc + 3] != 0) { top = CGPointMake(x, y); breakOut = YES; break; } } } breakOut = NO; for (int y = height-1;breakOut==NO && y >= 0; y--) { for (int x = width-1; x >= 0; x--) { int loc = x + (y * width); loc *= 4; if (m_PixelBuf[loc + 3] != 0) { bottom = CGPointMake(x, y); breakOut = YES; break; } } } breakOut = NO; for (int x = width-1;breakOut==NO && x >= 0; x--) { for (int y = height-1; y >= 0; y--) { int loc = x + (y * width); loc *= 4; if (m_PixelBuf[loc + 3] != 0) { right = CGPointMake(x, y); breakOut = YES; break; } } } CGFloat scale = self.scale; CGRect cropRect = CGRectMake(left.x / scale, top.y/scale, (right.x - left.x)/scale, (bottom.y - top.y) / scale); UIGraphicsBeginImageContextWithOptions( cropRect.size, NO, scale); [self drawAtPoint:CGPointMake(-cropRect.origin.x, -cropRect.origin.y) blendMode:kCGBlendModeCopy alpha:1.]; UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); CFRelease(m_DataRef); return croppedImage; } #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