gpt4 book ai didi

ios - 如何使用 UIKit 更快地渲染具有效果的图像

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:36:37 24 4
gpt4 key购买 nike

我正在制作一个 iOS 应用程序,其中有一个过程可以用多个 UIImageViews 切换很多图片(一个循环来设置带有一堆图像的 UIImageView 的图像属性)。有时一些图像需要一些图形效果,比如乘法。

最简单的方法是使用 CIFilter 来做这件事,但问题是 iOS 上的 CALayer 不支持“filters”属性,因此您需要在设置“image”属性之前将效果应用于图像。但是当你非常频繁地刷新屏幕时,这真的太慢了​​。

所以接下来我尝试直接使用 Core Graphics 与 UIGraphics 上下文和 kCGBlendModeMultiply 进行乘法运算。这确实比使用 CIFilter 快得多,但由于您必须在渲染图像之前应用乘法运算,因此在尝试渲染具有乘法效果的图像时,您仍然会感觉到程序运行速度比渲染普通图像慢。

我的猜测是,这两种方法的根本问题是你必须用GPU对图像进行效果处理,然后用CPU得到结果图像,最后用GPU渲染结果图像,这意味着数据CPU 和 GPU 之间的传输浪费了很多时间,所以我然后尝试将父类(super class)从 UIImageView 更改为 UIView 并将 CGGraphics 上下文代码实现为 drawRect 方法,然后当我设置“图像”属性时,我在 didSet 中调用 setNeedsDisplay 方法。但这并不是很好......实际上每次它调用 setNeedsDisplay 时程序变得更慢,甚至比使用 CIFilter 还要慢,可能是因为有多个 View 显示。

我想也许我可以用 OpenGL 解决这个问题,但我想知道我是否可以只用 UIKit 解决这个问题?

最佳答案

据我了解,您必须对不同的图像进行相同的更改。因此初始初始化的时间对您来说并不重要,但应尽快处理每张图像。首先,在后台队列/线程中生成新图像是关键。有两种快速处理/生成图像的好方法:

  1. 使用 CoreImage 中的 CIFilter

  2. 使用GPUImage库

如果您使用了 CoreImage,请检查您是否正确使用了 CIFilter 和 CIContext。 CIContext 创建需要很多时间,但它可以在不同的 CIFilters 和图像之间SHARED - 所以你应该只创建 CIContext 一次! CIFilter 也可以在不同的图像之间共享,但由于它不是线程安全的,您应该为每个线程设置一个单独的 CIFilter。

在我的代码中有以下内容:

+ (UIImage*)roundShadowImageForImage:(UIImage*)image {
static CIFilter *_filter;

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
NSLog(@"CIContext and CIFilter generating...");
_context = [CIContext contextWithOptions:@{ kCIContextUseSoftwareRenderer: @NO,
kCIContextWorkingColorSpace : [NSNull null] }];

CIImage *roundShadowImage = [CIImage imageWithCGImage:[[self class] roundShadowImage].CGImage];
CIImage *maskImage = [CIImage imageWithCGImage:[[self class] roundWhiteImage].CGImage];

_filter = [CIFilter filterWithName:@"CIBlendWithAlphaMask"
keysAndValues:
kCIInputBackgroundImageKey, roundShadowImage,
kCIInputMaskImageKey, maskImage, nil];
NSLog(@"CIContext and CIFilter are generated");
});

if (image == nil) {
return nil;
}
NSAssert(_filter, @"Error: CIFilter for cover images is not generated");

CGSize imageSize = CGSizeMake(image.size.width * image.scale, image.size.height * image.scale);

// CIContext and CIImage objects are immutable, which means each can be shared safely among threads
CIFilter *filterForThread = [_filter copy]; // CIFilter could not be shared between different threads.

CGAffineTransform imageTransform = CGAffineTransformIdentity;
if (!CGSizeEqualToSize(imageSize, coverSize)) {
NSLog(@"Cover image. Resizing image %@ to required size %@", NSStringFromCGSize(imageSize), NSStringFromCGSize(coverSize));
CGFloat scaleFactor = MAX(coverSide / imageSize.width, coverSide / imageSize.height);
imageTransform = CGAffineTransformMakeScale(scaleFactor, scaleFactor);
}
imageTransform = CGAffineTransformTranslate(imageTransform, extraBorder, extraBorder);

CIImage *ciImage = [CIImage imageWithCGImage:image.CGImage];
ciImage = [ciImage imageByApplyingTransform:imageTransform];

if (image.hasAlpha) {
CIImage *ciWhiteImage = [CIImage imageWithCGImage:[self whiteImage].CGImage];
CIFilter *filter = [CIFilter filterWithName:@"CISourceOverCompositing"
keysAndValues:
kCIInputBackgroundImageKey, ciWhiteImage,
kCIInputImageKey, ciImage, nil];
[filterForThread setValue:filter.outputImage forKey:kCIInputImageKey];
}
else
{
[filterForThread setValue:ciImage forKey:kCIInputImageKey];
}

CIImage *outputCIImage = [filterForThread outputImage];
CGImageRef cgimg = [_context createCGImage:outputCIImage fromRect:[outputCIImage extent]];
UIImage *newImage = [UIImage imageWithCGImage:cgimg];
CGImageRelease(cgimg);
return newImage;
}

如果您仍然对速度不满意,请尝试 GPUImage这是一个非常好的库,它也非常快,因为它使用 OpenGL 生成图像。

关于ios - 如何使用 UIKit 更快地渲染具有效果的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29742746/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com