iPhone 处理图像会停止所有进程

发布于 2024-11-27 02:41:15 字数 2723 浏览 3 评论 0原文

你好,我是 iPhone 开发新手,所以我可能做错了。我想连续转换图像 3 次,但是当我这样做时,它会锁定 iPhone,直到完成所有 3 次转换。我在步骤之间有函数,但在最后一个图像转换触发之前它们不会触发。如果您阅读下面的代码注释,这会更有意义。

我的问题是

  1. 是否有更快的方法来转换图像? 2. 如何阻止它锁定,以便它按顺序触发代码,并且图像之间的函数转换为内联触发?

    <前><代码>- (IBAction)ColorFun1 { // // 在第三次转换完成之前,此位置中的任何代码都不会触发 // // 要转换的图像 UIImage *originalImage = imageView.image; // 第一次转换 CGColorSpaceRef colorSapce = CGColorSpaceCreateDeviceGray(); CGContextRef context = CGBitmapContextCreate(nil,originalImage.size.width,originalImage.size.height,8,originalImage.size.width,colorSapce,kCGImageAlphaNone); CGContextSetInterpolationQuality(上下文, kCGInterpolationHigh); CGContextSetShouldAntialias(上下文,NO); CGContextDrawImage(上下文, CGRectMake(0, 0, 原始图像.size.宽度, 原始图像.尺寸.高度), [原始图像 CGImage]); CGImageRef bwImage = CGBitmapContextCreateImage(context); // CGContextRelease(上下文); CGColorSpaceRelease(colorSapce); // UIImage *resultImageBW = [UIImage imageWithCGImage:bwImage]; // 这是结果黑白图像。 [fxImage2View setImage:resultImageBW]; // // 在第三次转换完成之前,此位置中的任何代码都不会触发 // // // // 第二次转换 // UIGraphicsBeginImageContext(resultImageBW.size); CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy); [resultImageBW drawInRect:CGRectMake(0, 0, resultImageBW.size.width, resultImageBW.size.height)]; CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeDifference); CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(),[UIColor greyColor].CGColor); CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, resultImageBW.size.width, resultImageBW.size.height)); UIImage *returnImage = UIGraphicsGetImageFromCurrentImageContext(); [fxImage1View setImage:returnImage]; UIGraphicsEndImageContext(); // // // // 在第三次转换完成之前,此位置中的任何代码都不会触发 // // // // 第三次转换 // UIGraphicsBeginImageContext(resultImageBW.size); CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy); [resultImageBW drawInRect:CGRectMake(0, 0, resultImageBW.size.width, resultImageBW.size.height)]; CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeSoftLight); CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(),[UIColor colorWithRed:40 绿色:20 蓝色:0 alpha:1].CGColor); CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, resultImageBW.size.width, resultImageBW.size.height)); returnImage = UIGraphicsGetImageFromCurrentImageContext(); [fxImage3View setImage:returnImage]; UIGraphicsEndImageContext(); CGImageRelease(bwImage); }

Hello I am new to iPhone development so I could be doing this all wrong. I want to convert an image 3 times in a row but when I do it locks up the iphone until it finishes all 3 conversions. I have functions between the steps but they will not fire until the last image convert fires. This make more more sense if you read the code Notes below.

My questions are

  1. Is there a faster way to convert the images? 2. How do I stop it from locking up so that it fires the code in order and the functions between the image converts fire inline?

    - (IBAction)ColorFun1
    {
        //  
        // ANY CODE IN THIS location will not fire until 3rd convert is finished 
        // 
        // Image to convert 
        UIImage *originalImage = imageView.image;   
    
        // 1st Convert 
    
        CGColorSpaceRef colorSapce = CGColorSpaceCreateDeviceGray();
        CGContextRef context = CGBitmapContextCreate(nil, originalImage.size.width,     originalImage.size.height, 8, originalImage.size.width, colorSapce, kCGImageAlphaNone);
        CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
        CGContextSetShouldAntialias(context, NO);
        CGContextDrawImage(context, CGRectMake(0, 0, originalImage.size.width, originalImage.size.height), [originalImage CGImage]);
        CGImageRef bwImage = CGBitmapContextCreateImage(context);
        //
        CGContextRelease(context);
        CGColorSpaceRelease(colorSapce);
        //
        UIImage *resultImageBW = [UIImage imageWithCGImage:bwImage]; // This is result B/W image.
        [fxImage2View setImage:resultImageBW];
    
    
    
        //  
        // ANY CODE IN THIS location will not fire until 3rd convert is finished 
    
        // 
    
        //  
        // 
        // 2nd Convert 
    
        // 
    
        UIGraphicsBeginImageContext(resultImageBW.size);
    
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy);
    
        [resultImageBW drawInRect:CGRectMake(0, 0, resultImageBW.size.width, resultImageBW.size.height)];
    
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeDifference);
    
    
        CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(),[UIColor grayColor].CGColor);
    
        CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, resultImageBW.size.width, resultImageBW.size.height));
    
        UIImage *returnImage = UIGraphicsGetImageFromCurrentImageContext();
        [fxImage1View setImage:returnImage];
        UIGraphicsEndImageContext();    
    
        //
        //
    
        //   
        // ANY CODE IN THIS location will not fire until 3rd convert is finished 
        // 
        // 
    
        // 
        // 3rd Convert 
    
        // 
    
        UIGraphicsBeginImageContext(resultImageBW.size);
    
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy);
    
        [resultImageBW drawInRect:CGRectMake(0, 0, resultImageBW.size.width, resultImageBW.size.height)];
    
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(),   kCGBlendModeSoftLight);
    
    
        CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(),[UIColor colorWithRed:40 green:20 blue:0 alpha:1].CGColor);
    
        CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, resultImageBW.size.width, resultImageBW.size.height));
    
        returnImage = UIGraphicsGetImageFromCurrentImageContext();
        [fxImage3View setImage:returnImage];
        UIGraphicsEndImageContext();    
    
        CGImageRelease(bwImage);
    
    }
    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嘦怹 2024-12-04 02:41:15

