2011-06-08 15 views
12

Estoy tratando de pintar un mapa de color RGB completo que eventualmente permitirá a un usuario seleccionar un color tocando ese mapa visual en cualquier punto. Mi código actual es el siguiente:¿Cómo pintar un buen mapa de colores RGB?

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef c = UIGraphicsGetCurrentContext(); 

    for (float x=0; x<320; x++) { 
     for (float y=0; y<416; y++) { 

      float r = x/320; 
      float g = y/416; 
      float b = (y < 208) ? y/208 : (416 - y)/208; 

      CGContextSetRGBFillColor(c, r, g, b, 1.0); 
      CGContextFillRect(c, CGRectMake(x, y, 1, 1)); 

     } 
    } 
} 

El resultado no es tan malo, pero no estoy satisfecho todavía. El espectro pierde colores brillantes, incluido el blanco. La razón es clara: rojo, verde y azul nunca llegarán a 1.0 al mismo tiempo.

Screenshot of the resulting color map

¿Tiene alguna aconsejan cómo mejorar ese mapa lo que representa el espectro completo del espacio de color RGB?

Gracias por su contribución!

ACTUALIZACIÓN:

Como sugiere Josh Caswell He utilizado el espacio de color HSB y el siguiente código:

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef c = UIGraphicsGetCurrentContext(); 

    int size = 20; 

    for (float x=0; x<320; x+=size) { 

     float s = x < 160 ? 1  : (320 - x)/160; 
     float b = x < 160 ? x/160 : 1; 

     for (float y=0; y<416; y+=size) { 

      float h = y/416; 

      [[UIColor colorWithHue:h saturation:s brightness:b alpha:1.0] setFill]; 
      CGContextFillRect(c, CGRectMake(x, y, size, size)); 
     } 
    } 
} 

Esto se traduce en la siguiente salida, que es perfecto para mi necesariamente.

Result using HSB color space

Gracias por toda la entrada!

+1

Gracias por compartir el código; ¡que salió muy bien! –

+2

El resultado final es realmente hermoso. Espero que nadie requiera un gris; es posible que desee hacer una serie de grises en el lado derecho. –

+0

Eso es una buena adición. Gracias. –

Respuesta

7

Bueno, estás tratando de aplanar un objeto tridimensional en un avión. Un color RGB básicamente representa un punto dentro de un cubo. Mapear el sólido RGB en una superficie puede ser matemáticamente posible, pero probablemente no será particularmente intuitivo para este propósito de selección de color.

Puede tener mejor suerte con HSB, que es más como un cilindro con tono como ángulo alrededor de la circunferencia.Podría "desenrollar" el cilindro, asignar el matiz a la coordenada y, luego variar el brillo o la saturación a lo largo del eje x; puede hacer algunas pruebas simples para decidir qué componente es más importante para su aplicación. Un deslizamiento con dos dedos podría usarse para el tercer componente si creyera que era necesario incluirlo.

HSB con saturación en el eje x:
HSB map; S on X axis

Con brillo en el eje x:
HSB map; B on X axis

Con saturación y el brillo igual y tanto en el eje X:
HSB map; S=B on X axis

Si necesita blanco, lo que ocurre cuando S = 0%, B = 100%, puede pegar una tira a lo largo de un lado o intentar S = 1/B.

+0

El gesto de deslizar para cambiar el 3er componente es una buena idea ... pero quiero que sea lo más simple posible. Así que me atengo a una representación plana que no necesitará ninguna interacción del usuario. HSB podría ser más fácil de aplanar sin embargo ... gracias. –

+0

HSB es mucho más fácil de manejar. Levanté el brillo de izquierda a centro y luego reduje la saturación de centro a derecha. Esto resulta en lo siguiente (con cuadrados de 20px): http://cl.ly/1f0q0m043u3v1O2s1618 - Agregaré mi código final. –

+0

¡Oye, eso se ve _excelente_! Me alegro de poder ayudar. –

2

Creo que una manera de derivar es tal:

horizontalmente, para cada píxel, recoger una relación de rgb tal como "0, 0, 1"

Dibuje píxeles desde la parte superior a la parte inferior con una "brillo" que va de 0 a 1.

Derivar cada píxel como pixel = brightness * (r,g,b)

a medida que avanza horizontalmente, iterate RGB como:

000, 001, 010, 011, 100, 101, 110, 111

Puede lograr esto usando una ecuación, y manejar su interpolación al mismo tiempo, si utiliza 3 cálculos de seno.

Esto resuelve su problema de blanco y negro, y le ofrece una gran cantidad de espacio de color. Si necesita absolutamente cada píxel del espacio de color, necesita hacer su interpolación horizontal de manera diferente y necesitará 2^8 en lugar de 8 puntos de control.

+0

Esa es una muy buena idea ... usar sin() para interpolar desde 0..1 y tratar de abarcar todo el espectro horizontalmente, gracias por esa entrada. Intentaré adaptarlo. –

+1

Mi resultado actual es el siguiente: http://cl.ly/3v321G2m0V3o1c3n0n3c - Voy a intentar con HSB ... –

+0

No me había dado cuenta de que lo había implementado. ¡No puedo creer lo feo que salió mi idea! Gracias por compartir la captura de pantalla. – Nektarios

2

Está intentando representar un espacio de color tridimensional en una superficie bidimensional. Es poco probable que encuentre una sola superficie que sea adecuada.

Necesitará una selección de dos partes.

Cuestiones relacionadas