iPhone CGContextDrawImage和UIImageJPEGRepresentation大大减慢了应用程序的速度 [英] iPhone CGContextDrawImage and UIImageJPEGRepresentation drastically slowing down application

查看:71
本文介绍了iPhone CGContextDrawImage和UIImageJPEGRepresentation大大减慢了应用程序的速度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用相机拍摄图像的应用程序.应用程序可以运行,但是速度很慢,大约需要10秒钟来处理图像.

I have an application that uses camera to take images. Application works but is very slow, taking ~10 seconds to process images.

通过过程,我的意思是旋转,创建缩略图并将它们都保存到闪存中.

By process i mean, rotating, creating thumbnail and saving them both to flash memory.

应用程序基于Cordova,但是我没有参与其中.而且,这可以在较旧的型号iPhone 3G上运行,但是在较新的型号上尝试该应用程序并不会产生更好的结果.

Application is based on Cordova, but i dont have a part in that. And this is running on older model, iPhone 3G, but trying this app on newer model doesn't yield much better results.

主要瓶颈是前面提到的CGContextDrawImage和UIImageJPEGRepresentation函数.

The main bottleneck is aforementioned CGContextDrawImage and UIImageJPEGRepresentation functions.

我无法将该代码分成第二个线程,因为结果必须尽快可见.

I cant separate that code into second thread because results must be visible as soon as possible.

我搜索了两天,没有找到适用的解决方案.

I have searched for two days and found no applicable solutions.

我也发现了苹果的私有API,但是我不能使用它们.

Also i found out about apple's private API's but i can't use them.

这是时间紧迫代码的代码示例,如果您对如何加快速度有任何建议,那将是很好的.

Here is the code samples for time-critical code and if you have any advice on how to speed this up it would be great.

- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{
    NSLog(@"TEST imagePickerController");
    NSDate* dateFunctionStart = [NSDate date];

    NSLog(@"respond...");
    if ([picker respondsToSelector:@selector(presentingViewController)]) {
        [[picker presentingViewController] dismissModalViewControllerAnimated:YES];
    } else {
        [[picker parentViewController] dismissModalViewControllerAnimated:YES];
    }
    NSLog(@"done");

    // get the image
    NSLog(@"get the image...");
    UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];
    NSLog(@"done");
    NSLog(@"correct image for orientation...");
    image = [self imageCorrectedForCaptureOrientation:image]; // 3 sec
    //image = [image rotate:[image imageOrientation]]; // 1 - 6 sec
    NSLog(@"done");

    NSLog(@"make thumbnail...");
    CGSize thumbnailSize = CGSizeMake(200, 200);
    UIImage *thumbnailImage = [self imageByScalingNotCroppingForSize:image toSize:thumbnailSize];
    NSLog(@"done");

    NSLog(@"jpeg representation 1...");
    NSData* imageData = UIImageJPEGRepresentation(image, 1.0); // 4 sec
    NSLog(@"done");
    NSLog(@"jpeg representation 2...");
    NSData* thumbnailData = UIImageJPEGRepresentation(thumbnailImage, 1.0);
    NSLog(@"done");

    NSLog(@"save image and thumbnail...");
    NSString* imageRet = [self saveData:imageData toFile:self.imageName];   
    NSString* thumbRet = [self saveData:thumbnailData toFile:self.thumbnailName];
    NSLog(@"done");

    NSLog(@"array two images...");
    //NSString *jsResult = [NSString stringWithFormat:@"{%@, %@}", imageRet, thumbRet];
    NSArray *jsResultA = [NSArray arrayWithObjects:imageRet, thumbRet, nil];
    NSLog(@"done");

    NSLog(@"plugin stuff...");
    CDVPluginResult* result = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsArray:jsResultA];
    NSString* jsString = [result toSuccessCallbackString:self.callBackID];
    [self.webView stringByEvaluatingJavaScriptFromString:jsString];
    NSLog(@"done");

    timeFunc(dateFunctionStart, @"total time");
    NSLog(@"TEST END imagePickerController");

}

这是 imageCorrectedForCaptureOrientation 方法:

- (UIImage*) imageCorrectedForCaptureOrientation:(UIImage*)anImage
{
    NSLog(@"IMAGE CORRECTION IN");
    NSDate* start = nil;

    float rotation_radians = 0;
    bool perpendicular = false;

    switch ([anImage imageOrientation]) {
        case UIImageOrientationUp:
            rotation_radians = 0.0;
            break;
        case UIImageOrientationDown:
            rotation_radians = M_PI; 
            break;
        case UIImageOrientationRight:
            rotation_radians = M_PI_2;
            perpendicular = true;
            break;
        case UIImageOrientationLeft:
            rotation_radians = -M_PI_2;
            perpendicular = true;
            break;
        default:
            break;
    }

    UIGraphicsBeginImageContext(CGSizeMake(anImage.size.width, anImage.size.height));
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Rotate around the center point
    CGContextTranslateCTM(context, anImage.size.width/2, anImage.size.height/2);
    CGContextRotateCTM(context, rotation_radians);

    CGContextScaleCTM(context, 1.0, -1.0);
    float width = perpendicular ? anImage.size.height : anImage.size.width;
    float height = perpendicular ? anImage.size.width : anImage.size.height;
    CGContextDrawImage(context, CGRectMake(-width / 2, -height / 2, width, height), [anImage CGImage]);

    // Move the origin back since the rotation might've change it (if its 90 degrees)
    if (perpendicular) {
        CGContextTranslateCTM(context, -anImage.size.height/2, -anImage.size.width/2);
    }

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    NSLog(@"IMAGE CORRECTION OUT");

    return newImage;
}

