2012-11-25 14 views
11

Sto creando un selettore di colori per iOS. Vorrei abilitare l'utente a selezionare la luminosità (luminanza) e fare in modo che la ruota dei colori rifletta questa modifica. Sto usando Core Image per modificare la luminosità con il filtro CIColorControls. Ecco il mio codice:Immagine principale Il filtro di luminosità CIColorControls crea un effetto errato. Come posso cambiare la luminanza della mia immagine?

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

Ecco come la ruota dei colori guarda con intensità = 0.5 (inputBrightness = 0):

My image with inputBrightness = 0

Il problema è che la ruota dei colori sembra sbagliato quando l'intensità < 0.5. Ad esempio, ecco come si guarda con intensità = 0.3 (inputBrightness = -0.4):

My image with inputBrightness = -0.4

Si noti che c'è un cerchio nero al centro, e il resto dell'immagine non è stata oscurata in modo corretto sia . Questa dovrebbe essere una ruota dei colori HSL, quindi suppongo che ciò che effettivamente voglio cambiare sia la luminanza, non la luminosità.

In primo luogo, qualcuno può spiegare perché l'immagine assomiglia a questo? Non sono un esperto di colori; sembra strano che il centro del cerchio si graffi rapidamente al nero, mentre i suoi bordi non si scuriscono molto.

In secondo luogo, come posso ottenere l'effetto desiderato?

Ecco come ho effettivamente desidera che l'immagine di guardare:

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

Questo è stato creato con una funzione di HSL costume e luminanza = 0.3. Funziona sulla CPU, quindi è troppo lento per le mie esigenze. Sarei felice di pubblicare il codice per questa funzione HSL, ma non l'ho incluso perché non sembrava immediatamente rilevante. Se vuoi vederlo, basta chiedere.

Per favore fatemi sapere se avete domande, o se qualcosa sembra poco chiaro. Grazie!

+0

Un modo semplice e veloce, probabilmente per risolvere il problema è quello di disegnare un cerchio nero sopra il vostro cerchio colorato. L'alfa che scegli per questo cerchio nero determina la luminanza del tuo cerchio colorato. Non è necessario ricalcolare tutti i colori. – mmgp

+0

Provare a modificare lo spazio colore di lavoro su rgb linear quando si installa CIContext – ccgus

risposta

2

Prova questa e modificare il valore utilizzando un cursore: -

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

Questo non risponde alla domanda. Questo utilizza lo stesso filtro, 'CIColorControls', che ha usato per generare il secondo campione incluso nella domanda. Questa risposta riproduce solo il problema e non lo risolve. – Rob

+1

nel mio caso mi ha aiutato a fare un buon lavoro –

4

Ho trovato anche la non linearità del kCIInputBrightnessKey di CIColorControls ad essere fastidioso. Ho impiegato 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]; 
} 

Ecco la vostra immagine, riducendo la luminosità del 30% utilizzando la routine di cui sopra:

reduced

Può essere fatto con CIToneCurve. Che sia più veloce della tua routine, avrai un benchmark.

1

filtrare i CIColorControls sta funzionando come previsto. Aggiunge semplicemente il suo parametro di luminosità ai valori rosso, verde e blu di ciascun pixel. Se una luminosità negativa prende il pixel sotto 0, si blocca in nero. Se una luminosità positiva la spinge oltre 1, si blocca in bianco. (In realtà, ogni canale clip separatamente ...)

altro problema è che CIColorControls lavora nello spazio colore RGB. HSL è molto diverso.Questo è il motivo per cui la tua ruota dei colori di base appare molto diversa dal selettore di colori Apple standard.

Useful reference