Приложение для разрушения больших изображений CATiledLayer - PullRequest
0 голосов
/ 27 июня 2010

Это в некоторой степени связано с другим постом - но этот был немного запутан - поэтому я начинаю с нуля:

У меня есть CATiledLayer с огромным изображением (5780x6700px).

Плиточный слой находится в виде прокрутки.Когда я начинаю прокручивать, все в порядке до точки, где явно слишком много плиток рендерится.Затем я получаю предупреждение о памяти, и приложение вылетает.

Я попытался удалить плиточный слой из представления, когда получаю предупреждение о памяти, очистить его содержимое (rootLayer.contents = nil AND tiledLayer.contents = nil) изатем снова прикрепите его пустым к виду.не работал ...

Был бы благодарен за любой ввод ...

Редактировать:

Спасибо за подсказки до сих пор.Некоторые из моих предположений кажутся неверными.Я загрузил изображение в функцию, а затем сохранил его - что, по-моему, противоречит поведению CATiledLayer.Плюс UIImage imageNamed:, похоже, тоже вызывал некоторые ошибки.Теперь я загружаю изображение в drawLayer:(CALayer *) inContentext(CGContextRef) ctx и использую UIImage imageWithContentsOfFile: для его загрузки.

Кажется, что это работает, не приводя к уменьшению памяти.

Однако - плитки нарисованы мучительно медленно: (

Вот мои настройки для уровня tiledLayer:

-(CATiledLayer *)initTiledLayers: (int)level{

    //[tiledLayer release];

    CGRect pageRect;

    CATiledLayer *myLayer = [CATiledLayer layer];
    myLayer.delegate = self;

    if(level == 1){     
        pageRect = CGRectMake(0,  0,  690, 800);
        myLayer.tileSize = CGSizeMake(800, 800);
        myLayer.levelsOfDetail = 10;
        myLayer.levelsOfDetailBias = 2;
    }else if(level == 2){
        pageRect = CGRectMake(0,  0,  1445, 1675);
        myLayer.tileSize = CGSizeMake(600, 600);
        myLayer.levelsOfDetail = 8;
        myLayer.levelsOfDetailBias = 2;
    }else if(level == 3){   
        pageRect = CGRectMake(0,  0,  2890, 3350);
        myLayer.tileSize = CGSizeMake(400, 400);
        myLayer.levelsOfDetail = 4;
        myLayer.levelsOfDetailBias = 1;
    }else if(level == 4){
        pageRect = CGRectMake(0,  0, 5780, 6700);
        myLayer.tileSize = CGSizeMake(150, 150);
        myLayer.levelsOfDetail = 4;
        myLayer.levelsOfDetailBias = 0;
    }

    myLayer.frame = pageRect;

    return myLayer;
    [myLayer release];
}

(int) указывает, какое изображение будет использоваться (я переключаю изображения на определенных уровнях масштабирования). Level4 - этосамое большое изображение ...

А вот функция drawLayer:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(ctx, CGContextGetClipBoundingBox(ctx));
CGContextTranslateCTM(ctx, 0.0, layer.bounds.size.height);
CGContextClearRect(ctx, CGRectMake(0,0,layer.bounds.size.width, layer.bounds.size.height));
CGContextScaleCTM(ctx, 1.0, -1.0);

    UIImage *map = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Karte0%d", actLevel] ofType:@"jpg"]];
    UIImage *wanderwege = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Karte0%d_wanderwege", actLevel] ofType:@"png"]];
    UIImage *rhb = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Karte0%d_rhb", actLevel] ofType:@"png"]];
    UIImage *abstecher = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Karte0%d_abstecher", actLevel] ofType:@"png"]];

    CGRect imageRect = CGRectMake (0.0, 0.0, map.size.width, map.size.height);
    CGContextDrawImage (ctx, imageRect, [map CGImage]);

    imageRect = CGRectMake (0.0, 0.0, wanderwege.size.width, wanderwege.size.height);
    CGContextDrawImage (ctx, imageRect, [wanderwege CGImage]);

    imageRect = CGRectMake (0.0, 0.0, rhb.size.width, rhb.size.height);
    CGContextDrawImage (ctx, imageRect, [rhb CGImage]);

    imageRect = CGRectMake (0.0, 0.0, abstecher.size.width, abstecher.size.height);
    CGContextDrawImage (ctx, imageRect, [abstecher CGImage]);

}

Да, я знаю, я на самом деле рисую 4 изображения в контексте. PNG - это наложения, которые мне нужны для динамическогодобавить к основному изображению ...

Я пытался объединить изображения в одно - но это, кажется, еще больше потребляет память / процессор;)

Любая дополнительная помощь очень ценится!

Ответы [ 3 ]

2 голосов
/ 27 августа 2010

Почему вы рисуете все изображение в обратном вызове делегата?

Проблема в том, что CATiledLayer разбивает все содержимое на прямоугольники и передает обрезанный контекст в обратный вызов делегата: - (void) drawLayer: (CALayer *) слой inContext: (CGContextRef) ctx

Это происходит для всех прямоугольников, и поскольку их много, а изображение, которое вы рисуете, является большим и отнимает много времени, общий процесс длится "веками".

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

В вашем случае (1 большой pdf) я бы попробовал нарисовать только часть изображения. Не уверен, поможет ли это в любом случае:)

1 голос
/ 20 июня 2011

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

Вам нужно как-то предварительно разделить их на две половины и четверти и кэшировать на диск, а затем отобразить плитки оттуда.См. Обзор прокрутки WWDC 2010, в котором показано, как это сделать плавно.

0 голосов
/ 21 августа 2010

Я обнаружил, что неправильно использовал tiledLayer. Кроме того, я использовал PNG в качестве оверлеев и мне пришлось правильно настроить режим наложения на tiledLayer, чтобы избавиться от черных экранов ...

[править] и не забывать (как упоминает Эндрю ниже), большое изображение должно быть разрезано на тайлы (например, увеличение для PSD). Если вы используете мозаичный слой с одним большим изображением, он не будет работать ...

...