我没有找到其他更好的方法来保存图像 NSData * imageData = UIImageJPEGRepresentation(image,1.0);//4秒

I didnt found any better way to save image other that NSData* imageData = UIImageJPEGRepresentation(image, 1.0); // 4 sec

常规相机应用程序如何快速运行?它会拍摄图像,旋转图像并在一秒钟内将图像保存为闪光.如何产生这种效果?

How does regular camera application work so fast? It takes image, rotates it and saves image to flash in a second. How to produce that effect?

感谢您的帮助.

无解.我将放置一些自定义UIView来播放一些动画,以通知用户发生了一些事情.由于映像很大,为1.5 MB,因此这些操作必须持续一段时间.也许有解决方案可以加快拍摄图像,处理图像然后保存到磁盘的整个过程,但我不知道.

No solution. I will put some custom UIView to play some animation to notify user that something is happening. Since the image is large, 1.5 MB, these operations must last some time. Maybe there is solution to speed up this whole process of taking image, process it and then saving to disk but i do not know it.

我已经决定使用 https://github.com/matej/MBProgressHUD 是完整的解决方案.如果由于我是Objective-C新手而被证明很复杂,那么我将放置UIProgressView之类的东西.

I've decided for https://github.com/matej/MBProgressHUD as it seems to be complete solution. If it proves complicated as i am objective-c noob, i'll put UIProgressView or something.

无论如何,感谢大家的帮助.

Anyway, thanks to all for trying to help.

推荐答案

我建议您使用GCD并在另一个线程中处理图像....每次调用UIImageJpegRepresentation都会花费很多,因为它会将图像解码到设备的内存中.

I suggest you use GCD and process the image in another thread.... Every call for UIImageJpegRepresentation does cost a lot, since it does decode the image to the device's memory...

- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{

NSLog(@"TEST imagePickerController");
NSDate* dateFunctionStart = [NSDate date];

NSLog(@"respond...");
if ([picker respondsToSelector:@selector(presentingViewController)]) {
    [[picker presentingViewController] dismissModalViewControllerAnimated:YES];
} else {
    [[picker parentViewController] dismissModalViewControllerAnimated:YES];
}
NSLog(@"done");

// get the image
NSLog(@"get the image...");
UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];
NSLog(@"done");
NSLog(@"correct image for orientation...");

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^(void) {
    image = [self imageCorrectedForCaptureOrientation:image]; // 3 sec
    //image = [image rotate:[image imageOrientation]]; // 1 - 6 sec
    NSLog(@"done");

    NSLog(@"make thumbnail...");
    CGSize thumbnailSize = CGSizeMake(200, 200);
    UIImage *thumbnailImage = [self imageByScalingNotCroppingForSize:image toSize:thumbnailSize];
    NSLog(@"done");

    NSLog(@"jpeg representation 1...");
    NSData* imageData = UIImageJPEGRepresentation(image, 1.0); // 4 sec
    NSLog(@"done");
    NSLog(@"jpeg representation 2...");
    NSData* thumbnailData = UIImageJPEGRepresentation(thumbnailImage, 1.0);
    NSLog(@"done");

    NSLog(@"save image and thumbnail...");
    NSString* imageRet = [self saveData:imageData toFile:self.imageName];
    NSString* thumbRet = [self saveData:thumbnailData toFile:self.thumbnailName];
    NSLog(@"done");

    NSLog(@"array two images...");
    //NSString *jsResult = [NSString stringWithFormat:@"{%@, %@}", imageRet, thumbRet];
    NSArray *jsResultA = [NSArray arrayWithObjects:imageRet, thumbRet, nil];
    NSLog(@"done");

    dispatch_async(dispatch_get_main_queue(),^ {
        NSLog(@"plugin stuff...");
        CDVPluginResult* result = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsArray:jsResultA];
        NSString* jsString = [result toSuccessCallbackString:self.callBackID];
        [self.webView stringByEvaluatingJavaScriptFromString:jsString];
        NSLog(@"done");

        timeFunc(dateFunctionStart, @"total time");
        NSLog(@"TEST END imagePickerController");

    });

});

}

另一种想法是与布拉德·拉尔森(Brad Larson)一起使用GPUImage进行外观和工作,但是请记住,无论在何处,如何以及以何种方式进行完整的图像尺寸操作都将是昂贵的.

Another idea would be to look and work with GPUImage by Brad Larson, however remember that full image size operations will be costly no matter where, how and with way.

最好的方法是仅尽快准备好您将在应用程序中立即使用的内容,并在后台队列中运行其他任务,然后在其中完成任务...

The best idea is to only prepare ASAP only what you will be use immediately in your app and run the other tasks in a background queue and finish them there...

这篇关于iPhone CGContextDrawImage和UIImageJPEGRepresentation大大减慢了应用程序的速度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