您需要像 Sergio 所说的那样将控制权转移回运行循环。我建议研究一下中央调度。来自维基百科

Grand Central Dispatch 仍然在低级别使用线程,但将它们从程序员那里抽象出来,程序员不需要关心那么多细节。 GCD 中的任务是轻量级的,易于创建和排队; Apple 表示,在 GCD 中排队一个工作单元需要 15 条指令,而创建传统线程很容易需要数百条指令

找到有关如何实现它的教程应该不会太难。您甚至可以考虑斯坦福开发讲座。 讨论了性能和性能线程。我认为与您相关的部分从 33:36 开始。

You need to transfer control back to the run loop like sergio says. I'd suggest looking into grand central dispatch. From wikipedia

Grand Central Dispatch still uses threads at the low level but abstracts them away from the programmer, who will not need to be concerned with as many details. Tasks in GCD are lightweight to create and queue; Apple states that 15 instructions are required to queue up a work unit in GCD, while creating a traditional thread could easily require several hundred instructions

It shouldn't be too hard to find a tutorial on how to implement it. You might even consider the Stanford dev lectures. This one talks about performance & threading. I think the part thats relevant to you starts at 33:36.

黯然#的苍凉 2024-12-04 02:41:15

我认为您的问题取决于这样一个事实:由于您正在执行大量处理而不将控制权返回到主循环,因此您的 UI 在此期间不会更新。

您的一种可能性是定义三种方法,每种方法执行一次图像转换(这也将有助于代码的可读性)。然后,您可以通过在调用之间流程控制返回主循环并更新 UI 的方式来调用它们。

举个例子,如果你的 3 个方法是 convertImage1convertImage2convertImage3,你可以这样做

[self performSelector:@selector(convertImage1) withObject:nil afterDelay:0];
[self performSelector:@selector(convertImage2) withObject:nil afterDelay:0];
[self performSelector:@selector(convertImage3) withObject:nil afterDelay:0];

:如果您使用 Grand Central Dispatch dispatch_async 方法来调度您的调用,则可以这样:

dispatch_async(dispatch_get_main_queue(), ^{ [self convertImage1]; });
dispatch_async(dispatch_get_main_queue(), ^{ [self convertImage2]; });
dispatch_async(dispatch_get_main_queue(), ^{ [self convertImage3]; });

您可以在此处调整许多设计变量;这只是一个例子,供您参考。

I think that your issue depends on the fact that since you are doing a bunch of processing without returning control back to the main loop, your UI is not updated in between.

One possibility you have is defining three methods, each one doing one image conversion (this will also help readability of your code). Then you can call them in a way that between calls flow control gets back to the main loop and UI is updated.

As an example, if your 3 methods are convertImage1, convertImage2, and convertImage3, you can do:

[self performSelector:@selector(convertImage1) withObject:nil afterDelay:0];
[self performSelector:@selector(convertImage2) withObject:nil afterDelay:0];
[self performSelector:@selector(convertImage3) withObject:nil afterDelay:0];

The same effect can be obtained in a cleaner way if you use Grand Central Dispatch dispatch_async method to dispatch your call:

dispatch_async(dispatch_get_main_queue(), ^{ [self convertImage1]; });
dispatch_async(dispatch_get_main_queue(), ^{ [self convertImage2]; });
dispatch_async(dispatch_get_main_queue(), ^{ [self convertImage3]; });

There are many design variables that you can tweak here; this is just an example to give you an idea.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文