2009-05-07 4 views
5

Devo visualizzare le miniature di immagini in una determinata directory. Uso TFileStream per leggere il file immagine prima di caricare l'immagine in un componente immagine. La bitmap viene quindi ridimensionata alla dimensione dell'anteprima e assegnata a un componente TImage su un TScrollBox.Qual è il modo più veloce per caricare e ridimensionare un'immagine?

Sembra funzionare bene, ma rallenta parecchio con immagini più grandi.

C'è un modo più veloce di caricare (immagine) file da disco e ridimensionarli?

Grazie, Pieter

risposta

5

Non proprio. Quello che puoi fare è ridimensionarli in un thread in background e usare un'immagine "segnaposto" fino al ridimensionamento. Vorrei quindi salvare queste immagini ridimensionate in una sorta di file di cache per l'elaborazione successiva (Windows fa questo, e chiama la cache thumbs.db nella directory corrente).

avete diverse opzioni sull'architettura filo stesso. Un singolo thread che fa tutte le immagini, o un pool di thread in cui un thread sa solo come elaborare una singola immagine. La libreria AsyncCalls è anche un altro modo e può mantenere le cose abbastanza semplici.

+0

La mia app ora utilizza segnaposto e fili (skamradt, mghie) e funziona perfettamente.Le miniature sono estratte come suggerito da Stijn Sanders. Grazie. Pieter. –

+0

Sfortunatamente, AsyncCalls è morto (fuori produzione). – Ampere

5

Completerò la risposta di skamradt con un tentativo di progettarlo per essere il più veloce possibile. Per questo si dovrebbe

  • ottimizzare O
  • Usare I/più thread di fare uso di più core di CPU, e per mantenere anche un singolo core della CPU a lavorare mentre si legge (o scrivere) file

L'utilizzo di più thread implica che l'utilizzo delle classi VCL per il ridimensionamento non funzionerà, in quanto il VCL non è thread-safe e tutti gli hack che non si adattano bene. efg's Computer Lab dispone di collegamenti per il codice di elaborazione delle immagini.

È importante non causare più operazioni di I/O simultanee quando si utilizzano più thread. Se scegli di ridisporre le immagini in miniatura ai file, una volta che hai iniziato a leggere un file, dovresti leggerlo completamente e, una volta iniziato a scrivere un file, dovresti anche scriverlo completamente. Interlacciare entrambe le operazioni ucciderà il tuo I/O, perché potenzialmente causerai molte operazioni di ricerca della testina del disco rigido.

Per risultati ottimali, la lettura (e la scrittura) dei file non dovrebbe verificarsi anche nel thread principale (GUI) dell'applicazione. Ciò suggerirebbe il seguente progetto:

  • Avere un thread leggere i file in oggetti TGraphic e inserirli in un elenco thread-safe.
  • Avere un pool di thread in attesa nell'elenco dei file nella dimensione originale e fare in modo che un thread elabori un oggetto TGraphic, ridimensionarlo in un altro oggetto TGraphic e aggiungerlo a un altro elenco thread-safe.
  • Notificare il thread della GUI per ogni immagine di anteprima aggiunta all'elenco, in modo che possa essere visualizzata.
  • Se le anteprime devono essere scritte su file, fatelo anche nel thread di lettura (vedere sopra per una spiegazione).

Edit:

On rileggendo la tua domanda mi accorgo che è forse solo bisogno di ridimensionare un'immagine, nel qual caso un singolo thread in background è naturalmente sufficiente. Lascerò la mia risposta sul posto comunque, forse sarà utile a qualcun altro un po 'di tempo. È quello che ho imparato da uno dei miei ultimi progetti, in cui il programma finale avrebbe potuto richiedere un po 'più di velocità, ma nei picchi di punta utilizzavo solo il 75% della macchina quad-core. Disaccoppiare I/O dall'elaborazione avrebbe fatto la differenza.

5

Uso spesso TJPEGImage con Scala: = jsEighth (in Delphi 7). Questo è molto veloce perché la de-compressione JPEG può saltare molti dei dati per riempire una bitmap di solo un ottavo di larghezza e altezza.

Un'altra opzione è quella di utilizzare il shell's method to extract a thumbnail, che è abbastanza veloce così

+0

questo sembra buono. Volevo disperatamente capirlo l'anno scorso ma ora non mi interessa più tanto. Ma posso ancora aggiustare alcune mie app utilizzando l'approccio TJPEGImage.Scale. Grazie –

1

Sono nel business visione, e ho semplicemente caricare le immagini alla GPU utilizzando OpenGL. (in genere 20x 2048x2000x8bpp al secondo), un bmp per trama e lasciare la scala del videocard (win32, intestazioni opengl di Mike Lischke)

Il caricamento di tale immagine costa 5-10 ms a seconda del video esatto (se non integrato e nvidia 7300 serie o più recenti. Anche le GPU integrate molto recenti potrebbero essere fattibili). Ridimensionamento e visualizzazione dei costi 300us. Il che significa che i clienti possono eseguire panoramiche e zoom come matti senza toccare l'app. Disegno un overlay (che era un tmetafile ma ora è un proprio formato) su di esso.

La mia immagine più grande è 4096x7000x8bpp che mostra e scala in meno di 30 ms. (GF 8600)

Una limitazione di questa tecnologia è la dimensione massima della trama. Può essere risolto frammentando l'immagine in più trame, ma non mi sono ancora preoccupato perché distribuisco i sistemi con il software.

(alcune dimensioni tipiche: nv6x00 serie: 2k * 2k ma caricato è solo di andare in pari rispetto al GDI nv7x00 serie:. 4k * 4k Per me le carte di base GF7300 di sono come $ 20-40 nv8x00 serie: 8k * 8k )

Si noti che questo potrebbe non essere per tutti. Ma se ti trovi nella situazione fortunata per specificare i limiti hardware, potrebbe funzionare. Il problema principale sono i laptop come i Thinkpad, le cui GPU sono più vecchie del laptop avg, che a loro volta sono spesso una generazione dietro i desktop.

Ho scelto OpenGL su DirectX perché è più statico nel tempo e più facile da trovare esempi relativi ai giochi.

+0

molto informativo ma fuori tema. –

+0

ho trovato questo è quello che stavo cercando. grazie! –

0

Sfruttare la capacità di Windows per creare miniature. Ricordare che i file Thumbs.db nascosti nelle cartelle che contengono immagini?

Ho implementato qualcosa come questa funzione, ma in VB. Il mio software è in grado di creare miniature di 100 file (dimensioni miste) in circa 10 secondi.

Tuttavia, non sono in grado di convertirlo in Delphi.

0

Prova a guardare il Graphics32 library: è molto bravo a disegnare cose e funziona ottimo con Bitmap. Sono Thread - Safe con un buon esempio ed è totalmente gratuito.