我有一个使用相机拍摄图像的应用程序。 应用程序有效,但速度很慢,需要大约10秒钟来处理图像。
通过流程我的意思是,旋转,创建缩略图并将它们保存到闪存中。
应用程序基于Cordova,但我没有参与其中。 这是在较旧型号iPhone 3G上运行,但在较新型号上试用此应用程序并不会产生更好的效果。
主要瓶颈是前面提到的CGContextDrawImage和UIImageJPEGRepresentation函数。
我无法将该代码分成第二个帖子,因为结果必须尽快显示。
我搜索了两天,发现没有适用的解决方案。
我也发现了苹果的私有API,但我无法使用它们。
以下是时间关键代码的代码示例,如果您对如何加快速度有任何建议,那就太棒了。
- (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 sec
常规相机应用如何快速工作?它会拍摄图像,旋转图像并在一秒钟内将图像保存到闪光灯中。 如何产生这种效果?
感谢任何帮助。
编辑:没有解决方案。 我将放置一些自定义UIView来播放一些动画来通知用户发生了什么事。由于图像很大,1.5 MB,这些操作必须持续一段时间。 也许有解决方案可以加速拍摄图像,处理图像然后保存到磁盘的整个过程,但我不知道。我决定使用https://github.com/matej/MBProgressHUD,因为它似乎是完整的解决方案。 如果它被证明是复杂的,因为我是Objective-c noob,我会把UIProgressView或其他东西。
无论如何,感谢所有人试图提供帮助。
答案 0 :(得分:2)
我建议您使用GCD并在另一个线程中处理图像.... 每次调用UIImageJpegRepresentation都会花费很多,因为它会将图像解码到设备的内存中......
- (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,但请记住,无论在何处,如何以及如何使用,完整图像大小的操作都将是昂贵的。
最好的想法是只准备ASAP,只在你的应用程序中立即使用,并在后台队列中运行其他任务并在那里完成...
答案 1 :(得分:0)
我还没有太多地使用CoreGraphics来了解如何提高效率,但有一点可以肯定的是,iPhone 3G不是一个基于性能的好模型。此外,图像的大小会极大地影响处理所需的时间。
最后,如果需要,可以使用自定义UIView子类进行绘图。采用这种方法,您可以将子类的CALayer更改为CATiledLayer,有效地在后台绘图。