2010-10-06 25 views
2

Est-ce que quelqu'un sait quelles sont les limites sur la taille de l'image avec des CIFilters personnalisés? J'ai créé un filtre qui fonctionne comme prévu lorsque les images atteignent 2 méga pixels, mais produit des résultats très étranges lorsque les images sont plus grandes. J'ai testé cela à la fois dans mon application de cacao ainsi que dans le compositeur de quartz. Le filtre que j'ai développé est un filtre de distorsion de type géométrique qui (je pense) nécessite une ROI et un DOD qui couvre toute l'image d'entrée. J'ai créé ce filtre pour remapper des images panoramiques, donc je voudrais que cela fonctionne sur de très grandes images (50-100 méga pixels). En guise de simple test, le CIFilter suivant (peut être utilisé dans Quartz Composer) traduit simplement l'image de sorte que le coin inférieur gauche des images soit traduit au centre (je sais que cela peut être fait avec un transformation affine mais j'ai besoin d'effectuer une telle opération dans un filtre plus complexe). Ce filtre fonctionne comme prévu lorsque l'image est 2000x1000 mais produit des résultats impairs lorsque l'image d'entrée est 4000x2000 pixels. Le problème est que la traduction ne déplace pas exactement le coin vers le centre ou que la sortie de l'image est complètement disparue. J'ai remarqué d'autres problèmes bizarres avec des filtres plus compliqués sur de grandes images mais je pense que ce simple filtre illustre mon problème et peut être reproduit dans Quartz Composer.taille d'image maximale dans CIFilter/CIKernel?

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); 
} 

Le même comportement étrange apparaît lorsque vous utilisez le travail coordonne la place des coordonnées de l'échantillonneur mais dans ce cas, l'erreur se produit pour les images de taille 2000x1000 mais fonctionne très bien pour les images de taille 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); 
} 

Pour référence J'ai ajouté à la partie Objective-C de la méthode - (CIImage *)outputImage de mon filtre ce qui suit pour que le DOD soit l'image d'entrée entière.

- (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]; 

} 

De plus j'ai ajouté la méthode suivante pour définir le retour sur investissement que j'appelle dans ma méthode - (id)init avec ceci: [filterKernel setROISelector:@selector(regionOf:destRect:userInfo:)];

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

    return r; 
} 

Toute aide ou des conseils sur cette question seraient grandement appréciés. Je suis sûr que les CIFilters peuvent travailler avec des images plus grandes car j'ai utilisé la CIBumpDistortion avec des images de plus de 50 mégapixels, donc je dois faire quelque chose de mal. Des idées?

Répondre

2

Travailler avec CoreImage J'ai découvert qu'il coupe de grandes images en parties. Par exemple, dans votre cas, l'image 4k x 2k peut être divisée en 4 images 2k x 1k et rendue séparément. Malheureusement, ces astuces d'optimisation affectent samplerCoord et certains filtres dépendant des coordonnées ne fonctionnent pas correctement sur les grandes images.

Ma solution a été à l'aide destCoord au lieu de samplerCoord. Bien sûr, vous devez garder à l'esprit qu'une image peut être rendue dans une origine non nulle et destCoord. J'ai écrit mon propre filtre, donc j'ai été capable de passer toute l'étendue comme un paramètre vec4.

Exemple: essayez de générer une image avec CIFilter, quelque chose comme ça:

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

Cette sortie devrait nous donner de la couleur noire à (0,0) et blanc à (1,1), non? Cependant, pour les grandes images, vous verrez quelques quads, pas un seul dégradé.Cela est dû à optimiser le rendu provenant du moteur CoreImage, je ne l'ai pas trouvé un moyen de le transmettre, mais vous pouvez réécrire le noyau de cette façon:

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

rect est réelle étendue de l'échantillonneur que vous devez passer. J'ai utilisé [inputImage extent] à cette fin, mais cela dépend du filtre et peut être quelque chose d'autre dans votre cas.

Espérons que cette explication soit claire. Achetez le chemin, on dirait que les noyaux système fonctionnent très bien même avec de grandes images, donc vous devriez vous inquiéter de ces astuces dans vos noyaux personnalisés seulement.

+0

Existe-t-il un moyen de connaître l'origine de l'image en mosaïque a priori? Si vous passez dans l'extension 4-d (origine x, origine y, largeur, hauteur), pouvez-vous déterminer par programme comment CoreImage va découper l'image en parties pour savoir où l'origine sera pour chaque segment? Ou est-ce que je manque quelque chose? Ce que j'ai fait avec des résultats décents est d'utiliser destCoord puis samplerTransform en passant explicitement toute l'étendue de l'image d'entrée en tant que ROI. Cela fonctionne bien tant que l'image d'entrée est suffisamment petite. –

+0

J'ai modifié mon message avec un exemple – Gobra