2011-10-01 9 views
6

Estoy haciendo un generador de avatar donde los componentes de avatar son de archivos PNG con transparencia. Los archivos son cosas como body_1.png o legs_5.png. La transparencia está alrededor de las partes pero no dentro de ellas y las imágenes son todas en escala de grises. Las partes se superponen y puedo obtener un avatar en escala de grises.¿Cuál es la forma adecuada de colorear una imagen en escala de grises con transparencia en Java?

Me gustaría poder colorear estas partes dinámicamente, pero hasta ahora no estoy teniendo buena suerte. Intenté convertir los datos de píxel de RGB a HSL y usar el valor L del píxel original, al tiempo que proporcioné el valor H del nuevo color, pero los resultados no son muy buenos.

Miré Colorize grayscale image pero parece que no puedo hacer que lo que está diciendo funcione en Java. Terminé con una imagen que tiene colores de neón bastante brillantes en todas partes.

Lo que me gustaría es que la transparencia permanezca, mientras coloreo la parte de la escala de grises. Los contornos negros aún deben ser negros y las áreas blancas resaltadas aún deben ser blancas (creo).

¿Alguien tiene una buena manera de hacer esto?

EDIT:

Aquí está una imagen que podría estar tratando de colores: Sample Body

Una vez más, quiero mantener los niveles de brillo de la imagen en escala de grises (por lo que los contornos permanecen oscuras, los gradientes son visibles, y los parches blancos son blancos).

He podido hacer que un LookupOp funcione de alguna manera basado en Colorizing images in Java pero los colores siempre se ven opacos y oscuros.

He aquí un ejemplo de mi salida: Sample Output

El color que se estaba utilizando es este (tenga en cuenta la diferencia de brillo): http://www.color-hex.com/color/b124e7

Ésta es mi lookupOp

protected LookupOp createColorizeOp(short R1, short G1, short B1) { 
    short[] alpha = new short[256]; 
short[] red = new short[256]; 
short[] green = new short[256]; 
short[] blue = new short[256]; 

//int Y = 0.3*R + 0.59*G + 0.11*B 

    for (short i = 0; i < 30; i++) { 
    alpha[i] = i; 
     red[i] = i; 
     green[i] = i; 
     blue[i] = i; 
} 

for (short i = 30; i < 256; i++) {  
    alpha[i] = i; 
    red[i] = (short)Math.round((R1 + i*.3)/2); 
     green[i] = (short)Math.round((G1 + i*.59)/2); 
     blue[i] = (short)Math.round((B1 + i*.11)/2); 

    } 


    short[][] data = new short[][] { 
      red, green, blue, alpha 
    }; 

    LookupTable lookupTable = new ShortLookupTable(0, data); 
    return new LookupOp(lookupTable, null); 
} 

EDIT 2 : Cambié mi LookupOp para usar lo siguiente y obtuve colores mucho más atractivos:

red[i] = (short)((R1)*(float)i/255.0); 
green[i] = (short)((G1)*(float)i/255.0); 
blue[i] = (short)((B1)*(float)i/255.0); 
+0

Para una mejor ayuda antes, publique un [SSCCE] (http://pscode.org/sscce.html). Usar imágenes en un SSCCE es complicado. Puede hacer un enlace directo a una imagen en Internet o generar uno en el código. –

Respuesta

2

Parece lo que funciona para usted es algo como esto:

for each pixel 
    if pixel is white, black or transparent then leave it alone 
    else 
     apply desired H and S and make grayscale value the L 
     convert new HSL back to RGB 

Editar: después de ver sus imágenes que tengo un par de comentarios:

Parece que desea regalo especial tonos más oscuros , ya que no estás coloreando nada por debajo de 30. Siguiendo la misma lógica, ¿no deberías también eximir de colorear los valores más altos? Eso evitará que los blancos y los casi blancos se vuelvan teñidos de color.

No debe establecer los valores alfa junto con RGB. El valor alfa de la imagen original siempre debe conservarse. Su algoritmo de tabla de búsqueda solo debería afectar RGB.

Mientras dices que probaste HSL, eso no está en el código que publicaste. Debería hacer su coloreado en HSL, luego convertir los colores resultantes a RGB para su tabla de búsqueda, ya que eso preservará el brillo original de la escala de grises.Su creación de la tabla de búsqueda podría ser algo como esto:

short H = ??; // your favorite hue 
short S = ??; // your favorite saturation 
for (short i = 0; i < 256; i++) { 
    if (i < 30 || i > 226) { 
     red[i] = green[i] = blue[i] = i; // don't do alpha here 
    } 
    else { 
     HSL_to_RGB(H, S, i, red[i], green[i], blue[i]) 
    } 
} 

Nota: usted tiene que proporcionar la LAV a la función de conversión de RGB. Vea mi respuesta en Colorize grayscale image para obtener enlaces al código fuente.

Cuestiones relacionadas