2010-11-09 4 views
5

Mi aplicación para iPhone cuenta con UITableViewCell s personalizados que cada uno tiene un ícono. En el estado de celda normal, estos iconos son negros con un fondo transparente. En lugar de agrupar un segundo conjunto de íconos invertidos con la aplicación para un estado resaltado (blanco sobre un fondo transparente), me gustaría invertir estos íconos sobre la marcha usando Core Graphics siempre que el usuario toque la celda de la tabla correspondiente.Tratando de colorear dinámicamente los UIImages transparentes pero sigue obteniendo un resultado borroso. ¿Qué estoy haciendo mal?

He encontrado algunas otras respuestas relacionadas con superponer UIImage con un color o volver a colorear UIImage s, pero todas estas técnicas producen un resultado borroso para mí (ver más abajo). He intentado todo tipo de CGBlendMode s, así como computar manualmente una máscara más precisa (tal vez lo hice incorrectamente), pero parece que los píxeles semitransparentes alrededor de los bordes de mis iconos obtienen su opacidad borked o son básicamente caerse, dando una apariencia entrecortada/borrosa. Estoy perdido por lo que estoy haciendo mal.

Tampoco es realmente una opción cambiar todos mis íconos de modo que solo sean puros en blanco y negro sin transparencia - Necesito que los iconos queden sobre un fondo transparente para que puedan superponerse sobre otros elementos de la IU como bien.

El código (cortesía de Chadwick Wood) que estoy usando para invertir el ícono (estoy llamando a este método en cada uno de mis iconos originales y pasando [UIColor whiteColor] como segundo argumento) y el resultado de ejemplo (en un iPhone 4 con iOS 4.1) está debajo (ignore el fondo azul en la imagen resaltada, es el fondo resaltado de una celda de la tabla seleccionada).

Cualquier ayuda es muy apreciada.

Ejemplo de entrada & de salida:

Icon before & after programmatic recoloring.

@implementation UIImage(FFExtensions) 

+ (UIImage *)imageNamed:(NSString *)name withColor:(UIColor *)color { 

// load the image 
UIImage *img = [UIImage imageNamed:name]; 

// begin a new image context, to draw our colored image onto 
UIGraphicsBeginImageContext(img.size); 

// get a reference to that context we created 
CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextSetInterpolationQuality(context, kCGInterpolationHigh); 

// set the fill color 
[color setFill]; 

// translate/flip the graphics context (for transforming from CG* coords to UI* coords 
CGContextTranslateCTM(context, 0, img.size.height); 
CGContextScaleCTM(context, 1.0, -1.0); 

// set the blend mode to color burn, and the original image 
CGContextSetBlendMode(context, kCGBlendModeMultiply); 
CGRect rect = CGRectMake(0, 0, img.size.width, img.size.height); 
//CGContextDrawImage(context, rect, img.CGImage); 

// set a mask that matches the shape of the image, then draw (color burn) a colored rectangle 
CGContextClipToMask(context, rect, img.CGImage); 
CGContextAddRect(context, rect); 
CGContextDrawPath(context,kCGPathFill); 


// generate a new UIImage from the graphics context we drew onto 
UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

//return the color-burned image 
return coloredImg; 
} 

@end 
+0

¿Cuál es el tamaño de la imagen y cómo la dibuja? ¿Hay una etapa adicional de escalado o está dibujando la imagen en un píxel no integral? –

+0

No es borroso, es de baja resolución. Si compara los tamaños de píxeles de las CGImages de las imágenes, verá que son diferentes. No conozco suficiente Cocoa Touch para decirte cómo solucionarlo, pero ese es el problema que debes resolver. –

+0

@Steven El tamaño de la imagen original que se está coloreando depende del dispositivo. Es 52px (Retina Display) o 26px (iPhone 3G/3GS). El ejemplo que publiqué es la imagen como se ve en un iPhone 4. Parece que de alguna manera la escala está sucediendo, pero no estoy seguro de por qué. De forma deliberada, dejo el argumento .png/@ 2x.png fuera del nombre a esta función para que + imagedNamed: (en la primera línea de la función) elija el archivo de origen correcto según el dispositivo. –

Respuesta

5

Gracias a Peter & observación de Steven que la resolución de la imagen de salida parecía ser más bajo que el de entrada, me di cuenta de que yo no estaba de contabilidad de el factor de escala de la pantalla al crear mi contexto de imagen.

Cambio de la línea:

UIGraphicsBeginImageContext(img.size); 

a

UIGraphicsBeginImageContextWithOptions(img.size, NO, [UIScreen mainScreen].scale); 

corrige el problema.

+2

O, incluso más fácil: simplemente pase 0.0 como el último parámetro a 'UIGraphicsBeginImageContextWithOptions()'. De la [documentación] (http://developer.apple.com/library/ios/documentation/uikit/reference/UIKitFunctionReference/Reference/reference.html # // apple_ref/c/func/UIGraphicsBeginImageContextWithOptions): "Si especifica un valor de 0.0, el factor de escala se establece en el factor de escala de la pantalla principal del dispositivo". –

Cuestiones relacionadas