2012-11-25 17 views
11

Ich erstelle eine Farbauswahl für iOS. Ich möchte dem Benutzer ermöglichen, die Helligkeit (Luminanz) auszuwählen und das Farbrad diese Änderung reflektieren zu lassen. Ich verwende Core Image, um die Helligkeit mit dem CIColorControls-Filter zu ändern. Hier ist mein Code:Core Image CIColorControls Helligkeitsfilter erzeugt einen falschen Effekt. Wie ändere ich die Luminanz meines Bildes?

-(CIImage *)oldPhoto:(CIImage *)img withBrightness:(float)intensity 
{ 
    CIFilter *lighten = [CIFilter filterWithName:@"CIColorControls"]; 
    [lighten setValue:img forKey:kCIInputImageKey]; 
    [lighten setValue:@((intensity * 2.0) - 1.0) forKey:@"inputBrightness"]; 
    return lighten.outputImage; 
} 

Hier ist, wie das Farbrad mit Intensität sieht = 0,5 (inputBrightness = 0):

My image with inputBrightness = 0

Das Problem ist, dass das Farbrad falsch aussieht, wenn Intensität < 0,5. Zum Beispiel, hier ist, wie es mit der Intensität = 0,3 (inputBrightness = -0,4) aussieht:

My image with inputBrightness = -0.4

Hinweis, dass es ein schwarzer Kreis in der Mitte, und der Rest des Bildes nicht richtig entweder verdunkelt . Das soll ein HSL-Farbrad sein, also glaube ich, dass ich eigentlich die Leuchtdichte ändern möchte, nicht die Helligkeit.

Erstens, kann jemand erklären, warum das Bild so aussieht? Ich bin kein Experte für Farbe; Es erscheint merkwürdig, dass das Zentrum des Kreises schnell zu schwarz wird, während die Kanten davon nicht viel dunkler werden.

Zweitens, wie kann ich den gewünschten Effekt erzielen?

Hier ist, wie ich will eigentlich das Bild aussehen:

Image with luminance = 0.3, generated with HSL function on CPU (too slow)

Dies wurde mit einer benutzerdefinierten HSL-Funktion und Luminanz geschaffen = 0,3. Dies läuft auf der CPU, also ist es viel zu langsam für meine Bedürfnisse. Ich wäre glücklich, den Code für diese HSL-Funktion zu veröffentlichen, aber ich habe es nicht aufgenommen, weil es nicht sofort relevant erschien. Wenn Sie es sehen wollen, fragen Sie einfach.

Bitte lassen Sie mich wissen, wenn Sie Fragen haben oder wenn etwas unklar scheint. Vielen Dank!

+0

Ein einfacher und wahrscheinlich schneller Weg, um Ihr Problem zu lösen, ist ein schwarzen Kreis über die farbigen Kreis zu zeichnen. Das Alpha, das Sie für diesen schwarzen Kreis wählen, bestimmt die Leuchtdichte Ihres farbigen Kreises. Keine Notwendigkeit, alle Farben neu zu berechnen. – mmgp

+0

Versuchen Sie, Ihren Arbeitsfarbraum auf rgb linear zu ändern, wenn Sie Ihren CIContext einrichten – ccgus

Antwort

2

Versuchen Sie dies und Änderungswert mit Hilfe eines Schiebers: -

- (void)viewDidLoad{ 

    UIImage *aUIImage = showPickedImageView.image; 
    CGImageRef aCGImage = aUIImage.CGImage; 
    aCIImage = [CIImage imageWithCGImage:aCGImage]; 


    context = [[CIContext contextWithOptions:nil] retain]; 
    brightnessFilter = [[CIFilter filterWithName:@"CIColorControls" keysAndValues: @"inputImage", aCIImage, nil] retain]; 

} 

- (IBAction)brightnessSliderValueChanged:(id)sender { 

    [brightnessFilter setValue:[NSNumber numberWithFloat:brightnessSlider.value ] forKey: @"inputBrightness"]; 
    outputImage = [brightnessFilter outputImage]; 
    CGImageRef cgiig = [context createCGImage:outputImage fromRect:[outputImage extent]]; 
    newUIImage = [UIImage imageWithCGImage:cgiig]; 
    CGImageRelease(cgiig); 
    [showPickedImageView setImage:newUIImage]; 
} 
+0

