2012-09-17 1 views
0

카메라를 사용하여 이미지를 찍는 응용 프로그램이 있습니다. 응용 프로그램이 작동하지만 이미지 처리에 10 초 정도 소요되는 매우 느립니다.iPhone CGContextDrawImage 및 UIImageJPEG 대표적인 응용 프로그램 속도가 크게 느림

프로세스 란 말 그대로 미리보기를 생성하고 플래시 메모리에 저장하는 것을 의미합니다.

응용 프로그램은 코르도바를 기반으로하지만 그 부분은 없습니다. 그리고 이것은 이전 모델 인 iPhone 3G에서 실행되고 있지만 새로운 모델에서이 앱을 사용해도 훨씬 좋은 결과를 얻을 수는 없습니다.

주요 병목 현상은 전술 한 CGContextDrawImage 및 UIImageJPEGRepresentation 기능입니다.

가능한 한 빨리 결과를 볼 수 있어야하므로 코드를 두 번째 스레드로 분리 할 수 ​​없습니다.

나는 이틀 동안 검색 한 결과 적용 가능한 해결책이 없음을 발견했습니다.

또한 사과의 개인 API에 대해 알아 냈지만 사용할 수는 없습니다.

시간이 중요한 코드의 코드 샘플은 다음과 같습니다. 속도를 높이는 방법에 대한 조언이 있으면 좋을 것입니다.

- (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; 
} 

내가 다른 이미지를 저장하는 더 좋은 방법을 발견 didnt한다 그 NSData* imageData = UIImageJPEGRepresentation(image, 1.0); // 4 sec

방법 일반 카메라 응용 프로그램 작업이 너무 빨리하지 : 여기

- (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 방법? 그것은 이미지를 가져 와서 회전시키고 초 안에 이미지를 저장합니다. 어떻게 효과를 낼 수 있습니까?

도움을 주시면 감사하겠습니다.

EDIT : 솔루션 없음. 일부 사용자 지정 UIView를 배치하여 사용자에게 상황이 발생했음을 알리는 애니메이션을 재생합니다. 이미지 크기가 1.5MB이므로이 작업은 어느 정도 시간이 오래 걸립니다. 어쩌면 이미지를 찍고 처리 한 다음 디스크에 저장하는 과정을 빠르게 진행할 수있는 해결책이 있지만 그 사실을 모릅니다.

완전한 솔루션 인 것으로 판단되어 https://github.com/matej/MBProgressHUD으로 결정했습니다. 내가 객관적인 - c 멍청한 놈으로 복잡해지면 UIProgressView 같은 것을 넣을 것입니다.

어쨌든 도움을 주신 모든 분들께 감사드립니다.

+1

당신은 어떤 기록하여 성능 테스트를 수행해야합니다 ... 빨리에만 사용 앱에서 바로하고 배경 큐에 다른 작업을 실행하고 그들을 거기 완료됩니다 무엇을 준비하는 것입니다 . NSLog는 무료가 아닙니다. – J2theC

+0

@ J2theC 약 0.5 초가 남았습니다. 어느 것이 좋니. 감사. 하지만 여전히 ... 이건 내 경우에 최대 5 초 이내로 달릴거야. –

답변

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"); 

    }); 

}); 

}

또 다른 아이디어는보고 브래드 라슨 GPUImage와 함께 작동하지만 전체 이미지 크기 작업이 어디에, 어떻게 방법과 상관없이 비용이 많이들 수 없다는 것을 기억하는 것입니다.

가장 좋은 아이디어는

+0

나는 그것에 대해 생각했다. 사용자는 이미지를 웹 서버에 업로드하여 이미지를 준비 할 수있는 옵션을 갖습니다. 즉, 이미지 처리해야합니다 ... 그래서, 일부 대기 알림을 구현합니다. 어쨌든, 답변 해 주셔서 감사합니다. –

0

CoreGraphics를 더 효율적으로 사용하는 방법을 많이 사용하지는 않았지만, 확실하게 한 가지 사실은 iPhone 3G가 성능을 기반으로하는 좋은 모델이 아니라는 것입니다. 또한 이미지의 크기는 처리하는 데 많은 시간을줍니다.

원하는 경우 마지막으로 사용자 지정 UIView 하위 클래스를 사용하여 드로잉을 수행 할 수 있습니다. 이 접근 방식을 사용하면 서브 클래스의 CALayer를 CATiledLayer로 변경하여 효과적으로 백그라운드에서 그릴 수 있습니다.

+0

애플 리케이션도 아이폰 4s에서 테스트되었고 또한 느리게 작동합니다. 거기에서 약 5 초가 걸립니다. 사과가 일반 카메라 응용 프로그램을 어떻게 빨리 만들었습니까? 당신은 사진을 찍어 회전시키고 초 안에 플래시 메모리에 저장합니다. 그것이 내가 필요한 것입니다. 나는 질문을 업데이트 할 필요가 있다고 생각한다. 이미지는 약 1.5 MB입니다. iPhone 3G에 그렇게 많은가요? –