2013-08-16 4 views
0

UICollectionView은 코어 이미지로 조작 한 이미지가 포함 된 셀이 주로 채도가 낮은 이미지로 구성된 UICollectionView입니다. 스크롤 할 때 성능은 절대적으로 끔찍합니다. 프로필을 작성할 때, 대부분의 시간 (80 % 정도)은 내 코드 또는 스택에 있지 않습니다. 모두 Core Animation 코드에있는 것 같습니다. 왜 이것이 될 수 있는지 아는 사람이 있습니까?UICollectionView Core Image 조작 이미지가있는 UIImageViews의 성능이 좋지 않습니다.

UIImage *img = [self obtainImageForCell]; 
img = [img applySaturation:0.5]; 
self.imageView.image = img; 

applySaturation는 다음과 같습니다 :

CIImage *image = [CIImage imageWithCGImage:self.CGImage]; 
CIFilter *filter = [CIFilter filterWithName:@"CIColorControls"]; 
[filter setValue:image forKey:kCIInputImageKey]; 
[filter setValue:[NSNumber numberWithFloat:saturation] forKey:@"inputSaturation"]; 
return [UIImage imageWithCIImage:filter.outputImage]; 

내 유일한 생각은 코어 애니메이션은 코어 이미지와 잘 재생되지 않는다는 것입니다 내 UICollectionViewCell 서브 클래스에서

나는 이런 식으로 뭔가가있다. CIImage 객체에 연관된 이미지 데이터를 가지고

있지만, 이미지 일치하지 않음 Apple docs이 약 CIImage 말한다. CIImage 객체를 이미지 "recipe"로 생각할 수 있습니다. CIImage 객체는 이미지를 생성하는 데 필요한 모든 정보를 가지고 있지만 코어 이미지는 실제로 그렇게 할 때까지 이미지를 렌더링하지 않습니다. 이 "게으른 평가"방법은 Core Image가 가능한 한 효율적으로 작동하도록합니다.

애니메이션 처리 중 마지막 단계에서이 평가를하는 것은 까다로울 수 있습니다.

+1

필터링을 한 번 시도해 본 결과가 캐싱 되었습니까? –

+0

나는 같은 슬로우 스크롤 동작을 참조하십시오. – openfrog

답변

2

정확히 똑같은 문제가 있었는데 셀 업데이트 중에 코어 이미지 필터가 실행되는 것을 피하여 치료했습니다.

게으른 평가/조리법에 관한 Apple의 문서는 핵심 이미지 필터를 매우 효율적으로 연결할 수 있다는 아이디어에 더 중점을 둡니다. 그러나 코어 이미지 필터 체인의 결과를 표시하려면 신속하게 스크롤하는보기에서 '다음'이 나오면 좋은 상황이 아니며 그 곳에서 평가해야합니다. 질문은 무거운 처리가 필요합니다 (대다수가 처리).

나의 추천은 치료하는 것입니다 (내 대답 here 참조) 당신은 CPU 처리 대 GPU 만지작 시도 할 수 있습니다,하지만 난과 CIImage에서 이미지 데이터를 이동하는 오버 헤드가 더 중요한 오버 헤드가 될 수 있음을 발견했다 이러한 종류의 처리는 온라인 이미지 (예 : 비동기식 처리, 자리 표시 자 (예 : 전처리 된 이미지) 사용) 및 재사용을위한 캐시 결과와 같은 스크롤 뷰의 채우기를 처리하는 것과 동일한 방식으로 처리합니다.

갱신 귀하의 코멘트에 회신

: 당신이 CIImage에서 데이터를 추출 할 때

적용 필터가 적용됩니다 - 예를 들어, imageWithCIImage: [경고 -이 내 추론이다, 내가 테스트하지 않았습니다를 ].

그러나 이것은 문제가 아닙니다. 스크롤링을 유지하는 데 시간이 걸리기 때문에 이미지를 백 그운드 스레드에서 처리해야합니다. 그 사이에 편평한 색깔 또는 더 나은 - UIImage와 같은 두루 말기 세포에서 다른 것을 표시하십시오 당신은 당신의 CIImage로 먹이를 먹이고 있습니다. 처리가 끝나면 셀을 업데이트합니다 (아직 업데이트가 필요한지 확인하고 그때까지 화면이 스크롤되지 않을 수 있습니다).필터링 된 이미지를 일종의 영구 저장소에 저장하여 두 번째 필터링 할 필요가 없도록하고 처음부터 다시 처리하기 전에 이미지를 다시 표시해야 할 때마다 캐시를 ​​확인하십시오.

+0

필터를 즉시 적용하도록 어떻게 제안 하시겠습니까? –

+0

@ Mr.Jefferson, 내 확장 된 답글보기 – foundry

+0

이미'imageWithCIImage'를 사용하고 있습니다. 채도를 적용하는 내 메서드는 UIImage를 반환합니다. 앱을 프로파일 링 할 때 코드가 무거운 스택 추적 위치에 있지 않습니다. Core Animation은 스크롤보기가 스크롤 될 때 이미지 "recipe"를 적용해야합니다. –

0

나는 또한이 정확한 문제를 가지고있었습니다. 바로 이미지를 채도 저하시키고 싶었습니다! - 한 번 필터링하고 결과를 캐싱 (심지어 UIImage로) 도움이되지 않았다.

다른 사람들이 말한 것처럼 문제는 CIImage은 이미지를 생성하는 데 필요한 정보를 캡슐화하지만 실제로는 이미지 자체가 아닙니다. 따라서 스크롤 할 때 온 스크린 이미지를 즉시 생성해야하므로 성능이 저하됩니다. imageWithCIImage:scale:orientation: 메서드를 사용하여 만든 UIImage도 마찬가지이므로이 코드를 한 번 만들고 다시 사용하면 도움이되지 않습니다.

해결 방법은 CoreGraphics가 이미지를 UIImage로 저장하기 전에 실제로 렌더링하도록하는 것입니다. 이것은 나를 위해 스크롤링 성능을 크게 향상 시켰습니다. 귀하의 경우, applySaturation 방법은 다음과 같습니다 이들에 비용이 많이들 수 있기 때문에

CIImage *image = [CIImage imageWithCGImage:self.CGImage]; 
CIFilter *filter = [CIFilter filterWithName:@"CIColorControls"]; 

[filter setValue:image forKey:kCIInputImageKey]; 
[filter setValue:[NSNumber numberWithFloat:saturation] forKey:@"inputSaturation"]; 

CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:filter.outputImage fromRect:filter.outputImage.extent]; 
UIImage *image = [UIImage imageWithCGImage:cgImage]; 
CGImageRelease(cgImage); 

return image; 

또한,이 방법을 많이 사용하게 될 겁니다 경우 CIFilter 및/또는 CIContext 캐싱을 고려해 볼 수 있습니다 몹시 떠들어 대다.