2013-07-29 13 views
5

Ich versuche etwas zu einer Farbmaske mit ausschließlich CImage Filter zu bekommen.Machen Sie alle schwarzen Pixel transparent mit CIImage

Grundsätzlich möchte ich alle schwarzen Pixel transparent machen. Es macht mir nichts aus, welche Farbe alle nicht-schwarzen Pixel haben, solange sie maximal Alpha haben.

Der Code, den ich mit in Core Graphics vertraut bin, um diese wie zu erreichen würden aussehen:

// Convert black sections to transparent using a color mask 
const CGFloat maskingColors[6] = { 0, 0, 0, 0, 0, 0 }; 
CGImageRef result = CGImageCreateWithMaskingColors(image, maskingColors); 

Ich habe es einen Schuss in Core Image gegeben einen Farbmatrix-Filter, aber es setzt nur result-nil da die CIVector-Werte größer als 1.0f sind.

// Create color matrix filter 
CIFilter *matrix = [CIFilter filterWithName:@"CIColorMatrix"]; 

// Set filter properties 
[matrix setValue:image forKey:kCIInputImageKey]; 
[matrix setValue:[CIVector vectorWithX:1.0f Y:0.0f Z:0.0f W:0.0f] forKey:@"inputRVector"]; 
[matrix setValue:[CIVector vectorWithX:0.0f Y:1.0f Z:0.0f W:0.0f] forKey:@"inputGVector"]; 
[matrix setValue:[CIVector vectorWithX:0.0f Y:0.0f Z:1.0f W:0.0f] forKey:@"inputBVector"]; 
[matrix setValue:[CIVector vectorWithX:255.0f Y:255.0f Z:255.0f W:0.0f] forKey:@"inputAVector"]; 

// Get the mapped image 
CIImage *result = [matrix valueForKey:kCIOutputImageKey]; 

Hinweis: Für was es wert ist, ist dies ein OSX App.

+0

Benötigen Sie sie ein einfache Lösung oder die schnellste? Ich habe ein solches Problem einmal konfrontiert und ich empfehle Ihnen, OpenGL für schnelle Bild neu zu zeichnen, da Sie nicht nur transparente Pixel oben zeichnen können. – Mehdzor

+0

Einfache Lösung für jetzt, aber wenn Sie Tipps zu OpenGL haben, wäre das auch gut. Idealerweise sollten wir alles für den Umfang dieser Frage im Rahmen von CIImage behalten (um auch anderen zu helfen). –

+0

Haben Sie sich den 'CIFilter'' CIMaskToAlpha' oder 'CIColorMap' angesehen? –

Antwort

5

EDIT

Lösung eines (einfachen) Individuellen CIFilter verwenden. Diese Methode funktioniert nur auf OSX, wie iOS Benutzerdefinierte Filter unterstützt nicht:

