Pregunta

Necesito mostrar miniaturas de imágenes en un directorio dado. Uso TFileStream para leer el archivo de imagen antes de cargar la imagen en un componente de imagen. El mapa de bits se redimensiona al tamaño de la miniatura y se asigna a un componente TImage en un TScrollBox.

Parece funcionar bien, pero se ralentiza bastante con imágenes más grandes.

¿Existe una forma más rápida de cargar archivos (imagen) desde el disco y cambiar su tamaño?

Gracias, Pieter

¿Fue útil?

Solución

No realmente. Lo que puede hacer es cambiarles el tamaño en un hilo de fondo y usar un "marcador de posición". imagen hasta que se realice el cambio de tamaño. Luego guardaría estas imágenes redimensionadas en algún tipo de archivo de caché para su procesamiento posterior (Windows hace esto y llama a la caché thumbs.db en el directorio actual).

Tiene varias opciones en la arquitectura del subproceso en sí. Un único subproceso que hace todas las imágenes, o un grupo de subprocesos donde un subproceso solo sabe cómo procesar una sola imagen. La AsyncCalls es incluso otra forma y puede mantener las cosas bastante simples.

Otros consejos

Completaré la respuesta de skamradt con un intento de diseñar esto para que sea lo más rápido posible. Para esto deberías

  • optimizar E / S
  • use múltiples hilos para hacer uso de múltiples núcleos de CPU, y para mantener incluso un solo núcleo de CPU funcionando mientras lee (o escribe) archivos

El uso de múltiples subprocesos implica que el uso de clases VCL para cambiar el tamaño no funcionará, ya que el VCL no es seguro para subprocesos, y todos los hacks que no escalan bien. El laboratorio de computación de efg tiene enlaces para el código de procesamiento de imágenes.

Es importante no provocar varias operaciones simultáneas de E / S cuando se usan varios subprocesos. Si elige volver a escribir las imágenes en miniatura en los archivos, una vez que haya comenzado a leer un archivo, debe leerlo por completo, y una vez que haya comenzado a escribir un archivo, también debe escribirlo por completo. Intercalar ambas operaciones matará su E / S, ya que potencialmente puede causar muchas operaciones de búsqueda del cabezal del disco duro.

Para obtener los mejores resultados, la lectura (y escritura) de archivos tampoco debe ocurrir en el hilo principal (GUI) de su aplicación. Eso sugeriría el siguiente diseño:

  • Haga que un hilo lea los archivos en objetos TGraphic y colóquelos en una lista segura para hilos.
  • Haga que un grupo de subprocesos espere en la lista de archivos en tamaño original y haga que un subproceso procese un objeto TGraphic, cambie su tamaño a otro objeto TGraphic y agréguelo a otra lista segura para subprocesos.
  • Notifique el hilo de la GUI para cada imagen en miniatura agregada a la lista, para que pueda mostrarse.
  • Si las miniaturas deben escribirse en el archivo, haga esto también en el hilo de lectura (consulte la explicación anterior).

Edición :

Al volver a leer su pregunta, me doy cuenta de que quizás solo necesite cambiar el tamaño de una imagen, en cuyo caso un solo hilo de fondo es suficiente. Dejaré mi respuesta en su lugar de todos modos, tal vez sea útil para alguien más en algún momento. Es lo que aprendí de uno de mis últimos proyectos, donde el programa final podría haber necesitado un poco más de velocidad, pero solo estaba usando alrededor del 75% de la máquina de cuatro núcleos en las horas punta. Desacoplar la E / S del procesamiento habría hecho la diferencia.

A menudo uso TJPEGImage con Scale: = jsEighth (en Delphi 7). Esto es realmente rápido porque la descompresión JPEG puede omitir una gran cantidad de datos para llenar un mapa de bits de solo un octavo de ancho y alto.

Otra opción es usar el método de shell para extraer una miniatura , que es bastante rápido bien

Estoy en el negocio de la visión, y simplemente subo las imágenes a la GPU usando OpenGL. (típicamente 20x 2048x2000x8bpp por segundo), un bmp por textura, y deja que la tarjeta de video escale (win32, encabezados de opengl de Mike Lischke)

La carga de una imagen de este tipo cuesta de 5 a 10 ms dependiendo de la tarjeta de video exacta (si no está integrada y la serie nvidia 7300 o más nueva. Las GPU integradas muy recientes también podrían ser factibles). Escalar y mostrar cuesta 300us. Lo que significa que los clientes pueden desplazarse y hacer zoom como locos sin tocar la aplicación. Dibujo una superposición (que solía ser un tmetafile pero ahora tiene un formato propio) encima de ella.

Mi imagen más grande es 4096x7000x8bpp, que se muestra y escala en menos de 30 ms. (GF 8600)

Una limitación de esta tecnología es el tamaño máximo de textura. Se puede resolver fragmentando la imagen en múltiples texturas, pero aún no me he molestado porque entrego los sistemas con el software.

(algunos tamaños típicos: Serie nv6x00: 2k * 2k, pero la carga es casi un punto de equilibrio en comparación con GDI Serie nv7x00: 4k * 4k Para mí, las tarjetas de referencia. Los GF7300 son como $ 20-40 Serie nv8x00: 8k * 8k )

Tenga en cuenta que esto podría no ser para todos. Pero si tiene la suerte de especificar límites de hardware, podría funcionar. El principal problema son las computadoras portátiles como Thinkpads, cuyas GPU son más antiguas que la computadora portátil avg, que a su vez a menudo están una generación detrás de las computadoras de escritorio.

Elegí OpenGL sobre DirectX porque es más estático en el tiempo y es más fácil encontrar ejemplos no relacionados con el juego.

Intenta mirar la biblioteca Graphics32 : es muy buena para dibujar cosas y funciona genial con mapas de bits. Son Thread - Safe con un buen ejemplo, y es totalmente gratis.

Explotar la capacidad de Windows para crear miniaturas. ¿Recuerdas los archivos ocultos Thumbs.db en carpetas que contienen imágenes?

He implementado algo como esta característica pero en VB. Mi software es capaz de crear miniaturas de 100 archivos (tamaño mixto) en unos 10 segundos.

Sin embargo, no puedo convertirlo a Delphi.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top