PDA

Visualizza la versione completa : [Java a livello avanzato] Immagini di grandi dimensioni


pireda
04-08-2003, 12:48
Ho incontrato un grosso problema che mi sta tormentando da 5 giorni. Sto realizzando una applicazione per il trasferimento via FTP di immagini realizzate con fotocamere digitali. Vista la natura di queste immagini, posso avere a che fare con JPEG da 3500 x 5300 pixels e del peso di 3,9 MB (:eek:).
Il cliente vorrebbe che durante la selezione dei files (la faccio tramite JFileChooser) fosse possibile vedere un'anteprima delle immagini (un pò come avviene in esplora risorse di Windows, quando clicchi su un file immagine dopo un pò ti appare la preview).
Creare un anteprima nel JFileChooser tramite il metodo "setAccessory" è semplice, il problema è che finché le immagini arrivano a 1600 x 1200 pixels la miniatura viene generata abbastanza velocemente, ma quando il file comincia ad essere più grosso si rischiano attese fino a 2 minuti con un Pentium III 800. Io vorrei riuscire ad emulare un comportamento simile ad esplora risorse di Windows, ovvero se ci si sofferma sull'immagine per abbastanza tempo l'anteprima appare, se la selezione cambia Windows abbandona la generazione della vecchia anteprima ed inizia a caricare la nuova. In Java questo non lo riesco a fare nemmeno usando i thread, posto il codice della classe che genera l'anteprima:



import javax.swing.*;
import java.beans.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

public class Preview extends JComponent implements PropertyChangeListener, Runnable
{
ImageIcon thumbnail = null;
File file = null;
Thread td;

public void run()
{
thumbnail = null;

while (!td.interrupted)
{
if (isShowing())
{
loadImage();
repaint();
td = null;
}
}
}

public Preview(JFileChooser fc)
{
setPreferredSize(new Dimension(100, 200));
setBorder(BorderFactory.createEtchedBorder());
fc.addPropertyChangeListener(this);
}

public void loadImage() {
if (file == null) {
thumbnail = null;
return;
}

ImageIcon tmpIcon = new ImageIcon(file.getPath());
if (tmpIcon != null) {
if (tmpIcon.getIconWidth() > 90) {
thumbnail = new ImageIcon(tmpIcon.getImage().getScaledInstance(90, -1, Image.SCALE_DEFAULT));
} else { //Non c'è bisogno della miniatura
thumbnail = tmpIcon;
}
}
}

public void propertyChange(PropertyChangeEvent e)
{
boolean update = false;
String prop = e.getPropertyName();

//Se la directory è cambiata, non mostra l'immagine.
if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(pr op)) {
file = null;
update = true;

//Se un file viene selezionato, individua quale.
} else if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equal s(prop)) {
file = (File) e.getNewValue();
update = true;
if (td != null)
{
td.interrupt();
}
}

//Aggiorna la preview.
if (update && file != null)
{
td = new Thread(this);
td.start();
}
}

public void paintComponent(Graphics g) {
if (thumbnail == null) {
loadImage();
}
if (thumbnail != null) {
int x = getWidth()/2 - thumbnail.getIconWidth()/2;
int y = getHeight()/2 - thumbnail.getIconHeight()/2;

if (y < 0) {
y = 0;
}

if (x < 5) {
x = 5;
}
thumbnail.paintIcon(this, g, x, y);
}
}
}


L'istruzione incriminata è "ImageIcon tmpIcon = new ImageIcon(file.getPath());" nel metodo "loadImage" e l'eventuale interruzione del thread avviene solo una volta terminata questa istruzione (che come dicevo può durare anche 2 minuti) ma non durante (come invece avviene in esplora risorse di Windows)

Qualcuno ha una soluzione a questo complicato problema?

pireda
04-08-2003, 16:52
up :stordita:

pireda
05-08-2003, 10:32
up

Loading