iOS - возможно ли кешировать CGContextDrawImage? - PullRequest
1 голос
/ 31 марта 2012

Я использовал инструмент профиля синхронизации, чтобы определить, что 95% времени уходит на вызов функции CGContextDrawImage.

В моем приложении много повторяющихся изображений, которые неоднократно вырезаются из карты спрайтов и выводятся на экран. Мне было интересно, можно ли кешировать вывод CGContextDrawImage в NSMutableDictionay, тогда, если тот же спрайт запрашивается снова, его можно просто извлечь из кеша, а не выполнять всю работу по отсечке и рендерингу снова. Это то, что я получил, но не добился успеха:

Определения

if(cache == NULL) cache = [[NSMutableDictionary alloc]init];
//Identifier based on the name of the sprite and location within the sprite.
NSString* identifier = [NSString stringWithFormat:@"%@-%d",filename,frame];

Добавление в кеш

 CGRect clippedRect = CGRectMake(0, 0, clipRect.size.width, clipRect.size.height);
    CGContextClipToRect( context, clippedRect);

    //create a rect equivalent to the full size of the image
    //offset the rect by the X and Y we want to start the crop
    //from in order to cut off anything before them
    CGRect drawRect = CGRectMake(clipRect.origin.x * -1,
                                 clipRect.origin.y * -1,
                                 atlas.size.width,
                                 atlas.size.height);

    //draw the image to our clipped context using our offset rect
    CGContextDrawImage(context, drawRect, atlas.CGImage);
    [cache setValue:UIGraphicsGetImageFromCurrentImageContext() forKey:identifier];
    UIGraphicsEndImageContext();

Визуализация кэшированного спрайта Вероятно, есть лучший способ визуализации CGImage, который является моей конечной целью кэширования, но в данный момент я просто пытаюсь успешно визуализировать кэшированное изображение, однако это не увенчалось успехом.

 UIImage* cachedImage = [cache objectForKey:identifier];

if(cachedImage){
    NSLog(@"Cached %@",identifier);

    CGRect imageRect =  CGRectMake(0,
                                   0,
                                   cachedImage.size.width,
                                   cachedImage.size.height);

    if (NULL != UIGraphicsBeginImageContextWithOptions)
        UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, 0);
    else
        UIGraphicsBeginImageContext(imageRect.size);

    //Use draw for now just to see if the image renders out ok
    CGContextDrawImage(context, imageRect, cachedImage.CGImage);
     UIGraphicsEndImageContext();
}

1 Ответ

3 голосов
/ 31 марта 2012

Да, можно кэшировать визуализированное изображение.Ниже приведен пример того, как это делается:

+ (UIImage *)getRenderedImage:(UIImage *)image targetSize:(CGSize)targetSize
{
    CGRect targetRect = CGRectIntegral(CGRectMake(0, 0, targetSize.width, targetSize.height)); // should be used by your drawing code
    CGImageRef imageRef = image.CGImage; // should be used by your drawing code
    UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    // TODO: draw and clip your image here onto context
    // CGContextDrawImage CGContextClipToRect calls
    CGImageRef newImageRef = CGBitmapContextCreateImage(context);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
    CGImageRelease(newImageRef);
    UIGraphicsEndImageContext();
    return newImage;
}

Таким образом, вы получаете отрендеренную копию изображения ресурса.Потому что во время рендеринга у вас есть контекст, вы можете делать все, что захотите.Вам просто нужно заранее определить размер вывода.

Полученное изображение является просто экземпляром UIImage, который вы можете поместить в NSMutableDictionary для дальнейшего использования.

...