/Users/lyon/j4p/src/j2d/gui/Main.java

1    // Glenn Josefiak 
2    // Fairfield University 
3    // SW513 
4    // Spring 2003 
5     
6    package j2d.gui; 
7     
8    // Standard libraries 
9     
10   import futils.StreamSniffer; 
11   import gui.ClosableJFrame; 
12   import gui.run.RunMenu; 
13   import gui.run.RunMenuItem; 
14   import j2d.Images; 
15   import j2d.ImageUtils; 
16   import j2d.file.ExtensionFileFilter; 
17   import j2d.file.PPMToolkit; 
18   import j2d.imageproc.ExponentialStretchProcessor; 
19   import j2d.imageproc.FalseColorProcessor; 
20   import j2d.imageproc.HistogramEQProcessor; 
21   import j2d.imageproc.LinearMappingProcessor; 
22    
23   import javax.swing.*; 
24   import javax.media.format.VideoFormat; 
25   import javax.media.protocol.PushBufferDataSource; 
26   import java.awt.*; 
27   import java.awt.image.BufferedImage; 
28   import java.awt.event.ActionEvent; 
29   import java.awt.event.ActionListener; 
30   import java.io.*; 
31   import java.util.Observable; 
32   import java.util.Observer; 
33    
34   /** 
35    * This class provides a GUI for altering images 
36    */ 
37    
38   public class Main extends ClosableJFrame { 
39    
40       private MDIDesktopPane deskTop = new MDIDesktopPane(); 
41    
42       private FalseColorToolbox falseColorToolbox; 
43       private LinearMappingToolbox linearMappingToolbox; 
44       private HistogramEQToolbox histEqToolbox; 
45       private ExponentialStretchToolbox estStretchControls; 
46    
47    
48       // Image processors 
49    
50       private FalseColorProcessor fcProcessor 
51               = new FalseColorProcessor(); 
52       private LinearMappingProcessor lmProcessor 
53               = new LinearMappingProcessor(); 
54       private HistogramEQProcessor heProcessor 
55               = new HistogramEQProcessor(); 
56       private ExponentialStretchProcessor esProcessor 
57               = new ExponentialStretchProcessor(); 
58    
59       // Capture details 
60       private VideoFormat vfFormat; 
61       private PushBufferDataSource pbds; 
62    
63       /** 
64        * Construct a new ImageTool 
65        */ 
66       public Main() { 
67           Container c; 
68    
69           c = getContentPane(); 
70           c.setLayout(new BorderLayout()); 
71    
72    
73           c.add(new JScrollPane(deskTop)); 
74    
75           setTitle("Image Tool"); 
76           setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
77    
78           // Set up the menus 
79    
80           JMenuBar mb = new JMenuBar(); 
81           setJMenuBar(mb); 
82           addFileMenu(mb); 
83           addProcessMenu(mb); 
84           WindowMenu windowMenu = new WindowMenu(deskTop); 
85           mb.add(windowMenu); 
86           windowMenu.setMnemonic('W'); 
87       } 
88    
89       private void addProcessMenu(JMenuBar mb) { 
90           RunMenu processMenu = new RunMenu("[process"); 
91           mb.add(processMenu); 
92           processMenu.add(new RunMenuItem("[False Color") { 
93               public void run() { 
94                   if (falseColorToolbox == null || 
95                           falseColorToolbox.isClosed()) { 
96                       launchColorControls(); 
97                   } 
98               } 
99           }); 
100          processMenu.add(new RunMenuItem("[negate{ctrl N}") { 
101              public void run() { 
102                  Utils.negate(deskTop); 
103              } 
104          }); 
105          processMenu.add(new RunMenuItem("[Linear Mapping") { 
106              public void run() { 
107                  if (linearMappingToolbox == null || 
108                          linearMappingToolbox.isClosed()) { 
109                      launchMappingControls(); 
110                  } 
111              } 
112          }); 
113          processMenu.add(new RunMenuItem("[Histogram EQ{ctrl H}") { 
114              public void run() { 
115                  if (histEqToolbox == null || 
116                          histEqToolbox.isClosed()) { 
117                      launchHistogramControls(); 
118                  } 
119              } 
120          }); 
121          processMenu.add(new RunMenuItem("[Exponential Stretch") { 
122              public void run() { 
123                  if (estStretchControls == null || 
124                          estStretchControls.isClosed()) { 
125                      launchStretchControls(); 
126                  } 
127              } 
128          }); 
129      } 
130   
131      private void addFileMenu(JMenuBar mb) { 
132          RunMenu fileMenu = new RunMenu("[File"); 
133          mb.add(fileMenu); 
134   
135          fileMenu.add(new RunMenuItem("[Open{ctrl O}", 
136                  Images.getOpenIcon()) { 
137              public void run() { 
138                  openImage(); 
139              } 
140          }); 
141   
142          fileMenu.add(new RunMenuItem("[Capture screen{alt 4}") { 
143              public void run() { 
144                  captureScreen(); 
145              } 
146          }); 
147          fileMenu.add(new RunMenuItem("[Save{ctrl S}", 
148                  Images.getSaveIcon()) { 
149              public void run() { 
150                  saveImage(); 
151              } 
152          }); 
153          fileMenu.add(new RunMenuItem("[Revert{crtl R}", 
154                  Images.getRevertIcon()) { 
155              public void run() { 
156                  revertImage(); 
157              } 
158          }); 
159          fileMenu.add(new RunMenuItem("[Exit{ctrl Q}", 
160                  Images.getExitIcon()) { 
161              public void run() { 
162                  shutdown(); 
163              } 
164          }); 
165      } 
166   
167      /** 
168       * Helper function for closing the ImageTool. 
169       * Could put other termination code here. 
170       */ 
171      private void shutdown() { 
172          dispose(); 
173      } 
174      /** 
175       * This is called when the user requests a new file to be opened. 
176       */ 
177      private void captureScreen() { 
178   
179          Image imgProcessee; 
180          ImageChildFrame icfNewFrame; 
181          //int intSuccess = 0; 
182   
183          try { 
184              BufferedImage bi = ImageUtils.captureWholeScreen(); 
185              imgProcessee = ImageUtils.getImage(bi); 
186   
187              icfNewFrame = 
188                      new ImageChildFrame(imgProcessee, 
189                              "screen shot"); 
190              deskTop.add(icfNewFrame); 
191          } catch (AWTException e) { 
192              e.printStackTrace(); 
193   
194          } 
195   
196      } 
197      /** 
198       * This is called when the user requests a new 
199       * file to be opened. 
200       */ 
201      private void openImage() { 
202          File imageFile; 
203          Image imgProcessee; 
204          ImageChildFrame icfNewFrame; 
205          //int intSuccess = 0; 
206   
207          imageFile = 
208                  futils.Futil.getReadFile("select an image file"); 
209          imgProcessee = getImage(imageFile); 
210   
211          icfNewFrame = 
212                  new ImageChildFrame(imgProcessee, 
213                          imageFile.getName()); 
214          deskTop.add(icfNewFrame); 
215   
216      } 
217   
218      public Image getImage(File f) { 
219          if (f == null) return null; 
220          if (!f.exists()) return null; 
221   
222          InputStream is = null; 
223          try { 
224              is = new FileInputStream(f); 
225          } catch (FileNotFoundException e) { 
226              e.printStackTrace(); 
227          } 
228   
229          StreamSniffer ss = new StreamSniffer(is); 
230          int id = ss.classifyStream(); 
231          switch (id) { 
232              case StreamSniffer.PPM: 
233                  return getPPMImage(f); 
234              case StreamSniffer.PPM_RAWBITS: 
235                  return getPPMImage(f); 
236              case StreamSniffer.GIF87a: 
237                  return getGifOrJpg(f); 
238              case StreamSniffer.GIF89a: 
239                  return getGifOrJpg(f); 
240              case StreamSniffer.JPEG: 
241                  return getGifOrJpg(f); 
242              default: 
243                  { 
244                      System.out.println("Can not open " + 
245                              ss + 
246                              " as image"); 
247                      return null; 
248                  } 
249   
250          } 
251      } 
252   
253      private Image getGifOrJpg(File imageFile) { 
254          return Toolkit.getDefaultToolkit() 
255                  .getImage(imageFile.getAbsolutePath()); 
256      } 
257   
258      /* 
259      private Image getZippedPPMImage(File imageFile) { 
260          Image imgProcessee = null; 
261          try { 
262              imgProcessee = PPMToolkit.getImage(imageFile, true); 
263          } catch (IOException e) { 
264              e.printStackTrace(); 
265          } 
266          return imgProcessee; 
267      } 
268      */ 
269   
270      private Image getPPMImage(File imageFile) { 
271          try { 
272              Image imgProcessee; 
273              imgProcessee = 
274                      PPMToolkit.getImage(imageFile, 
275                              false); 
276              return imgProcessee; 
277          } catch (IOException e) { 
278              e.printStackTrace(); 
279          } 
280          return null; 
281      } 
282   
283      /** 
284       * This is called when the user picks the save 
285       * menu option. 
286       */ 
287      private void saveImage() { 
288          ImageChildFrame icf; 
289          int intSuccess; 
290          File imageFile; 
291   
292   
293          try { 
294              icf = 
295                      (ImageChildFrame) deskTop.getTopmostFrame(ImageChildFrame.class); 
296              if (icf == null) return; 
297          } catch (Exception e) { 
298              return; 
299          } 
300   
301          JFileChooser jfc = new JFileChooser(); 
302          ExtensionFileFilter eff1 = 
303                  new ExtensionFileFilter("ppm", 
304                          "Portable Pixelmap image file"); 
305          jfc.addChoosableFileFilter(eff1); 
306          ExtensionFileFilter eff2 = 
307                  new ExtensionFileFilter("ppm.gz", 
308                          "Zipped Pixelmap image file"); 
309          jfc.addChoosableFileFilter(eff2); 
310          jfc.setFileFilter(eff1); 
311          jfc.setAcceptAllFileFilterUsed(false); 
312   
313          intSuccess = jfc.showSaveDialog(this); 
314   
315          if (intSuccess == 
316                  JFileChooser.APPROVE_OPTION) { 
317              imageFile = jfc.getSelectedFile(); 
318   
319              ExtensionFileFilter eff = (ExtensionFileFilter) jfc.getFileFilter(); 
320   
321              try { 
322                  if (eff == eff1) { 
323                      imageFile = 
324                              fixExtension(imageFile, 
325                                      "ppm"); 
326                      PPMToolkit.saveImage(icf.getImage(), 
327                              imageFile, 
328                              false); 
329                  } else if (eff == eff2) { 
330                      imageFile = 
331                              fixExtension(imageFile, 
332                                      "ppm.gz"); 
333                      PPMToolkit.saveImage(icf.getImage(), 
334                              imageFile, 
335                              true); 
336                  } 
337                  icf.setTitle(imageFile.getName()); 
338              } catch (Exception e) { 
339                  JOptionPane.showMessageDialog(this, "File write error: \n" 
340                          + e.toString()); 
341              } 
342          } 
343      } 
344   
345      /** 
346       * Fix the file extension 
347       */ 
348      private File fixExtension(File file, 
349                                String extension) { 
350          String path = file.getAbsolutePath(); 
351   
352          if (!path.endsWith("." + extension)) { 
353              path += "." + extension; 
354          } 
355          return new File(path); 
356      } 
357   
358      /** 
359       * Set the image in the active frame to the 
360       * base image. 
361       */ 
362      private void revertImage() { 
363          ImageChildFrame icf; 
364   
365          try { 
366              icf = 
367                      (ImageChildFrame) 
368                      deskTop.getTopmostFrame(ImageChildFrame.class); 
369              icf.revert(); 
370          } catch (Exception e) { 
371              // do nothing 
372          } 
373      } 
374   
375      /** 
376       * Helper function to show LinearMappingToolbox 
377       */ 
378      private void launchMappingControls() { 
379          linearMappingToolbox = 
380                  new LinearMappingToolbox(); 
381          linearMappingToolbox.show(); 
382          linearMappingToolbox.getSliderBank() 
383                  .addObserver(new Observer() { 
384                      public void update(Observable x, 
385                                         Object y) { 
386                          adjustLinearMapping(false); 
387                      } 
388                  }); 
389          linearMappingToolbox.getButton() 
390                  .addActionListener(new ActionListener() { 
391                      public void actionPerformed(ActionEvent e) { 
392                          adjustLinearMapping(true); 
393                      } 
394                  }); 
395          deskTop.add(linearMappingToolbox); 
396      } 
397   
398      /** 
399       * Helper function to show FalseColorToolbox 
400       */ 
401      private void launchColorControls() { 
402          falseColorToolbox = 
403                  new FalseColorToolbox(); 
404          falseColorToolbox.show(); 
405          falseColorToolbox.getSliderBank() 
406                  .addObserver(new Observer() { 
407                      public void update(Observable x, 
408                                         Object y) { 
409                          adjustColorization(); 
410                      } 
411                  }); 
412          deskTop.add(falseColorToolbox); 
413      } 
414   
415      /** 
416       * Helper function to show HistogramEQToolbox 
417       */ 
418      private void launchHistogramControls() { 
419          histEqToolbox = new HistogramEQToolbox(); 
420          histEqToolbox.show(); 
421          histEqToolbox.getButton() 
422                  .addActionListener(new ActionListener() { 
423                      public void actionPerformed(ActionEvent e) { 
424                          adjustHistogram(); 
425                      } 
426                  }); 
427          histEqToolbox.getSlider().addObserver(new Observer() { 
428              public void update(Observable x, 
429                                 Object y) { 
430                  adjustHistogram(); 
431              } 
432          }); 
433   
434          deskTop.add(histEqToolbox); 
435      } 
436   
437      /** 
438       * Helper function to show ExponentialStretchToolbox 
439       */ 
440      private void launchStretchControls() { 
441          estStretchControls = 
442                  new ExponentialStretchToolbox(); 
443          estStretchControls.show(); 
444          estStretchControls.getSlider() 
445                  .addObserver(new Observer() { 
446                      public void update(Observable x, 
447                                         Object y) { 
448                          adjustExponentialStretch(); 
449                      } 
450                  }); 
451          deskTop.add(estStretchControls); 
452      } 
453   
454   
455      /** 
456       * This is called each time a slider in the 
457       * FalseColorToolbox is moved. This is where 
458       * the real image processing happens. 
459       */ 
460      private void adjustColorization() { 
461          float coeff[] = new float[3]; 
462          ImageChildFrame icf; 
463   
464          try { 
465              coeff = 
466                      falseColorToolbox.getSliderBank() 
467                      .getValues(); 
468   
469              icf = 
470                      (ImageChildFrame) 
471                      deskTop.getTopmostFrame(ImageChildFrame.class); 
472              fcProcessor.setBaseImage(icf.getBaseImage()); 
473              fcProcessor.setColorization(coeff[0], 
474                      coeff[1], 
475                      coeff[2]); 
476              fcProcessor.performAlgorithm(); 
477              icf.setImage(fcProcessor.getProcessedImage()); 
478          } catch (Exception e) { 
479              // for now, do nothing. 
480          } 
481      } 
482   
483      /** 
484       * This is called each time a slider on the 
485       * LinearMappingToolbox is moved (btn = false) 
486       * or the button on the LinearMappingToolbox 
487       * is pressed (btn = true).  This is where the 
488       * real image processing happens. 
489       */ 
490      private void adjustLinearMapping(boolean btn) { 
491          float coeff[] = new float[2]; 
492          ImageChildFrame icf; 
493   
494          try { 
495              icf = 
496                      (ImageChildFrame) deskTop.getTopmostFrame(ImageChildFrame.class); 
497              lmProcessor.setBaseImage(icf.getBaseImage()); 
498              if (btn) { 
499  // compute parameters from the image, then update the toolbox sliders 
500                  coeff = 
501                          lmProcessor.setOptimalParameters(); 
502                  linearMappingToolbox.getSliderBank() 
503                          .setValues(coeff); 
504              } else { 
505  // get the parameters from the sliders, then update the image 
506                  coeff = 
507                          linearMappingToolbox.getSliderBank() 
508                          .getValues(); 
509                  lmProcessor.setParameters(coeff[0], coeff[1]); 
510              } 
511              lmProcessor.performAlgorithm(); 
512              icf.setImage(lmProcessor.getProcessedImage()); 
513          } catch (Exception e) { 
514              // for now, do nothing. 
515          } 
516      } 
517   
518      /** 
519       * This is called when the slider on the 
520       * HistogramEQToolbox is moved, or when its 
521       * button is pressed. 
522       */ 
523      private void adjustHistogram() { 
524          boolean exponential; 
525          float alpha; 
526          ImageChildFrame icf; 
527   
528          try { 
529              icf = 
530                      (ImageChildFrame) deskTop.getTopmostFrame(ImageChildFrame.class); 
531              heProcessor.setBaseImage(icf.getBaseImage()); 
532   
533              exponential = 
534                      histEqToolbox.getExponential(); 
535              heProcessor.setExponential(exponential); 
536              if (exponential) { 
537                  alpha = 
538                          histEqToolbox.getSlider() 
539                          .getValue(); 
540                  heProcessor.setAlpha(alpha); 
541              } 
542   
543              heProcessor.performAlgorithm(); 
544              icf.setImage(heProcessor.getProcessedImage()); 
545          } catch (Exception e) { 
546              // for now, do nothing. 
547          } 
548      } 
549   
550      /** 
551       * This is called each time a slider in the 
552       * ExponentialStretchToolbox is moved. This is 
553       * where the real image processing happens. 
554       */ 
555      private void adjustExponentialStretch() { 
556          float coeff; 
557          ImageChildFrame icf; 
558          try { 
559              coeff = 
560                      estStretchControls.getSlider() 
561                      .getValue(); 
562   
563              icf = 
564                      (ImageChildFrame) deskTop.getTopmostFrame(ImageChildFrame.class); 
565              esProcessor.setBaseImage(icf.getBaseImage()); 
566              esProcessor.setPower(coeff); 
567              esProcessor.performAlgorithm(); 
568              icf.setImage(esProcessor.getProcessedImage()); 
569          } catch (Exception e) { 
570              // for now, do nothing. 
571          } 
572      } 
573   
574      /** 
575       * Entry point of the ImageTool application. 
576       */ 
577      public static void main(String args[]) { 
578          Main fc = new Main(); 
579          fc.setSize(500, 400); 
580          fc.show(); 
581      } 
582  }