我正在开发一个实用程序,用于根据任意宽高比裁剪UIImage
,aspectFit
或aspectFill
作为裁剪选项。 aspectFill
选项将裁剪原始图像,使最终图像完全被原始图像覆盖。 aspectFit
将确保不会剪切原始图像的像素,并且将黑色条纹添加到原始图像的两侧以使其适合宽高比。我知道已经有第三方图书馆做同样的工作,但我想把它作为一个学习练习。
aspectFill
,我只是计算最终图像偏移量和大小,并从原始CGRect
中裁剪UIImage
。aspectFit
,我会计算最终图片尺寸,然后使用CGContextRef
制作一个CGContextFillRect
。在这种情况下,我在所需的偏移处绘制原始图像(将原始图像保留在最终图像的中间)。要测试此实用程序,我使用的是 2MB 图像,其大小与iPhone相机照片大致相同。出现了以下问题:
aspectFill
的实用程序按预期工作,每个图像处理 0.01ms 处理时间,这很好。问题是,如果我尝试在循环中运行此实用程序以获取大量图像(10000 +),则内存使用量会激增,直到应用程序崩溃。我添加了@autoreleasepool
块,但似乎没有任何区别。
aspectFit
实用程序存在相反的问题。此处的@autoreleasepool
块按预期工作,并定期释放对象,以便应用程序不会因循环中的任意数量的图像而崩溃。但在这里,每张图片的处理时间都在 130ms 左右,这似乎很多。我尝试使用UIGraphicsBeginImageContext
代替CGContextRef
,但这需要花费更多时间。
aspectFill
的代码
//ox, oy are the image crop offsets calculated before and fw, fh are the width and height of final image
@autoreleasepool {
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake(ox,oy,fw,fh));
UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return finalImage;
}
aspectFit
的代码
@autoreleasepool {
CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
CGContextRef context = CGBitmapContextCreate(NULL, fw, fh, CGImageGetBitsPerComponent(image.CGImage), 0, colorSpace, CGImageGetBitmapInfo(image.CGImage));
CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
CGContextFillRect(context, CGRectMake(0, 0, fw, fh));
CGRect rect = CGRectMake(ox, oy, image.size.width, image.size.height);
CGContextDrawImage(context, rect, image.CGImage);
CGImageRef newCGImage = CGBitmapContextCreateImage(context);
CGContextRelease(context);
UIImage *finalImage = [UIImage imageWithCGImage:newCGImage];
CGImageRelease(newCGImage);
return finalImage;
}
有人能指出我做错了什么,或者给我一些优化来减少这个实用程序的处理时间?提前谢谢!
答案 0 :(得分:2)
最后,经过对CGGraphics
和UIGraphics
内容的大量讨论,我发现问题根本不在于实用程序。上面的代码很完美,但罪魁祸首就是我加载UIImage
的方式。
我正在使用
[UIImage imageNamed:@"twomb.jpg"];
加载图片。 imageNamed
方法将图像缓存在内存中,全部为2MB。那耗费时间。将上述行更改为
[UIImage imageWithContentsOfFile:@"twomb.jpg"];
时间和记忆的使用都大大减少了。