Die CIFilter Unterklasse (mehr oder weniger eine Kopie Apple's How-To):

#import <QuartzCore/QuartzCore.h> 

@interface MaskFilter : CIFilter { 
    CIImage *inputImage; 
} 

@end 

@implementation MaskFilter 

static CIKernel *maskFilterKernel = nil; 

+ (void)initialize { 
    [CIFilter registerFilterName: @"MaskFilter" 
        constructor: (id)self 
       classAttributes: [NSDictionary dictionaryWithObjectsAndKeys: 
            @"Mask Filter", kCIAttributeFilterDisplayName, 
            [NSArray arrayWithObjects: 
            kCICategoryColorAdjustment, 
            kCICategoryStillImage, kCICategoryInterlaced, 
            kCICategoryNonSquarePixels,nil], kCIAttributeFilterCategories, 
            nil] 
    ]; 
} 

+ (CIFilter *)filterWithName:(NSString *)name { 
    CIFilter *filter; 
    filter = [[self alloc] init]; 
    return filter; 
} 

- (id)init { 
    if(maskFilterKernel == nil) { 
     NSBundle *bundle = [NSBundle bundleForClass:[self class]]; 
     NSString *code = [NSString stringWithContentsOfFile:[bundle pathForResource:@"MaskFilter" ofType: @"cikernel"] encoding:NSUTF8StringEncoding error:nil]; 
     NSArray *kernels = [CIKernel kernelsWithString:code]; 
     maskFilterKernel = [kernels objectAtIndex:0]; 
    } 
    return [super init]; 
} 

- (CIImage *)outputImage { 
    CISampler *src = [CISampler samplerWithImage: inputImage]; 
    return [self apply:maskFilterKernel, src, kCIApplyOptionDefinition, [src definition], nil]; 
} 

@end 

Die Custom-Kernel, die die ganze Arbeit (Dateiname: MaskFilter.cikernel)

kernel vec4 maskFilterKernel(sampler src) 
{ 
    vec4 t = sample(src, destCoord()); 
    t.w = (t.x == 0.0 ? (t.y == 0.0 ? (t.z == 0.0 ? 0.0 : 1.0) : 1.0) : 1.0); 
    return t; 
} 

Filter verwenden funktioniert wie nur ein Build-in-Filter:

CIFilter *filter = [MaskFilter filterWithName:@"MaskFilter"]; 
[filter setValue:ciImage forKey:@"inputImage"]; 
CIImage *mask = [filter valueForKey: @"outputImage"]; 

Das Hinzufügen eines Parameters zur Auswahl der Farbe, die als Maskenfarbe verwendet werden soll, sollte kein Problem sein.

ALTE ANTWORT

Mit integrierten Methoden und Klassen, kann ich nur mit dieser eher unelegant Lösung kommen (die nur Core Image Filter verwendet):

// convert all colors so they are brighter or equal to 0.5, except black 
CIFilter *binary = [CIFilter filterWithName:@"CIColorMatrix"]; 
[binary setValue:inputImage forKey:@"inputImage"]; 
[binary setValue:[CIVector vectorWithX:1 Y:1 Z:1 W:0] forKey:@"inputRVector"]; 
[binary setValue:[CIVector vectorWithX:1 Y:1 Z:1 W:0] forKey:@"inputGVector"]; 
[binary setValue:[CIVector vectorWithX:1 Y:1 Z:1 W:0] forKey:@"inputBVector"]; 
[binary setValue:[CIVector vectorWithX:0.49999 Y:0.49999 Z:0.49999 W:0] forKey:@"inputBiasVector"]; 
inputImage = [binary valueForKey:@"outputImage"]; 

// convert to black/white only colors 
binary = [CIFilter filterWithName:@"CIColorPosterize"]; 
[binary setDefaults]; 
[binary setValue:inputImage forKey:@"inputImage"]; 
[binary setValue:@2 forKey:@"inputLevels"]; 
inputImage = [binary valueForKey:@"outputImage"]; 

// get mask 
CIFilter *mask = [CIFilter filterWithName:@"CIMaskToAlpha"]; 
[mask setDefaults]; 
[mask setValue: inputImage forKey:@"inputImage"]; 
+0

Danke Kumpel! Benutzerdefinierte Filter eröffnen mir eine Vielzahl von Möglichkeiten :) Gibt es Hinweise, wie man einen benutzerdefinierten Filter erstellt, der ein einzelnes Pixelergebnis wie CIAreaMaximumAlpha ausgibt? –

+0

Sie können die Ausgabegröße so definieren, dass sie einer anderen Eingabegröße entspricht.Da Core Image jedoch keine dynamischen Schleifen unterstützt (nur Schleifen mit Kompilierungsbedingungen), müssen Sie über eine intelligente Reduzierung ohne Informationsverlust zwischen den Schritten nachdenken. Werfen Sie einen Blick auf [diesen Artikel Abschnitt 26.2.2] (http://http.developer.nvidia.com/GPUGems3/gpugems3_ch26.html) –

Verwandte Themen