Dies beantwortet die Frage nicht. Dies verwendet denselben Filter "CIColorControls", den er beim Generieren der zweiten in der Frage enthaltenen Stichprobe verwendet hat. Diese Antwort reproduziert nur das Problem und löst es nicht. – Rob

+1

in meinem Fall half ich mir gute Arbeit –

4

Ich fand auch die Nichtlinearität des kCIInputBrightnessKey von CIColorControls ärgerlich zu sein. Ich verwendet, um eine lineare CIToneCurve:

/** Change luminosity of `CIImage` 

@param inputImage The `CIImage` of the image to have it's luminosity changed. 
@param luminosity The percent change of the luminosity, ranging from -1.0 to 1.0. 

@return `CIImage` of image with luminosity changed. If luminosity of 0.0 used, original `inputImage` is returned. 
*/ 

- (CIImage *)changeLuminosityOfCIImage:(CIImage *)inputImage luminosity:(CGFloat)luminosity 
{ 
    if (luminosity == 0) 
     return inputImage; 

    NSParameterAssert(luminosity >= -1.0 && luminosity <= 1.0); 

    CIFilter *toneCurveFilter = [CIFilter filterWithName:@"CIToneCurve"]; 
    [toneCurveFilter setDefaults]; 
    [toneCurveFilter setValue:inputImage forKey:kCIInputImageKey]; 

    if (luminosity > 0) 
    { 
     [toneCurveFilter setValue:[CIVector vectorWithX:0.0 Y:luminosity]       forKey:@"inputPoint0"]; 
     [toneCurveFilter setValue:[CIVector vectorWithX:0.25 Y:luminosity + 0.25 * (1 - luminosity)] forKey:@"inputPoint1"]; 
     [toneCurveFilter setValue:[CIVector vectorWithX:0.50 Y:luminosity + 0.50 * (1 - luminosity)] forKey:@"inputPoint2"]; 
     [toneCurveFilter setValue:[CIVector vectorWithX:0.75 Y:luminosity + 0.75 * (1 - luminosity)] forKey:@"inputPoint3"]; 
     [toneCurveFilter setValue:[CIVector vectorWithX:1.0 Y:1.0]         forKey:@"inputPoint4"]; 
    } 
    else 
    { 
     [toneCurveFilter setValue:[CIVector vectorWithX:0.0 Y:0.0]      forKey:@"inputPoint0"]; 
     [toneCurveFilter setValue:[CIVector vectorWithX:0.25 Y:0.25 * (1 + luminosity)] forKey:@"inputPoint1"]; 
     [toneCurveFilter setValue:[CIVector vectorWithX:0.50 Y:0.50 * (1 + luminosity)] forKey:@"inputPoint2"]; 
     [toneCurveFilter setValue:[CIVector vectorWithX:0.75 Y:0.75 * (1 + luminosity)] forKey:@"inputPoint3"]; 
     [toneCurveFilter setValue:[CIVector vectorWithX:1.0 Y:1 + luminosity]   forKey:@"inputPoint4"]; 
    } 

    return [toneCurveFilter outputImage]; 
} 

Hier Ihr Bild, um 30% der Leuchtkraft der Verringerung der obigen Routine:

reduced

Es kann mit CIToneCurve erfolgen. Ob es schneller als deine Routine ist, du wirst es benchmarken.

1

Ihr CIColorControls-Filter funktioniert wie vorgesehen. Es addiert einfach seinen Helligkeitsparameter zu den roten, grünen und blauen Werten jedes Pixels. Wenn eine negative Helligkeit das Pixel unter 0 nimmt, wird es schwarz dargestellt. Wenn eine positive Helligkeit über 1 hinausgeht, wird es zu weiß abgeschnitten. (Eigentlich wird jeder Kanal separat getrennt ...)

Ein anderes Problem ist, dass CIColorControls im RGB-Farbraum arbeitet. HSL ist sehr unterschiedlich.Aus diesem Grund unterscheidet sich das Basisfarbenrad stark vom Standard-Farbwähler von Apple.

Useful reference