Domanda

Devo visualizzare le anteprime delle immagini in una determinata directory. Uso TFileStream per leggere il file di immagine prima di caricare l'immagine in un componente di immagine. La bitmap viene quindi ridimensionata in base alle dimensioni della miniatura e assegnata a un componente TImage su un TScrollBox.

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

Esiste un modo più veloce per caricare file (immagine) dal disco e ridimensionarli?

Grazie, Pieter

È stato utile?

Soluzione

Non proprio. Quello che puoi fare è ridimensionarli in un thread in background e utilizzare un "segnaposto" immagine fino al completamento del 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).

Hai diverse opzioni sull'architettura del thread stesso. Un singolo thread che esegue 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ò rendere le cose abbastanza semplici.

Altri suggerimenti

Completerò la risposta di skamradt con un tentativo di progettare per essere il più veloce possibile. Per questo dovresti

  • ottimizza I / O
  • utilizza più thread per utilizzare più core della CPU e per far funzionare anche un singolo core della CPU mentre leggi (o scrivi) file

L'uso di più thread implica che l'uso delle classi VCL per il ridimensionamento non funzionerà, poiché VCL non è sicuro per i thread e tutti gli hack che non si adattano bene. Lab Computer di efg ha collegamenti per il codice di elaborazione delle immagini.

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

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

  • Chiedi a un thread di leggere i file negli oggetti TGraphic e di inserirli in un elenco thread-safe.
  • Chiedi a un pool di thread di attendere nell'elenco di file nella dimensione originale e a un thread di elaborare un oggetto TGraphic, ridimensionarlo in un altro oggetto TGraphic e aggiungerlo a un altro elenco thread-safe.
  • Notifica 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, farlo anche nel thread di lettura (vedere sopra per una spiegazione).

Modifica

Rileggendo la tua domanda, noto che forse hai solo bisogno di ridimensionare un'immagine, nel qual caso un singolo thread di sfondo è ovviamente sufficiente. Lascerò comunque la mia risposta, forse sarà utile a qualcun altro qualche volta. È quello che ho imparato da uno dei miei ultimi progetti, in cui il programma finale avrebbe potuto richiedere un po 'più di velocità ma utilizzava solo il 75% della macchina quad core nelle ore di punta. Il disaccoppiamento dell'I / O dall'elaborazione avrebbe fatto la differenza.

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

Un'altra opzione è utilizzare il il metodo della shell per estrarre una miniatura , che è piuttosto veloce come ben

Sono nel settore della visione e carico semplicemente le immagini sulla GPU usando OpenGL. (in genere 20x 2048x2000x8 bpp al secondo), un bmp per trama e lascia scalare la videocard (win32, le intestazioni opengl di Mike Lischke)

Il caricamento di tale immagine costa 5-10ms a seconda della videocard esatta (se non integrata e nvidia serie 7300 o più recente. Potrebbero essere eseguibili anche GPU integrate molto recenti). Ridimensionamento e visualizzazione dei costi 300us. Ciò significa che i clienti possono eseguire la panoramica e lo zoom come un matto senza toccare l'app. Traccio un overlay (che era un tmetafile ma ora è un suo formato) sopra di esso.

La mia immagine più grande è 4096x7000x8 bpp che mostra e scala in meno di 30ms. (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é consegno i sistemi con il software.

(alcune dimensioni tipiche: Serie nv6x00: 2k * 2k ma il caricamento è quasi in pareggio rispetto a GDI Serie nv7x00: 4k * 4k Per me le carte base. I GF7300 sono come $ 20-40 Serie nv8x00: 8k * 8k )

Nota che potrebbe non essere adatto a tutti. Ma se sei nella situazione fortunata di 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 trovare esempi non relativi al gioco.

Prova a guardare la libreria Graphics32 : è molto brava a disegnare cose e funziona fantastico con Bitmap. Sono Thread - Sicuro con un buon esempio ed è totalmente gratuito.

Sfrutta la capacità di Windows per creare miniature. Ricorda che i file nascosti Thumbs.db in cartelle che contengono immagini?

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

Non sono in grado di convertirlo in Delphi però.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top