裁剪UIImage到alpha

我有一个相当大的,几乎全屏的图像,我将要在iPad上显示。 图像是大约80%透明。 我需要,在客户端上,确定不透明像素的边界框,然后裁剪到该边界框。

在StackOverflow上扫描其他问题,并阅读一些CoreGraphics文档,我想我可以通过以下方式实现:

CGBitmapContextCreate(...) // Use this to render the image to a byte array .. - iterate through this byte array to find the bounding box .. CGImageCreateWithImageInRect(image, boundingRect); 

这看起来非常低效和笨重。 有没有什么聪明的我可以用CGImage的面具或使用设备的graphics加速来做到这一点?

设备无法做到这一点,没有什么聪明的做法,但是有一些方法可以加快任务速度,或者减less对用户界面的影响。

首先考虑加快这一任务的需要。 通过这个字节数组的简单迭代可能会足够快。 如果应用程序每次运行只计算一次,或者对select之间至less需要几秒钟的用户select作出反应,则可能不需要投资优化此任务。

如果在图像可用之后一段时间不需要边界框,则可以在单独的线程中启动该迭代。 这样计算不会阻塞主界面线程。 Grand Central Dispatch可以使这个任务更容易使用一个单独的线程。

如果任务必须加速,也许这是video图像的实时处理,那么并行处理数据可能会有所帮助。 Accelerate框架可以帮助设置数据的SIMD计算。 或者,为了真正获得这个迭代的性能,使用NEON SIMD操作的ARM汇编语言代码可以得到很好的结果,而且还需要大量的开发工作。

最后的select是调查一个更好的algorithm。 检测图像中的特征有大量的工作。 边缘检测algorithm可能比通过字节数组的简单迭代更快。 也许苹果将在未来增加边缘检测function给Core Graphics,可以应用于这种情况。 苹果公司实施的image processing能力可能并不完全符合这种情况,但苹果的实施应该优化使用iPad的SIMD或GPUfunction,从而获得更好的整体性能。

感谢user404709所做的一切努力。 下面的代码也处理视网膜图像并释放CFDataRef。

 - (UIImage *)trimmedImage { 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); 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; } 

我在UImage上创build了一个类别,如果有人需要它的话…

 + (UIImage *)cropTransparencyFromImage:(UIImage *)img { CGImageRef inImage = img.CGImage; CFDataRef m_DataRef; m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage)); UInt8 * m_PixelBuf = (UInt8 *) CFDataGetBytePtr(m_DataRef); int width = img.size.width; int height = img.size.height; 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; } } } CGRect cropRect = CGRectMake(left.x, top.y, right.x - left.x, bottom.y - top.y); UIGraphicsBeginImageContextWithOptions( cropRect.size, NO, 0.); [img drawAtPoint:CGPointMake(-cropRect.origin.x, -cropRect.origin.y) blendMode:kCGBlendModeCopy alpha:1.]; UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return croppedImage; }