2011-02-10 6 views
5

Desarrollando un iPad PDF-Reader decidimos preparar imágenes de alta resolución de renderizado de páginas intensivas (muchas rutas) y usarlas en lugar de las páginas pdf para evitar problemas de rendimiento. Decidimos que 3*768 by 3*1024 es un buen compromiso entre la legibilidad y el rendimiento de representación que resulta en ~ 1.5 MB jpegs.¿Por qué es UIImageView tan intensivo en memoria en comparación con CGContextDrawImage?

Sin embargo, probamos dos implementaciones para mostrar las páginas de imágenes. Uno que usa una subclase CATiledLayer que también es responsable de manejar las páginas PDF "normales" (dibujo con CGContextDrawImage) y otra que usa UIImageView. Este último tiene la ventaja de que la visualización y el zoom es muy rápido, pero el uso de memoria es realmente malo: toma aproximadamente 30 MB en la memoria (lo cual es consistente con el tamaño del mapa de bits de la imagen). El otro enfoque (CATiledLayer) necesita más tiempo para mostrar primero la página y necesita otros dos segundos para volver a renderizar después del zoom (similar a las páginas en PDF, pero mucho más rápido) pero no ocupa más memoria de la que necesita para mostrar un tamaño mucho más pequeño imagen o una página PDF.

¿Alguien sabe lo que está sucediendo entre bastidores y si es posible combinar el uso de poca memoria de CGContextDrawImage con un alto rendimiento de UIImageView mediante el uso de Quartz Framework.

Respuesta

3

No estoy seguro si esta pregunta sigue siendo relevante, pero si es así, tal vez esto ayude:

He luchado la batalla de visualización eficiente de grandes vistas en mi tiled image view también. Hay un montón de partes subyacentes al problema:

  • normal A UIView, incluyendo UIImageView, parece estar siempre completamente respaldado por la memoria de su imagen. Incluso si implementa el método drawRect:, siempre parece pasar todos los límites de la vista, no solo el área visible dentro de una vista de desplazamiento. Como ha descubierto, esto rápidamente ocupa un lote de memoria ya que cada píxel toma 4 bytes.
  • El CATiledLayerhace solo solicita el contenido para los mosaicos visibles. También descarta las fichas que ya no son visibles, de ahí proviene el ahorro de memoria. Sin embargo, hace la notificación y el dibujo en un hilo de fondo, mientras anima de blanco a los contenidos. Parece hacer esto a través de una API privada, no he encontrado una manera de volver a implementar la funcionalidad de CATiledLayer como mi propia subclase de CALayer, ya que simplemente parece que no hay un mecanismo de notificación que podamos usar como meros mortales.
  • Si tiene varias vistas dentro de la vista de desplazamiento, recibirán los mensajes drawRect: de forma apropiada a medida que se localizan. UIKit parece tener problemas con demasiadas subvistas debajo de una vista.

Para usted, puede ver un par de opciones posibles:

  • podría ser posible para salvar la CATiledLayer aplicación basada. El fadeDuration tiene un valor predeterminado de 0,25 segundos, que puede ser demasiado largo si los tiempos de carga son cortos. Puede soltar esto a algo como 1.0/60.0, es decir, un marco. Una cosa que no está clara en su descripción es si sus imágenes cubren todo el tamaño de página o solo cada mosaico de 256x256 píxeles. La decodificación del JPEG completo una y otra vez para cada tesela será mucho más lenta que la decodificación de archivos de teselas individuales.
  • Si la latencia de hacer todo desde el subproceso CATiledLayer es demasiado alta, puede crear manualmente un grupo de teselas como UIImageView subvistas a un UIView en blanco que es la subvista principal de la vista de desplazamiento. A cada una de estas subvistas se le asigna su propia imagen de mosaico. Si tiene suerte, UIKit será lo suficientemente inteligente como para dejar caer el contenido de estas vistas y volver a cargar los archivos JPEG correspondientes a pedido.
  • Si UIImageViews no es lo suficientemente inteligente, o si tiene demasiadas vistas para que UIKit lo solucione, puede crear sus propias vistas que carguen sus archivos JPEG en drawRect:. Si todavía es demasiado espasmódico, intente con sus propios CALayers, que serán subcapas de la capa en blanco de su vista única y vuelvan a cargar su imagen a pedido. Esto es con lo que finalmente fui con mi vista de imagen en mosaico.

Eso debería cubrir el desplazamiento, pero podría ser realmente lento si permite al usuario acercarlo (minificación). En ese caso, recomiendo que almacene versiones de menor resolución apropiadas y cargue/muestre aquellas en esos niveles de zoom más externos.

+0

Muchas gracias por esta respuesta detallada e ilustrativa. A pesar de que el proyecto que realmente pedí, está hecho, estoy seguro de que su explicación será útil para los próximos números y, si no, es bueno saberlo. –

Cuestiones relacionadas