2010-10-06 2 views
2

Кто-нибудь знает, каковы ограничения на размер изображения с помощью пользовательских CIFilters? Я создал фильтр, который работает так, как ожидалось, когда изображения имеют до 2 мегапикселей, но затем дают очень странные результаты, когда изображения больше. Я тестировал это как в своем приложении для какао, так и в кварцевом композиторе. Фильтр, который я разработал, представляет собой фильтр искажений геометрии, который (я думаю) требует ROI и DOD, который охватывает все входное изображение. Я создал этот фильтр для переназначения панорамных изображений, поэтому мне бы хотелось, чтобы это работало на очень больших (50-100 мегапиксельных) изображениях.Максимальный размер изображения в CIFilter/CIKernel?

В качестве простого теста рассмотрим следующий CIFilter (может использоваться в Quartz Composer), который просто преобразует изображение, чтобы нижний левый угол изображения был переведен в центр (я знаю, что это можно сделать с помощью аффинное преобразование, но мне нужно выполнить такую ​​операцию в более сложном фильтре). Этот фильтр работает так, как ожидалось, когда изображение 2000x1000, но производит нечетные результаты, когда входное изображение составляет 4000x2000 пикселей. Проблема в том, что либо перевод не переводит угол в центр точно, либо что выход изображения полностью исчез. Я заметил другие странные проблемы с более сложными фильтрами на больших изображениях, но я думаю, что этот простой фильтр иллюстрирует мою проблему и может быть воспроизведен в Quartz Composer.

kernel vec4 equidistantProjection(sampler src, __color color) 
{ 
    vec2 coordinate = samplerCoord(src); 
    vec2 result; 
    vec4 outputImage; 

    result.x = (coordinate.x - samplerSize(src).x/2.0); 
    result.y = (coordinate.y - samplerSize(src).y/2.0); 

    outputImage = unpremultiply(sample(src,result)); 

    return premultiply(outputImage); 
} 

То же самое странное поведение появляется при использовании Рабочих координат вместо координат сэмплер, но в этом случае возникает ошибка для изображений размера 2000x1000, но отлично работает для изображений размера 1000x500

kernel vec4 equidistantProjection(sampler src, __color color, vec2 destinationDimensions) 
{ 
    vec2 coordinate = destCoord(); 
    vec2 result; 
    vec4 outputImage; 

    result.x = (coordinate.x - destinationDimensions.x/2.0); 
    result.y = (coordinate.y - destinationDimensions.y/2.0); 

    outputImage = unpremultiply(sample(src,result)); 
    outputImage = unpremultiply(sample(src,samplerTransform(src, result))); 

    return premultiply(outputImage); 
} 

Для reference Я добавил к разделу Objective-C метода - (CIImage *)outputImage моего фильтра следующее, чтобы установить DOD как полное входное изображение.

- (CIImage *)outputImage 
{ 
    CISampler *src = [CISampler samplerWithImage: inputImage]; 



    NSArray * outputExtent = [NSArray arrayWithObjects: 
      [NSNumber numberWithInt:0], 
      [NSNumber numberWithInt:0], 
      [NSNumber numberWithFloat:[inputImage extent].size.width], 
      [NSNumber numberWithFloat:[inputImage extent].size.height],nil]; 


return [self apply: filterKernel, src, inputColor, zoom, viewBounds, inputOrigin, 
    kCIApplyOptionDefinition, [src definition], kCIApplyOptionExtent, outputExtent, nil]; 

} 

Кроме того, я добавил следующий метод для установки ROI, который я называю в моем - (id)init методе с этим: [filterKernel setROISelector:@selector(regionOf:destRect:userInfo:)];

- (CGRect) regionOf:(int)samplerIndex destRect:(CGRect)r userInfo:obj 
{ 

    return r; 
} 

Любая помощь или консультации по этому вопросу будет весьма признателен. Я уверен, что CIFilters могут работать с большими изображениями, поскольку я использовал CIBumpDistortion с изображениями более 50 мегапикселей, поэтому я должен что-то делать неправильно. Есть идеи?

ответ

2

Работа с CoreImage Я обнаружил, что он разрезает большие изображения на части. Например, в вашем случае изображение 4k x 2k может быть разделено на 4 изображения 2 x x 1 k и отображено отдельно. К сожалению, эти трюки оптимизации влияют на samplerCoord, а некоторые зависящие от координат фильтры работают неправильно на больших изображениях.

Мое решение было в использовании destCoord вместо samplerCoord. Конечно, вы должны иметь в виду, что изображение может быть отображено в ненулевом начале и destCoord. Я написал свой собственный фильтр, так что я смог пройти в целом как параметр vec4.

Пример: попытаться сформировать изображение с CIFilter, что-то вроде этого:

float gray = (samplerCoord.x/samplerSize.width) * (samplerCoord.y/samplerSize.height); 

Этот вывод должен дать нам черный цвет в (0,0) и белый в точке (1,1), не так ли? Однако для больших изображений вы увидите несколько квадов, а не один градиент.Это происходит за счет оптимизированной визуализации наступающем от двигателя CoreImage, я не нашел способ передать его, но вы можете переписать ядру таким образом:

float gray = ((destCoord.x - rect.x)/rect.size) * ((destCoord.y - rect.y)/rect.height) 

Где Прямоугольник является реальной степени пробоотборник, который вы должны пройти. Для этой цели я использовал [inputImage extent], но это зависит от фильтра и может быть чем-то другим в вашем случае.

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

+0

Есть ли способ узнать, что происхождение мозаичного изображения является априори? Если вы пройдете в 4-й степени (происхождение x, начало координат y, ширина, высота), вы можете программным образом определить, как CoreImage будет обрезать изображение на части, чтобы узнать, где происхождение будет для каждого фрагмента? Или я что-то упускаю. То, что я делал с достойными результатами, - это использование destCoord, а затем samplerTransform, в то время как явное пропускание всей длины входного изображения в качестве ROI. Это хорошо работает, пока входное изображение достаточно мало. –

+0

Я редактировал свое сообщение с примером – Gobra

Смежные вопросы