我的像素化图像处理算法有点问题。
我将图像从头开始加载到unsigned char*
类型的数组中
之后,在需要时,我会修改此数据并更新图像。
此更新需要很长时间。我就是这样做的:
CGDataProviderRef dataProvider = CGProviderCrateWithData(.....);
CGImageRef cgImage = CGImageCreate(....);
[imageView setImage:[UIImage imageWithCGImage:cgImage]]];
一切正常,但处理大图像的速度很慢。我尝试在后台线程上运行它,但这没有帮助。
所以基本上,这需要太长时间。有谁知道如何改进它?
答案 0 :(得分:16)
正如其他人所建议的那样,您需要将这项工作从CPU卸载到GPU,以便在这些移动设备上获得任何良好的处理性能。
为此,我创建了an open source framework for iOS called GPUImage,这使得进行这种加速图像处理变得相对简单。它确实需要OpenGL ES 2.0支持,但过去几年销售的每台iOS设备都有此功能(统计数据显示该领域所有iOS设备的97%)。
作为该框架的一部分,我捆绑的初始过滤器之一是像素化过滤器。 SimpleVideoFilter示例应用程序显示了如何使用它,使用滑块控制处理过的图像中的像素宽度:
此过滤器是带有以下GLSL代码的片段着色器的结果:
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform highp fractionalWidthOfPixel;
void main()
{
highp vec2 sampleDivisor = vec2(fractionalWidthOfPixel);
highp vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor);
gl_FragColor = texture2D(inputImageTexture, samplePos );
}
在我的基准测试中,像这样的基于GPU的过滤器比iOS上的图像和视频的等效CPU绑定处理例程快6-24倍。上面链接的框架应该相当容易合并到一个应用程序中,并且源代码可以自由地供您自定义,无论您认为合适。
答案 1 :(得分:3)
使用名为Core Image
的{{1}}过滤器怎么样?
这是我如何实现它的代码片段。您可以使用CIPixellate
来获得所需的强度:
kCIInputScaleKey
以下是官方Apple Filter Tutorial和List of available Filters。
我刚写了一个方法来在后台执行渲染工作:
// initialize context and image
CIContext *context = [CIContext contextWithOptions:nil];
CIImage *logo = [CIImage imageWithData:UIImagePNGRepresentation([UIImage imageNamed:@"test"])];
// set filter and properties
CIFilter *filter = [CIFilter filterWithName:@"CIPixellate"];
[filter setValue:logo forKey:kCIInputImageKey];
[filter setValue:[[CIVector alloc] initWithX:150 Y:150] forKey:kCIInputCenterKey]; // default: 150, 150
[filter setValue:[NSNumber numberWithDouble:100.0] forKey:kCIInputScaleKey]; // default: 8.0
// render image
CIImage *result = (CIImage *) [filter valueForKey:kCIOutputImageKey];
CGRect extent = result.extent;
CGImageRef cgImage = [context createCGImage:result fromRect:extent];
// result
UIImage *image = [[UIImage alloc] initWithCGImage:cgImage];
这样称呼:
- (void) pixelateImage:(UIImage *) image withIntensity:(NSNumber *) intensity completionHander:(void (^)(UIImage *pixelatedImage)) handler {
// async task
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// initialize context and image
CIContext *context = [CIContext contextWithOptions:nil];
CIImage *logo = [CIImage imageWithData:UIImagePNGRepresentation(image)];
// set filter and properties
CIFilter *filter = [CIFilter filterWithName:@"CIPixellate"];
[filter setValue:logo forKey:kCIInputImageKey];
[filter setValue:[[CIVector alloc] initWithX:150 Y:150] forKey:kCIInputCenterKey]; // default: 150, 150
[filter setValue:intensity forKey:kCIInputScaleKey]; // default: 8.0
// render image
CIImage *result = (CIImage *) [filter valueForKey:kCIOutputImageKey];
CGRect extent = result.extent;
CGImageRef cgImage = [context createCGImage:result fromRect:extent];
// result
UIImage *image = [[UIImage alloc] initWithCGImage:cgImage];
// dispatch to main thread
dispatch_async(dispatch_get_main_queue(), ^{
handler(image);
});
});
}
答案 2 :(得分:1)
iPhone不是一个很好的设备,可以执行图像操作等计算密集型任务。如果您希望提高显示非常高分辨率图像的性能 - 可能在同时执行某些图像处理任务时,请查看使用CATiledLayer。它是以平铺块的形式显示内容,因此您只能根据需要在单个图块上显示/处理内容数据。
答案 3 :(得分:1)
转换@Kai Burghardt对Swift 3的回答
func pixelateImage(_ image: UIImage, withIntensity intensity: Int) -> UIImage {
// initialize context and image
let context = CIContext(options: nil)
let logo = CIImage(data: UIImagePNGRepresentation(image)!)!
// set filter and properties
let filter = CIFilter(name: "CIPixellate")
filter?.setValue(logo, forKey: kCIInputImageKey)
filter?.setValue(CIVector(x:150,y:150), forKey: kCIInputCenterKey)
filter?.setValue(intensity, forKey: kCIInputScaleKey)
let result = filter?.value(forKey: kCIOutputImageKey) as! CIImage
let extent = result.extent
let cgImage = context.createCGImage(result, from: extent)
// result
let processedImage = UIImage(cgImage: cgImage!)
return processedImage
}
将此代码称为
self.myImageView.image = pixelateImage(UIImage(named:"test"),100)
答案 4 :(得分:0)
我同意@Xorlev。我唯一希望的是(假设您正在使用大量浮点运算),您正在为arm6构建并使用thumb isa。在这种情况下,编译时不使用-mthumb选项,性能可能会提高。
答案 5 :(得分:0)
实际上,这很简单。更高的输入比例键意味着更多的像素化。
let filter = CIFilter(name: "CIPixellate")
filter?.setValue(inputImage, forKey: kCIInputImageKey)
filter?.setValue(30, forKey: kCIInputScaleKey)
let pixellatedCIImage = filter?.outputImage
结果是CIImage,您可以使用UIImage将其转换为
UIImage(ciImage: pixellatedCIImage)