2015-09-14 2 views
5

Я пытаюсь создать карту смещения cikernel для iOS 8, которая перемещает пиксели по горизонтали от канала R карты и вертикально от канала G. Координаты пикселя карты должны быть сопоставлены с исходным размером изображения mapPixel = ((dest.x/source.width) * map.width, (dest.y/source.height) * map.height)Пользовательская карта смещения CIKernel

размер входного изображения, что я проверяю с является 2048 x 2048 и карта красный-зеленый шума Перлина 2560 х 2560

в Quartz композитор cikernel работает почти как и следовало ожидать, за исключением того, что карта не применяется ко всему изображению

kernel vec4 coreImageKernel(sampler image, sampler displaceMap, float scaleX, float scaleY) 
{ 
vec2 destination = destCoord(); 

vec2 imageSize = samplerSize(image); 
float xPercent = destination.x/imageSize.x; 
float yPercent = destination.y/imageSize.y; 

vec2 mapSize = samplerSize(displaceMap); 
vec2 mapCoord = vec2(mapSize.x * xPercent, mapSize.y * yPercent); 

vec4 mapPixel = sample(displaceMap, mapCoord); 
float ratioShiftX = ((mapPixel.x) * 2.0) - 1.0; 
float ratioShiftY = ((mapPixel.y) * 2.0) - 1.0; 
vec2 pixelShift = vec2(ratioShiftX * scaleX, ratioShiftY * scaleY); 

return sample(image, destination - pixelShift); 
} 

Вот как выглядит функция фильтра:

function __image main(__image image, __image displaceMap, __number scaleX, __number scaleY) { 
    return coreImageKernel.apply(image.definition, null, image, displaceMap, scaleX, scaleY); 
} 

Но когда я загружаю цикернель в CIFilter, результат далек от того, что я вижу в Quartz Composer. Вот то, что моя применить функцию выглядит в CIFilter

override var outputImage:CIImage? { 
    if let inputImage = inputImage { 
     if let inputMap = inputMap { 
      let args = [inputImage as AnyObject, inputMap as AnyObject, inputScaleX, inputScaleY] 

      return CIDisplacementMapFilter.kernel?.applyWithExtent(inputImage.extent, roiCallback: { 
        (index, rect) in 

        if index == 0 { 
         return rect 
        } 

        return CGRectInfinite 
       }, arguments: args) 
     } 
    } 

    return nil 
} 

Я предполагаю, что ROI является неправильным и пробоотборник плиткой, но я не могу понять это.

ответ

1

Как оказалось, ядро ​​было неправильным. Вот ядро, которое делает работу

kernel vec4 displace(sampler source, sampler map, float scaleX, float scaleY) 
{ 

vec2 d = destCoord(); 
vec4 mapPixel = sample(map, samplerTransform(map, d)); 
float shiftX = ((mapPixel.x * 2.0) - 1.0) * scaleX; 
float shiftY = ((mapPixel.y * 2.0) - 1.0) * scaleY; 

vec2 s = samplerTransform(source, d + vec2(shiftX, shiftY)); 

return sample(source, s); 
} 
Смежные вопросы