package net.trevize.galatee; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; //import net.trevize.tinker.ImageUtils; import com.davidsoergel.conja.Function; import com.davidsoergel.conja.Parallel; import com.sun.media.jai.codec.SeekableStream; import edu.mbl.jif.imaging.nav.FileOpener; import edu.mbl.jif.imaging.nav.util.Histogram; /** * This class is used for the Galatee image viewer. * * In this implementation, severals locks are in use: 1. a lock on the instance of the class (this): * running/sleeping 2. a lock on the variable stopIt: a boolean that notice if the end of the thread * is asked by the GUI or not. 3. a lock on the variable loading: an ArrayList<GalleryItem> which * contains GalleryItem that are in a loading state (i.e. not ever in the queue). 4. a lock on the * variable files: an ArrayList<File> which contains File instances regarding to each GalleryItem. * This is the process queue. * * @author Nicolas James <nicolas.james@gmail.com> [[http://njames.trevize.net]] * ImageLoaderThread.java - Mar 25, 2009 */ public class ImageLoaderThread extends Thread { private Galatee galatee; private int imageWidth; private int imageHeight; private GItemList gi_list; public ImageLoaderThread(Galatee galatee, int imageWidth, int imageHeight) { super("ImgLoader"); this.galatee = galatee; this.imageWidth = imageWidth; this.imageHeight = imageHeight; gi_list = new GItemList(); } /** * For adding the loading of an image. The GalleryItem given in parameter is put in the first * place queue, i.e. at the next iteration of the main loop in the run() method, it will be this * GalleryItem that will be loaded. * * @param file * @param item */ public void pushItem(GItem item) { gi_list.add(item); //notify this because he's maybe in a "waiting" state. synchronized (this) { this.notify(); } } public void run() { while (!stop) { //main loop. //define the function for the Parallel.forEach(...). Function<GItem, Void> loadImageFunction = new Function<GItem, Void>() { public Void apply(GItem gitem) { BufferedImage image = null; String metaDataString = null; if (gitem.getUri().getScheme().equals("tar")) { // special behavior: is the URI schema is tar, we access the file using Apache Common VFS. InputStream gitem_is = gitem.getInputStream(); image = ImageUtils.JAI_loadAndResizeImage(imageWidth, imageHeight, SeekableStream.wrapInputStream( gitem_is, true), true); try { gitem_is.close(); } catch (IOException e) { e.printStackTrace(); } } else { // from local file //====================================================================== // TODO GBH here is where we will read metadata... // if it is a MM dataset... // Open it and get summary metadata... //======================================================================▐ boolean isMMDataset = FileOpener.isMicroManagerType(gitem.getLocalFilepath()); // if (isMMDataset) { // try { // String[] paths = DatasetUtils.parsePath(gitem.getLocalFilepath()); // MMgrDatasetAccessor mmdp = new MMgrDatasetAccessor(paths[0], paths[1], // true, false); // //JSONObject sumMD = mmdp.getImageCache().getSummaryMetadata(); // String comment = mmdp.getImageCache().getComment(); // if (comment != null) { // metaDataString = "\n" + comment; // } // } catch (Exception ex) { // System.err.println("Cannot open dataset: " + gitem.getLocalFilepath()); // } // try { // image = ImageUtils.JAI_loadAndResizeImage(imageWidth, // imageHeight, gitem.getLocalFilepath(), true); // } catch (Exception e) { // // exception may be thrown here, but no problem, // // as it is mlib accelerator for JAI... // // e.printStackTrace(); // } // // } else { try { image = ImageUtils.JAI_loadAndResizeImage(imageWidth, imageHeight, gitem.getLocalFilepath(), true); } catch (Exception e) { // exception may be thrown here, but no problem, // as it is mlib accelerator for JAI... // e.printStackTrace(); } //} } if (image == null) { image = Galatee.imageLoadingError; } // after HERE we assume the image is loaded. // If Enhance checked... if (galatee.isEqualizeHisto()) { if (image.getType() == 10 || image.getType() == 11) { // Equalize the contrast Histogram hist = new Histogram(image); hist.equalizeHistogram(); gitem.setImage(hist.getImage()); } else { gitem.setImage(image); } } else { gitem.setImage(image); } // Add to description ======================================================== if (!gitem.wasMetadataAdded()) { // prevent adding it more than once. if (metaDataString != null) { gitem.setText(gitem.getText() + metaDataString); } gitem.setMetadataAdded(true); } // =========================================================================== galatee.getTable().repaint(galatee.getTable().getVisibleRect()); // if needed we keep the selected cell still in the visible rectangle of the JTable. synchronized (galatee) { int selected_row = galatee.getTable().getSelectedRow(); int selected_column = galatee.getTable().getSelectedColumn(); if (galatee.isKeep_selected_cell_visible() && selected_row != -1 && selected_column != -1) { galatee.getTable().scrollRectToVisible( galatee.getTable().getCellRect(selected_row, selected_column, true)); } } gi_list.processingEndedFor(gitem); return null; } }; //launch the Parallel.forEach(...). try { Parallel.forEach(gi_list, loadImageFunction); Parallel.emergencyAbort(); } catch (Exception e) { e.printStackTrace(); } //waiting to be notified that there's stuff again in the queue. synchronized (this) { try { //System.out.println("iltpt is waiting."); this.wait(); } catch (InterruptedException e) { //e.printStackTrace(); //System.out.println("Image loader Thread terminated... at wait"); } } }//end while(true) }//end run() method boolean stop = false; public void terminate() { stop = true; this.interrupt(); } /** * ************************************************************************* * getters and setters. ************************************************************************ */ public int getImageWidth() { return imageWidth; } public int getImageHeight() { return imageHeight; } public void setImageWidth(int imageWidth) { this.imageWidth = imageWidth; } public void setImageHeight(int imageHeight) { this.imageHeight = imageHeight; } }