12

Generuję pakiet płytek dla CATiledLayer. Potrwa to około 11 sekund, aby wygenerować 120 płytek przy 256 x 256 z 4 poziomami szczegółów na iPhone 4S. Sam obraz mieści się w granicach 2048 x 2048.Jakikolwiek sposób kodowania PNG szybciej niż UIImagePNGRepresentation?

Moje wąskie gardło to UIImagePNGRepresentation. Wykonanie każdego obrazu 256 x 256 zajmuje około 0,10-0,15 sekundy.

Próbowałem już generować wiele płytek w różnych kolejkach tła, ale to tylko obniża je do około 9-10 sekund.

Ja również próbowałem przy użyciu ramy ImageIO z kodem tak:

- (void)writeCGImage:(CGImageRef)image toURL:(NSURL*)url andOptions:(CFDictionaryRef) options 
{ 
    CGImageDestinationRef myImageDest = CGImageDestinationCreateWithURL((__bridge CFURLRef)url, (__bridge CFStringRef)@"public.png", 1, nil); 
    CGImageDestinationAddImage(myImageDest, image, options); 
    CGImageDestinationFinalize(myImageDest); 
    CFRelease(myImageDest); 
} 

Mimo to uzyskuje się mniejsze pliki PNG (wygrana!), Trwa około 13 sekund, 2 sekundy więcej niż wcześniej.

Czy istnieje sposób na szybsze kodowanie obrazu PNG z CGImage? Być może robi to biblioteka korzystająca z rozszerzenia ARM NEON (iPhone 3GS +), np. libjpeg-turbo?

Czy istnieje lepszy format niż PNG do zapisywania płytek, które nie zajmują dużo miejsca?

Jedyną realną opcją, jaką udało mi się wymyślić, jest zwiększenie rozmiaru kafli do 512 x 512. Skraca to czas kodowania o połowę. Nie jestem pewien, co to może zrobić z moim widokiem przewijania. Ta aplikacja jest przeznaczona dla iPada 2+ i obsługuje tylko iOS 6 (używając iPhone 4S jako linii bazowej).

Odpowiedz

4

Okazuje się, dlaczego UIImageRepresentation wykonywał tak źle, ponieważ był dekompresji obraz oryginalny każdym razem chociaż przemyślany byłem tworząc nowy obraz z CGImageCreateWithImageInRect.

można zobaczyć wyniki z instrumentów tutaj:

enter image description here

Zawiadomienie _cg_jpeg_read_scanlines i decompress_onepass.

I był siły dekompresji obrazu z tym:

UIImage *image = [UIImage imageWithContentsOfFile:path]; 
UIGraphicsBeginImageContext(CGSizeMake(1, 1)); 
[image drawAtPoint:CGPointZero]; 
UIGraphicsEndImageContext(); 

Moment to około 0,10 sekund, prawie równoważne z czasu potrzebnego każdej UIImageRepresentation połączenia.

Istnieje wiele artykułów w Internecie, które zalecają rysunek jako sposób na dekompresję obrazu.

Istnieje artykuł na temat Cocoanetics Avoiding Image Decompression Sickness. Artykuł zapewnia alternatywny sposób ładowania obrazu:

NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] 
               forKey:(id)kCGImageSourceShouldCache]; 
CGImageSourceRef source = CGImageSourceCreateWithURL((__bridge CFURLRef)[[NSURL alloc] initFileURLWithPath:path], NULL); 
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, (__bridge CFDictionaryRef)dict); 
UIImage *image = [UIImage imageWithCGImage:cgImage]; 
CGImageRelease(cgImage); 
CFRelease(source); 

A teraz ten sam proces trwa około 3 sekund! Używanie GCD do generowania płytek równolegle skraca czas znacznie bardziej.

Powyższa funkcja zajmuje około 5 sekund. Ponieważ rozmiary plików są mniejsze, podejrzewam, że kompresja zlib jest na wyższym poziomie.

Powiązane problemy