iOS: esbozar las partes opacas de una image parcialmente transparente

Tengo una aplicación que requiere dibujar un contorno negro sólido alnetworkingedor de un UIImage parcialmente transparente. No alnetworkingedor del marco de la image, sino alnetworkingedor de todas las partes opacas de la image misma. Es decir, piense en un PNG transparente con una "X" blanca opaca; necesito perfilar la "X" en negro.

Para hacer las cosas más difíciles, DESPUÉS de dibujar el contorno, la opacidad de la image original se ajustará, pero el contorno debe permanecer opaco, por lo que el contorno que genero debe include solo el contorno y no la image original.

Mi técnica actual es esta:

  • Cree una nueva UIView que tenga las dimensiones de la image original.
  • Duplique el UIImage 4 veces y agregue los duplicates como subviews de UIView , con cada UIImage desplazado en diagonal desde la location original por un par de píxeles.
  • Convierta esa UIView en una image (mediante el método típico UIGraphicsGetImageFromCurrentImageContext ).
  • Utilizando CGImageMaskCreate y CGImageCreateWithMask , reste la image original de esta nueva image, por lo que solo queda el contorno.

Funciona. Incluso con solo las 4 imágenes offset, el resultado se ve bastante bien. Sin embargo, es terriblemente ineficiente y causa una buena demora de 4 segundos en un iPhone 4.

Entonces, lo que necesito es una forma agradable, rápida y eficiente de lograr lo mismo, que es totalmente compatible con iOS 4.0.

¿Alguna gran idea? 🙂

Me gustaría señalar que, aunque algunas personas han sugerido la detección de bordes, esta no es una solución adecuada. La detección de bordes es para encontrar bordes dentro de los datos de la image donde no hay una representación obvia exacta de los bordes en los datos.

Para usted, los bordes están más bien definidos, está buscando el contorno bien definido. Un borde en su caso es cualquier píxel que está en un píxel totalmente transparente y al lado de un píxel que no es completamente transparente, ¡tan simple como eso! iterar a través de cada píxel en la image y establecerlos en negro si cumplen con estas condiciones.

Alternativamente, para get un resultado antialias, obtenga una representación booleana de la image y pase un pequeño núcleo antialias con círculos. Sé que dijo que los filters personalizados no son compatibles, pero si tiene acceso directo a los datos de image, esto no sería demasiado difícil de implementar a mano …

Saludos, espero que esto ayude.

Por el bien de aportar nuevas ideas:

Una variante de su implementación actual CALayer el soporte de CALayer para las sombras, que calcula a partir del contenido real de los píxeles de la capa en lugar de simplemente su rectángulo delimitador, y para el que usa la GPU. Puede intentar shadowOpacity a un valor masivo para tratar de eliminar el plumaje; en su defecto, podría renderizar a un CGContext adecuado, sacar solo la capa alfa y procesarla manualmente para aplicar una testing de umbral en los valores alfa, empujándolos a ser totalmente opacos o totalmente transparentes.

Puede lograr ese paso de procesamiento final en la GPU incluso bajo ES 1 a través de una variedad de forms. Usaría la testing alfa para aplicar el umbral real, entonces podría, por ejemplo, cebar el búfer de profundidad a 1.0, desactivar la salida de color y la testing de profundidad, dibujar la versión con la sombra a una profundidad de 0.5, dibujar la versión sin la sombra a una profundidad de 1.0 luego habilita la salida de color y las testings de profundidad y dibuja un sólido quad negro de pantalla completa a una profundidad de 0.75. Por lo tanto, es como usar el búfer de profundidad para emular la plantilla (ya que la GPU Apple utilizada antes del dispositivo con capacidad ES 2 no admitía un búfer de plantilla).

Eso, por supuesto, asume que CALayer sombras CALayer aparecen fuera del compositor, que no he comprobado.

Como alternativa, si está dispuesto a limitar su soporte a los dispositivos ES 2 (todo 3GS +), entonces puede upload su image como una textura y hacer todo el process en la GPU. Pero eso técnicamente dejaría que algunos dispositivos compatibles con iOS 4 no estén soportados, así que supongo que no es una opción.

Solo necesita implementar un algorithm de detección de bordes , pero en lugar de usar brillo o color para determinar dónde están los bordes, use opacidad. Hay varias forms diferentes de hacerlo. Por ejemplo, puede ver cada píxel y sus vecinos para identificar áreas donde la opacidad cruza cualquier umbral que haya establecido. Siempre que necesite mirar cada píxel de una image en MacOS X o iOS, piense en Core Image . Hay una serie útil de publicaciones de blog que comienzan con esta que busca implementar un filter Core Image personalizado; comenzaré allí para crear un filter de detección de bordes.

en lugar de utilizar UIView, sugiero simplemente presionar un context como el siguiente:

 UIGraphicsBeginImageContextWithOptions(image.size,NO,0.0); //draw your image 4 times and mask it whatever you like, you can just copy & paste //current drawing code here. .... outlinedimage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); 

Esto será mucho más rápido que tu UIView.