Выполнение дорогостоящей операции распаковки! что это такое и как это исправить?

Консоль отладки для моего тестового приложения Core Filters показывает это сообщение:

CGImageRef 0x7a0e890 имеет заполнение строк байтами. Выполнение дорогостоящей операции распаковки!

Я не смог найти ответ для этого точного сообщения (без информации об указателе) ни в заголовках, ни в поиске Google.

Мои вопросы: (1) что это значит и (2) как я могу исправить ситуацию?

Ниже приведен пример создания отфильтрованного UIImage с помощью CIFilter.

- (UIImage*)sepia
{    
    CIImage *beginImage = [CIImage imageWithCGImage:[self CGImage]];
    CIContext *context = [CIContext contextWithOptions:nil];

    CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone" 
                                  keysAndValues: kCIInputImageKey, beginImage, 
                        @"inputIntensity", [NSNumber numberWithFloat:0.8], nil];
    CIImage *outputImage = [filter outputImage];

    CGImageRef cgimg = 
    [context createCGImage:outputImage fromRect:[outputImage extent]];
    UIImage *newImg = [UIImage imageWithCGImage:cgimg];

    self = newImg;

    CGImageRelease(cgimg);
    return self;
}

person james_womack    schedule 17.11.2011    source источник
comment
Я так и не получил верного ответа на свой вопрос — моя ситуация специфична для iOS, и я предоставил код, вызывающий проблему, но не получил решения. Робин был единственным человеком, который вообще оказал какую-либо помощь, и вопрос не проявил никакого интереса. Я бы предложил награду, но я видел много наград, присужденных без достаточного ответа, поэтому оно того не стоит.   -  person james_womack    schedule 24.11.2011
comment
Мы только начали сталкиваться с этой проблемой сегодня, и у нас также возникли проблемы с ее отслеживанием.   -  person Beltalowda    schedule 12.01.2012
comment
@ThuggishNuggets — пожалуйста, дайте мне знать, если вы обнаружите какую-либо новую информацию   -  person james_womack    schedule 14.01.2012
comment
Мы исправили это, убедившись, что ширина изображения кратна 4, что имеет смысл, учитывая ответ @Robin ниже. Насколько я понимаю, как это работает, количество байтов в строке должно делиться на степень 2. Это сработало в нашем случае, потому что наш формат пикселей был RGBA8888 или 4 байта на пиксель. Ограничивая нашу ширину кратной 4, мы гарантировали, что каждое увеличение ширины изображения на 4 пикселя добавляло 16 байтов к строке, что делало количество байтов в строке всегда кратным 16, что равно 2^4 (делится на степень из 2).   -  person Beltalowda    schedule 15.01.2012


Ответы (3)


Байтовое заполнение — это дополнительные байты, добавляемые в конец каждой строки изображения, чтобы каждая строка начиналась с кратного 2^n байта в памяти. Это увеличивает производительность доступа к памяти за счет размера изображения. Вы можете проверить это, если сравните результат CGImageGetBytesPerRow и ожидаемые байты на строку, рассчитанные на основе размеров изображения и байтов на пиксель.

Что касается того, как исправить распаковку - вам нужно точно определить, какая операция запускает распаковку, и взять ее оттуда. Распаковка обходится дорого, потому что, по сути, необходимо перетасовать всю память изображения, чтобы удалить все пробелы в конце строки.

person Robin Summerhill    schedule 17.11.2011

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

У меня была такая же ошибка, и я попытался исправить ее, используя предложение Thuggish Nuggets. Оказалось, что это правильный подход, однако размер изображения должен быть кратным 8. Я просто выровнял ширину по множеству 8, я не знаю, должна ли высота также быть кратной 8, так как изображение, которое я в любом случае протестировал этот подход с квадратичным значением.

Вот алгоритм (вероятно, не очень эффективный), чтобы дать вам базовое представление о том, как рассчитать необходимый размер:

UIImage *image = ...;
CGSize targetSize = image.frame.size; //e.g. 51 x 51
double aspectRatio = targetSize.width / targetSize.height;
targetSize.width = targetSize.width + 8 - ((int)targetSize.width % 8);
targetSize.height = targetSize.width / aspectRatio;
person Florian    schedule 27.06.2012

Я подозреваю, что «дорогостоящая операция распаковки» является подделкой. Причина: я получаю его в Симуляторе, но нет на устройстве. Следовательно, я считаю, что это вводящий в заблуждение артефакт среды симулятора.

person matt    schedule 27.04.2013
comment
Мой пост был создан примерно за 16 месяцев до этого (поэтому я не совсем понимаю, какие были подробности), но у меня такое чувство, что вы вполне можете быть правы. Какое устройство, какая версия ОС? В то время я использовал iOS 5. - person james_womack; 27.04.2013