Engine.java
上传用户:shengda799
上传日期:2007-01-10
资源大小:68k
文件大小:23k
源码类别:

图片显示

开发平台:

Java

  1. // Engine.java
  2. //
  3. // This software is Copyright 1998, 2000, 2001 by Mark Watson.
  4. // This software may be freely used for any purpose
  5. // and may be modified for any purpose as long as
  6. // you agree to the following:
  7. //
  8. // 1. Any bug fixes or enhancements that you make must be emailed
  9. //    back to Mark Watson (markw@markwatson.com) for possible
  10. //    inclusion in the source code base that is available at
  11. //    the web site www.markwatson.com (credit will be given
  12. //    to contributers).
  13. //
  14. // 2. This copyright notice must be kept with the source code
  15. //    and duplicated if you distribute a modified verison of
  16. //    this software in binary form.
  17. //
  18. // 3. You will not re-distribute the source code. Rather, any
  19. //    improvements to this program will be returned to Mark
  20. //    Watson so that there is always one source base at
  21. //    the web site www.markwatson.com (you may freely
  22. //    distribute compiled derived versions of this program
  23. //    without any restrictions as long as this entire
  24. //    copyright notice is reproduced with the application
  25. //    (e.g., in the 'help' or 'about' dialog box).
  26. //
  27. // 4. This software may not be used for any illegal purpose.
  28. //
  29. // 5. You take all responsibility for the use of this software:
  30. //
  31. // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  32. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  34. // ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  35. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37. // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38. // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  39. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  40. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  41. // SUCH DAMAGE.
  42. // OpenSource contributers: Original program: Mark Watson (markw@markwatson.com)
  43. //
  44. //   Name                      Email (optional) + changes
  45. //   ----                      --------------------------
  46. //   3.0  Achille Petrilli     Achille.Petrilli@cern.ch (directory pop-up, new fonts, larger icons)
  47. //   4.1  Tony Allan           tony@apms.com.au (sorted files, selectable html filename, saved options)
  48. //   4.2  Tony Allan           tony@apms.com.au (fix .html bug, added height/width to HTML, don't write any
  49. //                                               entry if the subdirectory doesn't have any images, add option
  50. //                                               to select if thumbnails are reprocessed)
  51. //   4.3  Reinout van Schouwen rmvschou@cs.vu.nl (added tables and cleaned up HTML generation)
  52. //   6.0  Mark Watson: added an option to not generate thumbnail images
  53. //   7.0  Mark Watson: separated PicWeb.java into two parts: a GUI (PicWeb.java) and and
  54. //                     engine to generate thumbnail image files and HTML files (Engine.java)
  55. import java.applet.*;
  56. import java.awt.*;
  57. import java.awt.image.*;
  58. import java.awt.event.*;
  59. import java.awt.Image;
  60. import java.awt.Graphics;
  61. import java.awt.MediaTracker;
  62. import java.io.*;
  63. import java.net.*;
  64. import java.util.*;
  65. /**
  66.  * Engine - used by the class PicWeb to produce thumbnail image files and
  67.  * HTML files.
  68.  */
  69. public class Engine {
  70.     static final boolean DEBUG = false;  // used for copious debug printout
  71.     private int quality = 60; // JPEG quality, 0 -> 100
  72.     private static final String version = "7.0";
  73.     private static String iniFile = "picweb.ini";
  74.     /**
  75.      * Used to generate small thumbnail images
  76.      */
  77.     private int s_pixels[] = new int[256];
  78.     private float [] reds= new float[256];
  79.     private float [] greens= new float[256];
  80.     private float [] blues= new float[256];
  81.     private boolean [] trans= new boolean[256];
  82.     /**
  83.      * logo - image viewer for thumbnails on GUI
  84.      */
  85.     private Logo logo;
  86.     /**
  87.      * options - holds all data from the properties file
  88.      */
  89.     private Options options;
  90.     /**
  91.      * for callbacks to the PicWeb application for GUI display
  92.      */
  93.     private PicWeb picweb;
  94.     /** Engine class constructor creates the user interface Panel
  95.      * and initializes a work thread
  96.      */
  97.     public Engine(PicWeb picweb, Logo logo, Options options) {
  98.         this.picweb = picweb;
  99.         this.logo = logo;
  100.         this.options = options;
  101.     }
  102.     /**
  103.      * process - given a root directory, recursively process this directory and all
  104.      * subdirectories
  105.      */
  106.     public String process(String root_dir, Logo logo) {
  107.         options.updateFromFile();
  108.         if (!options.dirSpec.equals(root_dir)) {
  109.             options.dirSpec = root_dir;
  110.             options.ini.put("directory", options.dirSpec);
  111.             try {
  112.                 OutputStream out = new BufferedOutputStream(new FileOutputStream(iniFile));
  113.                 options.ini.store(out, "Engine (" + version + ") properties  (directory change)");
  114.                 out.close();
  115.             } catch (IOException e) {
  116.                 System.out.println(e);
  117.                 e.printStackTrace();
  118.             }
  119.         }
  120.         try {
  121.             ProcessGifs(root_dir, options.indexIfEmpty);
  122.             logo.clear();
  123.             return "Done processing." + nl;
  124.         } catch (IOException e) {
  125.             return "caught an io exception in ProcessGifs" + e.toString() + nl;
  126.         }
  127.         catch (IllegalArgumentException e) {
  128.             return "Invalid directory specified." + nl;
  129.         }
  130.     }
  131.     /** Method ProcessGifs processes an entire directory tree by
  132.      *  calling itself recursively.
  133.      */
  134.     final private boolean ProcessGifs(String directory, boolean indexIfEmpty) throws IOException {
  135.         boolean found_image = indexIfEmpty;     // (ta 4.2) set initial state depending on indexIfEmpty flag.
  136.         picweb.print("Processing: " + directory + nl);
  137.         File dir = new File(directory);
  138.         if (!dir.isDirectory())
  139.             throw new IllegalArgumentException("no such directory");
  140.         File cwd = dir;
  141.         String[] entries = cwd.list(new GraphicsFileFilter());
  142.         int num = entries.length;
  143.         int countTableColumns = 0; //RMvS
  144.         if (options.ini.getProperty("sort" ,"true").toLowerCase().equals("true")) {
  145.     picweb.print("Sorting directory " + directory + nl);
  146.             for (int i = num; --i>0; ) {
  147.                 boolean swapped = false;
  148.                 for (int j = 0; j<i; j++) {
  149.                     if (entries[j].toString().compareTo(entries[j+1].toString()) > 0) {
  150.                         String T = entries[j];
  151.                         entries[j] = entries[j+1];
  152.                         entries[j+1] = T;
  153.                         swapped = true;
  154.                     }
  155.                 }
  156.                 if (!swapped)
  157.                     break;
  158.             }
  159. }
  160.         if (options.skipProcessedDirs) {
  161.             // check to see if this sub-directory already has a 'HTMLFilename' file:
  162.             for (int i=0; i<num; i++) {
  163.                 if (entries[i].equals(options.HTMLFilename)) {
  164.                     picweb.print(directory + " already has a '" + options.HTMLFilename + "' file" + nl);
  165.                     return true;        // (ta 4.2) need to include previously processed directories
  166.                 }
  167.             }
  168.         }
  169.         // Open HTML output file:
  170.         String fname=directory + fs + options.HTMLFilename;
  171.         if (DEBUG) System.out.println("fname="+fname);
  172.         File out_file = new File(fname);
  173.         try {
  174.             if (out_file.exists())  {
  175.                 try { out_file.delete(); }
  176.                 catch (SecurityException e) {  }
  177.             }
  178.         } catch (Exception e) { e.printStackTrace(); }
  179.         DataOutputStream outs = null;
  180.         File d_f = null;
  181.         try {
  182.             try {
  183.                 d_f = new File(fname);
  184.                 outs = new DataOutputStream(new FileOutputStream(d_f));
  185.             } catch (Exception e) {
  186.                 picweb.print("Error writing HTML file: " + options.HTMLFilename + nl + e + nl);
  187.                 return found_image;
  188.             }
  189.             // add a comment to the start of the generated html...
  190.             outs.writeBytes("<HTML>" + nl +"<HEAD>" + nl); // RMvS
  191.             outs.writeBytes("<!-- Picture Web Page Maker(tm) version " +
  192.     version + "  www.markwatson.com -->" + nl);
  193.             outs.writeBytes("<!-- File created on " + new Date() + " -->" + nl + nl);
  194.             outs.writeBytes("<TITLE>Thumbnail image overview</TITLE>" + nl );
  195.             outs.writeBytes("</HEAD>" + nl + "<BODY>" + nl ); // RMvS
  196.             String dirName = directory.replace('\','/');
  197.             if (options.ini.getProperty("trimDir" ,"false").toLowerCase().equals("true")) {
  198.                 int x = dirName.indexOf('/');
  199.                 if (x == -1)
  200.                     x = 0;
  201.                 outs.writeBytes("<h1>" + options.ini.getProperty("dirText" ,"") +
  202. dirName.substring(x) + "</h1>" + nl);
  203.             }
  204.             else
  205.                 outs.writeBytes("<h1>Directory " + dirName + "</h1>" + nl);
  206.             // Make 2 passes at these files:
  207.             //   1. write out HTML href's to sub-directories
  208.             //   2. write out HTML href's showing mini-files, linked to large graphics files
  209.             //  or, if in no thumbnail mode:
  210.             //   2. write out full size images
  211.             for(int i = 0; i < num; i++) {
  212.                 String entry_name = entries[i].toString();
  213.                 String entry_name1 = entry_name.replace('\','/');
  214.                 try {
  215.                     File f = new File(cwd, entry_name);
  216.                     if (f.isDirectory()) {
  217.                         // (ta 4.1) tidy up generated html...
  218.                         String dirName1 = directory.replace('\','/');
  219.                         if (options.ini.getProperty("trimDir" ,"false").toLowerCase().equals("true")) {
  220.                             int y = dirName1.indexOf('/');
  221.                             if (y == -1)
  222.                                 y = 0;
  223.                             dirName1 = options.ini.getProperty("subDirText" ,
  224.        options.ini.getProperty("dirText" ,"")) +
  225. dirName1.substring(y);
  226.                         }
  227.                         // This is a directory, so add an entry to current HTML file.
  228.                         // (ta 4.2) Only write directory entry if there was an image in a sub-directory
  229.                         if (ProcessGifs(directory +  fs  + entry_name, indexIfEmpty))   {
  230.                             outs.writeBytes("<a href=""  + entry_name1 +
  231.                                             "/" + options.HTMLFilename +
  232.                                             "">" + dirName1 +
  233.                                             "/" + entry_name1 +
  234.                                             "</a><p>" + nl);
  235.                             found_image = true;
  236.                         } // Recurse down to handle this directory: (depth first is OK here!)
  237.                     }
  238.                 } catch (Exception e) {
  239.                     System.out.println(e);
  240.                     e.printStackTrace();
  241.                 }
  242.             }
  243.             // RMvS : create table, align it to center:
  244.             outs.writeBytes("<CENTER> <TABLE BORDER="1" PADDING="2">" + nl);
  245.             for (int i = 0; i < num; i++) {
  246.                 String entry_name = entries[i].toString();
  247.                 String entry_name1 = entry_name.replace('\','/');
  248.                 try {
  249.                     File f = new File(cwd, entry_name);
  250.                     if (!f.isDirectory() &&
  251.                         !entry_name.toLowerCase().endsWith("htm")  &&
  252.                         !entry_name.toLowerCase().endsWith("html")) {
  253.                         Image thumbnail = null;
  254.                         if (options.thumbs == true) {
  255.                             if (DEBUG) System.out.println("in thumb nail mode");
  256.                             if (options.skipProcessedFiles)     {
  257.                                 thumbnail = existingThumbnail(directory + fs + convertName(entry_name));
  258.                                 if (thumbnail == null)
  259.                                     thumbnail = newImage(directory + fs + entry_name, 1);
  260.                             } else {
  261.                                 thumbnail = newImage(directory + fs + entry_name, 1);
  262.                             }
  263.                             // Add a link:
  264.                             if (thumbnail != null) {
  265.                                 if (countTableColumns == 0 && options.thumbs) {
  266.                                     outs.writeBytes("<TR ALIGN=center VALIGN=middle>" + nl);
  267.                                 }
  268.                                 outs.writeBytes("<TD>" +
  269.                                                 "<a href="" + entry_name1 + "">" +
  270.                                                 "<IMG src="" + convertName(entry_name).replace('\', '/') + """ +
  271.                                                 " width="" + thumbnail.getWidth(picweb) + """ +
  272.                                                 " height="" + thumbnail.getHeight(picweb) + """ +
  273.                                                 " border="0"></a>");
  274.                                 if (options.fileNamesFlag) {
  275.                                     outs.writeBytes("<BR> <FONT SIZE="-1">" + entry_name1 + "</FONT>" + nl);
  276.                                 }
  277.                                 outs.writeBytes("</TD>" + nl); //RMvS : added <TD> and </TD> to output string
  278.                                 found_image = true;  // remember that we actually did something in this directory
  279.                                 countTableColumns++ ; // RMvS
  280.                                 if (countTableColumns == 3) {
  281.                                     outs.writeBytes("</TR>" + nl);
  282.                                     countTableColumns = 0;
  283.                                 }
  284.                             }
  285.                         } else { // no thumbnail mode:
  286.                             outs.writeBytes("<IMG src="" + entry_name + """ +
  287.                                             " border="20">");
  288.                             if (options.fileNamesFlag) {
  289.                                 outs.writeBytes("<BR> <FONT SIZE="-1">" + entry_name1 + "</FONT>" + nl);                                                              // (ta 4.2)
  290.                             }
  291.                             found_image = true; // remember that we actually did something in this directory
  292.                         }
  293.                     }
  294.                 } catch (Exception e) {
  295.                     System.out.println(e);
  296.                     e.printStackTrace();
  297.                 }
  298.             }
  299.             if (countTableColumns != 0) {
  300.                 outs.writeBytes("</TR>" + nl);
  301.             }
  302.             outs.writeBytes("</TABLE> </CENTER>" + nl + "</BODY> </HTML>");
  303.         }
  304.         finally {
  305.             if (outs != null)  outs.close();
  306.         }
  307.         // (ta 4.2) if we didn't find anything, delete the file and write a message.
  308.         // - Yes I know that this is a very crude way to handle a empty directory!
  309.         if (!found_image) {
  310.             if (d_f != null)
  311.                 d_f.delete();
  312.             picweb.print(directory + " did not contain any images." + nl);
  313.         }
  314.         return found_image;
  315.     }
  316.     /**
  317.      * Take an image file name and make a thumbnail name.
  318.      */
  319.     private String convertName(String file_name) {
  320.         return file_name.substring(0, file_name.lastIndexOf('.')) + "_s.jpg";
  321.     }
  322.     /**
  323.      * create an image file
  324.      */
  325.     final private Image newImage(String file_name, int scale_mode) {
  326.         if (DEBUG) System.out.println("     -- entered Engine.newImage("+file_name+", "+scale_mode+")");
  327.         File test_file = new File(file_name);
  328.         if (test_file.isDirectory()) {
  329.     System.out.println("    -- leaving Engine.newImage: error: file is a directory");
  330.     return null;
  331. }
  332.         int to_width, to_height;
  333.         int image_width, image_height, image_pixels[];
  334.         // read data
  335.         URL url=null;
  336.         try { url = new URL("file", "", file_name); }
  337.         catch (MalformedURLException e) { }
  338.         if (url==null) {
  339.             System.out.println("     -- leaving Engine.newImage: malformed URL");
  340.             return null;
  341.         }
  342.         Image input_image = java.awt.Toolkit.getDefaultToolkit().getImage(url);
  343.         MediaTracker tracker = new MediaTracker(picweb);
  344.         tracker.addImage(input_image, 0);
  345.         // load it all before continuing
  346.         try { tracker.waitForAll(); } catch (InterruptedException e){};
  347.         tracker = null;
  348.         image_width = input_image.getWidth(picweb);
  349.         image_height = input_image.getHeight(picweb);
  350. if (DEBUG) System.out.println("      -- width of image="+image_width + ", height of image="+image_height);
  351.         image_pixels = new int[image_width * image_height];
  352.         to_width = 60;
  353.         to_height = 60;
  354.         float fact2;
  355.         if (image_width>image_height) {
  356.             fact2=image_width;
  357.         } else {
  358.             fact2=image_height;
  359.         }
  360.         fact2 = 60 / fact2;
  361.         to_width = (int)((float)image_width * fact2);
  362.         to_height= (int)((float)image_height* fact2);
  363.         // Tweak the size of the thumbnails:
  364.         if (options.imageSizeChoice == 0) {
  365.             to_width = (2 * to_width) / 3;
  366.             to_height= (2 * to_height)/ 3;
  367.         }
  368.         if (options.imageSizeChoice == 2) {
  369.             to_width = (3 * to_width) / 2;
  370.             to_height= (3 * to_height)/ 2;
  371.         }
  372.         if (options.imageSizeChoice == 3) {
  373.             to_width = (13 * to_width) / 6;
  374.             to_height= (13 * to_height)/ 6;
  375.         }
  376.         //# Create a PixelGrabber to Get the Pixels of the image and store
  377.         //# them into the image_pixels array
  378.         PixelGrabber pixel_grabber =
  379.             new PixelGrabber(input_image.getSource(), 0, 0,
  380.                              image_width, image_height, image_pixels,
  381.                              0, image_width);
  382. if (DEBUG) System.out.println("      -- after creating pixel grabber");
  383.         try {
  384.             pixel_grabber.grabPixels();
  385.         } catch (InterruptedException e) { }
  386.         pixel_grabber = null;
  387. if (DEBUG) System.out.println("      -- after grabbing pixels: to_width=" + to_width + ", to_height=" + to_height);
  388.         // resample data
  389.         int
  390.             to_pixels[] = new int[to_width*to_height];
  391.         double
  392.             xscale, yscale;
  393.         // set scale
  394.         xscale = ((double)image_width) / ((double)to_width);
  395.         yscale = ((double)image_height) / ((double)to_height);
  396.         // check mode
  397.         if ( scale_mode != 0 ) {   // 1 to 1 scaling
  398.             xscale = java.lang.Math.min(xscale,yscale);
  399.             yscale = xscale;
  400.         }
  401.         int
  402.             from_x, from_y,
  403.             to_index, to_x, to_y;
  404.         for(to_index=0,to_y=0;to_y<to_height;to_y++) {
  405.             from_y = (int)(yscale * to_y);
  406.             for(to_x=0;to_x<to_width;to_x++,to_index++) {
  407.                 from_x = (int)(xscale * to_x);
  408.                 to_pixels[to_index] = image_pixels[ (from_y * image_width) + from_x];
  409.             }// end for x
  410.         }// end for y
  411. if (DEBUG) System.out.println("      -- before trying to create new thumbnail image in memory");
  412.         // new image
  413.         Image temp= picweb.createImage(new MemoryImageSource(to_width,to_height,
  414.                                                              to_pixels,0,to_width));
  415. if (DEBUG) {
  416.     System.out.println("      -- after trying to create new thumbnail image in memory: width=" +
  417.        temp.getWidth(picweb) + ", height=" + temp.getHeight(picweb));
  418. }
  419.         if (options.showLogo) {
  420.             logo.setImage(temp, to_width, to_height);
  421.         }
  422. if (DEBUG) System.out.println("      -- after setting the thumbnail image on the GUI");
  423.         // save the image to a new GIF file:
  424.         FileOutputStream os = null;
  425.         File output_file = null;
  426.         try {
  427.             output_file = new File(convertName(file_name));
  428.             os = new FileOutputStream(output_file);
  429.     if (DEBUG) System.out.println("           before creating a new JpegEncoder: os="+os);
  430.             JpegEncoder je = new JpegEncoder(temp, quality, os);
  431.     if (DEBUG) System.out.println("           before doing the compress...");
  432.             je.Compress();
  433.     if (DEBUG) System.out.println("           before closing the file...");
  434.             os.close();
  435.         } catch (Exception e) {
  436.             try { os.close(); } catch (IOException e2) {}
  437.         }
  438.         if (options.verbose)
  439.             picweb.print("Creating: " + output_file.getName() + nl);
  440.         if (DEBUG) System.out.println("     -- leaving Engine.newImage");
  441.         return temp;
  442.     }
  443.     /**
  444.      * used int newImage
  445.      */
  446.     final private Image existingThumbnail(String thumbnail_name) {
  447.         File test_file = new File(thumbnail_name);
  448.         if (test_file.isDirectory())
  449.             return null;
  450.         //System.out.println("test_file.exists(): " + test_file.exists());
  451.         if (!test_file.exists())
  452.             return null;
  453.         // read data
  454.         URL url=null;
  455.         try { url = new URL("file", "", thumbnail_name); }
  456.         catch (MalformedURLException e) {System.out.println(e);}
  457.         if (url==null) { return null; }
  458.         Image thumbnail = java.awt.Toolkit.getDefaultToolkit().getImage(url);
  459.         // not sure if we need a Media Tracker if all we need are dimensions?
  460.         MediaTracker tracker = new MediaTracker(picweb);
  461.         tracker.addImage(thumbnail, 0);
  462.         // load it all before continuing
  463.         try { tracker.waitForAll(); } catch (InterruptedException e){};
  464.         tracker = null;
  465.         int width = thumbnail.getWidth(picweb);
  466.         int height = thumbnail.getHeight(picweb);
  467.         if ((width == -1) && (height == -1))
  468.             return null;        // image probably doesn't exist...
  469.         if (options.showLogo) {
  470.             logo.setImage(thumbnail, width, height);
  471.         }
  472.         // (ta 4.2)
  473.         if (options.verbose)
  474.             picweb.print("Using existing: " + test_file.getName() + nl);
  475.         return thumbnail;
  476.     }
  477.     /**
  478.      * accept graphics files and director files (only)
  479.      */
  480.     private class GraphicsFileFilter implements FilenameFilter {
  481.         public GraphicsFileFilter() {
  482.         }
  483.         final public boolean accept(File dir, String name) {
  484.             String s = name.toLowerCase();
  485.             if (s.endsWith("_s.jpg")) return false;
  486.             if (s.endsWith("gif")) return true;
  487.             if (s.endsWith("jpg")) return true;
  488.             if (s.endsWith("bmp")) return true;
  489.             if (s.endsWith("jpeg")) return true;
  490.             if (s.endsWith("htm")) return true;
  491.             if (s.endsWith("html")) return true;
  492.             return (new File(dir, name)).isDirectory();
  493.         }
  494.     }
  495.     /** The 'nl' and 'fs' objects are define for string constants
  496.      * instead of using literal strings in order to pass the
  497.      * "100% Pure" Java certification by Key Labs
  498.      */
  499.     private String nl = System.getProperty("line.separator");
  500.     private String fs = System.getProperty("file.separator");
  501. }