check annotation label widths as well as id widths
[jalview.git] / src / jalview / gui / AlignmentPanel.java
1 package jalview.gui;\r
2 \r
3 import jalview.jbgui.GAlignmentPanel;\r
4 import jalview.schemes.*;\r
5 import jalview.analysis.*;\r
6 import jalview.datamodel.*;\r
7 import java.awt.*;\r
8 import java.awt.event.*;\r
9 import java.awt.print.*;\r
10 import java.io.*;\r
11 import java.awt.image.*;\r
12 import org.jibble.epsgraphics.*;\r
13 import javax.imageio.*;\r
14 \r
15 \r
16 \r
17 public class AlignmentPanel extends GAlignmentPanel implements AdjustmentListener, Printable\r
18 {\r
19 \r
20   AlignViewport     av;\r
21   OverviewPanel overviewPanel;\r
22   SeqPanel   seqPanel;\r
23   IdPanel    idPanel;\r
24   IdwidthAdjuster idwidthAdjuster;\r
25   public AlignFrame alignFrame;\r
26   ScalePanel scalePanel;\r
27   AnnotationPanel annotationPanel;\r
28   AnnotationLabels alabels;\r
29 \r
30   // this value is set false when selection area being dragged\r
31   boolean fastPaint = true;\r
32 \r
33   public AlignmentPanel(AlignFrame af, final AlignViewport av)\r
34   {\r
35     alignFrame = af;\r
36     this.av         = av;\r
37     seqPanel        = new SeqPanel  (av, this);\r
38     idPanel         = new IdPanel   (av, this);\r
39 \r
40     scalePanel = new ScalePanel(av, this);\r
41 \r
42     idPanelHolder.add(idPanel, BorderLayout.CENTER);\r
43     idwidthAdjuster = new IdwidthAdjuster(this);\r
44     idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);\r
45 \r
46     annotationPanel = new AnnotationPanel(this);\r
47     alabels = new AnnotationLabels(this);\r
48 \r
49     annotationSpaceFillerHolder.setPreferredSize(annotationPanel.getPreferredSize());\r
50     annotationScroller.setPreferredSize(annotationPanel.getPreferredSize());\r
51     annotationScroller.setViewportView(annotationPanel);\r
52     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);\r
53 \r
54     Dimension d = calculateIdWidth();\r
55     d.setSize( d.width+4, d.height);\r
56     idPanel.idCanvas.setPreferredSize( d );\r
57     hscrollFillerPanel.setPreferredSize( d );\r
58 \r
59     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);\r
60     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);\r
61 \r
62 \r
63     if(seqPanel.seqCanvas.getWidth()==0)\r
64     javax.swing.SwingUtilities.invokeLater(new Runnable()\r
65      {\r
66        public void run()\r
67        {\r
68          setScrollValues(0,0);\r
69          Dimension d = calculateIdWidth();\r
70          d.setSize( d.width+4, d.height);\r
71          idPanel.idCanvas.setPreferredSize( d );\r
72          RefreshPanels();\r
73        }\r
74     });\r
75 \r
76 \r
77     hscroll.addAdjustmentListener(this);\r
78     vscroll.addAdjustmentListener(this);\r
79 \r
80     addComponentListener(new ComponentAdapter()\r
81    {\r
82      public void componentResized(ComponentEvent evt)\r
83      {\r
84           RefreshPanels();\r
85      }\r
86    });\r
87 \r
88    setFocusable(true);\r
89    addKeyListener(new KeyAdapter()\r
90    {\r
91      public void keyPressed(KeyEvent evt)\r
92      {\r
93        switch(evt.getKeyCode())\r
94        {\r
95          case  27: // escape key\r
96            av.setSelectionGroup(null);\r
97            RefreshPanels();\r
98            break;\r
99          case KeyEvent.VK_X:\r
100            if(evt.isControlDown())\r
101            alignFrame.cut_actionPerformed(null);\r
102            break;\r
103          case KeyEvent.VK_C:\r
104          if(evt.isControlDown())\r
105            alignFrame.copy_actionPerformed(null);\r
106            break;\r
107          case KeyEvent.VK_V:\r
108           if(evt.isControlDown())\r
109            alignFrame.paste(true);\r
110            break;\r
111          case KeyEvent.VK_A:\r
112          if(evt.isControlDown())\r
113            alignFrame.selectAllSequenceMenuItem_actionPerformed(null);\r
114            break;\r
115         case KeyEvent.VK_DOWN:\r
116           alignFrame.moveSelectedSequences(false);\r
117           break;\r
118         case KeyEvent.VK_UP:\r
119           alignFrame.moveSelectedSequences(true);\r
120           break;\r
121         case KeyEvent.VK_F:\r
122          if(evt.isControlDown())\r
123           alignFrame.findMenuItem_actionPerformed(null);\r
124           break;\r
125        }\r
126      }\r
127    });\r
128   }\r
129 \r
130   Dimension calculateIdWidth()\r
131   {\r
132     Graphics g = this.getGraphics();\r
133     if(g==null)\r
134     {\r
135       javax.swing.JFrame f = new javax.swing.JFrame();\r
136       f.addNotify();\r
137       g = f.getGraphics();\r
138     }\r
139 \r
140     FontMetrics fm = g.getFontMetrics(av.font);\r
141     AlignmentI al = av.getAlignment();\r
142 \r
143        int i   = 0;\r
144        int idWidth = 0;\r
145        String id;\r
146        while (i < al.getHeight() && al.getSequenceAt(i) != null)\r
147        {\r
148          SequenceI s   = al.getSequenceAt(i);\r
149          if(av.getShowFullId())\r
150            id   = s.getDisplayId();\r
151          else\r
152            id = s.getName();\r
153 \r
154          if (fm.stringWidth(id) > idWidth)\r
155            idWidth = fm.stringWidth(id);\r
156          i++;\r
157        }\r
158 \r
159        // Also check annotation label widths\r
160        i=0;\r
161        if(al.getAlignmentAnnotation()!=null)\r
162        {\r
163          fm = g.getFontMetrics(alabels.getFont());\r
164          while (i < al.getAlignmentAnnotation().length)\r
165          {\r
166            String label = al.getAlignmentAnnotation()[i].label;\r
167            if (fm.stringWidth(label) > idWidth)\r
168              idWidth = fm.stringWidth(label);\r
169            i++;\r
170          }\r
171        }\r
172 \r
173        return new Dimension(idWidth, 12);\r
174   }\r
175 \r
176 \r
177  public void highlightSearchResults(int [] results)\r
178  {\r
179    seqPanel.seqCanvas.highlightSearchResults( results );\r
180 \r
181    // do we need to scroll the panel?\r
182    if(results!=null && (av.getStartSeq()>results[0]\r
183                         || av.getEndSeq()<results[0]\r
184                         || av.getStartRes()>results[1]\r
185                         || av.getEndRes()<results[2]))\r
186        setScrollValues(results[1], results[0]);\r
187 \r
188 \r
189  }\r
190 \r
191 \r
192  public OverviewPanel getOverviewPanel()\r
193  {\r
194    return overviewPanel;\r
195  }\r
196 \r
197  public void setOverviewPanel(OverviewPanel op)\r
198  {\r
199    overviewPanel = op;\r
200  }\r
201 \r
202 \r
203   public void setAnnotationVisible(boolean b)\r
204   {\r
205     annotationSpaceFillerHolder.setVisible(b);\r
206     annotationScroller.setVisible(b);\r
207     javax.swing.SwingUtilities.invokeLater(new Runnable()\r
208      {\r
209        public void run()\r
210        {\r
211          RefreshPanels();\r
212        }\r
213     });\r
214 \r
215   }\r
216 \r
217 \r
218   public void setWrapAlignment(boolean wrap)\r
219   {\r
220     scalePanelHolder.setVisible(!wrap);\r
221     hscroll.setVisible(!wrap);\r
222     idwidthAdjuster.setVisible(!wrap);\r
223 \r
224     av.setShowAnnotation(!wrap);\r
225     annotationScroller.setVisible(!wrap);\r
226     annotationSpaceFillerHolder.setVisible(!wrap);\r
227     idSpaceFillerPanel1.setVisible(!wrap);\r
228 \r
229     RefreshPanels();\r
230 \r
231   }\r
232 \r
233 \r
234   public void setColourScheme()\r
235   {\r
236     ColourSchemeI cs = av.getGlobalColourScheme();\r
237 \r
238     if(av.getConservationSelected())\r
239     {\r
240 \r
241        Alignment al = (Alignment)av.getAlignment();\r
242        Conservation c = new Conservation("All",\r
243                             ResidueProperties.propHash, 3, al.getSequences(), 0,\r
244                             al.getWidth() );\r
245 \r
246        c.calculate();\r
247        c.verdict(false, 100);\r
248        ConservationColourScheme ccs = new ConservationColourScheme(c, cs);\r
249 \r
250        av.setGlobalColourScheme( ccs );\r
251 \r
252     }\r
253 \r
254     RefreshPanels();\r
255   }\r
256 \r
257 \r
258   public void RefreshPanels()\r
259   {\r
260     requestFocus();\r
261     invalidate();\r
262 \r
263     Dimension d = idPanel.idCanvas.getPreferredSize();\r
264     idPanelHolder.setPreferredSize(d);\r
265     hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));\r
266 \r
267     if (av.getWrapAlignment())\r
268     {\r
269       int max = av.alignment.getWidth() /\r
270           (seqPanel.seqCanvas.getWidth() / av.charWidth) + 1;\r
271       vscroll.setValues(0, 1, 0, max);\r
272     }\r
273     else\r
274     {\r
275       if (overviewPanel != null)\r
276         overviewPanel.updateOverviewImage();\r
277       setScrollValues(av.getStartRes(), av.getStartSeq());\r
278     }\r
279 \r
280     validate();\r
281     repaint();\r
282   }\r
283 \r
284   int hextent = 0;\r
285   int vextent = 0;\r
286 \r
287   // return value is true if the scroll is valid\r
288   public boolean scrollUp(boolean up)\r
289   {\r
290     if(up)\r
291     {\r
292       if(vscroll.getValue()<1)\r
293         return false;\r
294       fastPaint  = false;\r
295       vscroll.setValue(vscroll.getValue() - 1);\r
296     }\r
297     else\r
298     {\r
299      if(vextent+vscroll.getValue() >= av.getAlignment().getHeight())\r
300        return false;\r
301       fastPaint  = false;\r
302       vscroll.setValue(vscroll.getValue() + 1);\r
303     }\r
304     fastPaint = true;\r
305     return true;\r
306   }\r
307 \r
308   public boolean scrollRight(boolean right)\r
309   {\r
310 \r
311     if (right)\r
312     {\r
313       if (hscroll.getValue() < 1)\r
314         return false;\r
315       fastPaint = false;\r
316       hscroll.setValue(hscroll.getValue() - 1);\r
317     }\r
318     else\r
319     {\r
320       if (hextent + hscroll.getValue() >= av.getAlignment().getWidth())\r
321         return false;\r
322       fastPaint = false;\r
323       hscroll.setValue(hscroll.getValue() + 1);\r
324     }\r
325     fastPaint = true;\r
326     return true;\r
327   }\r
328 \r
329 \r
330   public void setScrollValues(int x, int y)\r
331   {\r
332     hextent = seqPanel.seqCanvas.getWidth()/av.charWidth;\r
333     vextent = seqPanel.seqCanvas.getHeight()/av.charHeight;\r
334 \r
335     if(hextent > av.alignment.getWidth())\r
336       hextent = av.alignment.getWidth();\r
337     if(vextent > av.alignment.getHeight())\r
338       vextent = av.alignment.getHeight();\r
339 \r
340     if(hextent+x  >  av.getAlignment().getWidth())\r
341       x =  av.getAlignment().getWidth()- hextent;\r
342 \r
343     if(vextent+y > av.getAlignment().getHeight())\r
344       y = av.getAlignment().getHeight() - vextent;\r
345 \r
346     if(y<0)\r
347       y = 0;\r
348 \r
349     if(x<0)\r
350       x=0;\r
351 \r
352     hscroll.setValues(x,hextent,0,av.getAlignment().getWidth());\r
353     vscroll.setValues(y,vextent,0,av.getAlignment().getHeight() );\r
354 \r
355   }\r
356 \r
357 \r
358   public void adjustmentValueChanged(AdjustmentEvent evt)\r
359   {\r
360     int oldX = av.getStartRes();\r
361     int oldY = av.getStartSeq();\r
362 \r
363     if (evt.getSource() == hscroll)\r
364     {\r
365       int x = hscroll.getValue();\r
366       av.setStartRes(x);\r
367       av.setEndRes(x + seqPanel.seqCanvas.getWidth()/av.getCharWidth()-1);\r
368     }\r
369 \r
370     if (evt.getSource() == vscroll)\r
371     {\r
372       int offy = vscroll.getValue();\r
373       if (av.getWrapAlignment())\r
374       {\r
375         av.setStartRes( vscroll.getValue() * av.getChunkWidth());\r
376       }\r
377       else\r
378       {\r
379         av.setStartSeq(offy);\r
380         av.setEndSeq(offy + seqPanel.seqCanvas.getHeight() / av.getCharHeight());\r
381       }\r
382     }\r
383 \r
384 \r
385     if(overviewPanel!=null)\r
386       overviewPanel.setBoxPosition();\r
387 \r
388     if(av.getWrapAlignment() || !fastPaint)\r
389       repaint();\r
390     else\r
391     {\r
392       seqPanel.seqCanvas.fastPaint(av.getStartRes() - oldX,\r
393                                    av.getStartSeq() - oldY);\r
394       idPanel.idCanvas.fastPaint(av.getStartSeq() - oldY);\r
395       scalePanel.repaint();\r
396       if (av.getShowAnnotation())\r
397         annotationPanel.fastPaint(av.getStartRes() - oldX);\r
398     }\r
399 \r
400   }\r
401 \r
402   public int print(Graphics pg, PageFormat pf, int pi) throws PrinterException\r
403   {\r
404     pg.translate((int)pf.getImageableX(), (int)pf.getImageableY());\r
405 \r
406     int pwidth = (int) pf.getImageableWidth();\r
407     int pheight = (int) pf.getImageableHeight();\r
408 \r
409     if (av.getWrapAlignment())\r
410       return printWrappedAlignment(pg, pwidth,pheight, pi);\r
411     else\r
412       return printUnwrapped(pg,pwidth, pheight,pi);\r
413   }\r
414 \r
415   public int printUnwrapped(Graphics pg, int pwidth, int pheight, int pi) throws PrinterException\r
416   {\r
417 \r
418     int idWidth = calculateIdWidth().width + 4;\r
419 \r
420 \r
421     pg.setColor(Color.white);\r
422     pg.fillRect(0,0,pwidth, pheight);\r
423     pg.setFont( av.getFont() );\r
424 \r
425     ////////////////////////////////////\r
426     /// How many sequences and residues can we fit on a printable page?\r
427     int totalRes = (pwidth - idWidth)/av.getCharWidth();\r
428     int totalSeq = (int)((pheight - 30)/av.getCharHeight())-1;\r
429     int pagesWide = av.getAlignment().getWidth() / totalRes +1;\r
430     int pagesHigh = av.getAlignment().getHeight() / totalSeq +1;\r
431 \r
432     if (pi >= pagesWide*pagesHigh)\r
433      return Printable.NO_SUCH_PAGE;\r
434 \r
435     /////////////////////////////\r
436     /// Only print these sequences and residues on this page\r
437     int startRes, endRes, startSeq, endSeq;\r
438     startRes = (pi % pagesWide) * totalRes;\r
439     endRes = startRes + totalRes-1;\r
440     if(endRes>av.getAlignment().getWidth())\r
441       endRes = av.getAlignment().getWidth();\r
442 \r
443      startSeq = (pi / pagesWide) * totalSeq;\r
444      endSeq = startSeq + totalSeq;\r
445      if(endSeq > av.getAlignment().getHeight())\r
446        endSeq = av.getAlignment().getHeight();\r
447 \r
448 \r
449     ////////////////\r
450     //draw Scale\r
451     pg.translate(idWidth,0);\r
452     scalePanel.drawScale(pg, startRes, endRes, pwidth-idWidth);\r
453 \r
454     pg.translate(-idWidth, 30);\r
455     ////////////////\r
456     // Draw the ids\r
457     Color currentColor=null;\r
458     Color currentTextColor=null;\r
459     for(int i=startSeq; i<endSeq; i++)\r
460     {\r
461       if (av.getSelectionGroup()!=null && av.getSelectionGroup().sequences.contains(av.getAlignment().getSequenceAt(i)))\r
462       {\r
463         currentColor = Color.gray;\r
464         currentTextColor = Color.black;\r
465       }\r
466       else\r
467       {\r
468         currentColor = av.getAlignment().getSequenceAt(i).getColor();\r
469         currentTextColor = Color.black;\r
470       }\r
471 \r
472       pg.setColor(currentColor);\r
473       pg.fillRect(0,  jalview.analysis.AlignmentUtil.getPixelHeight(startSeq, i, av.getCharHeight()),\r
474                               idWidth,\r
475                               av.getCharHeight());\r
476 \r
477       pg.setColor(currentTextColor);\r
478 \r
479       String string = av.getAlignment().getSequenceAt(i).getName();\r
480       if(av.getShowFullId())\r
481         string = av.getAlignment().getSequenceAt(i).getDisplayId();\r
482 \r
483       pg.drawString(string, 0,  jalview.analysis.AlignmentUtil.getPixelHeight\r
484                     (startSeq, i, av.getCharHeight()) + av.getCharHeight() - (av.getCharHeight() / 5));\r
485     }\r
486 \r
487     // draw main sequence panel\r
488     pg.translate(idWidth,0);\r
489     seqPanel.seqCanvas.drawPanel(pg,startRes,endRes,startSeq,endSeq,startRes,startSeq,0);\r
490 \r
491 \r
492     if(av.getShowAnnotation())\r
493       {\r
494         pg.translate(-idWidth,(endSeq-startSeq)*av.charHeight);\r
495         alabels.drawComponent((Graphics2D)pg);\r
496         pg.translate(idWidth,0);\r
497         annotationPanel.drawComponent((Graphics2D) pg, startRes, endRes+1);\r
498       }\r
499 \r
500     return Printable.PAGE_EXISTS;\r
501   }\r
502 \r
503 \r
504   public int printWrappedAlignment(Graphics pg, int pwidth, int pheight, int pi) throws PrinterException\r
505   {\r
506 \r
507     int idWidth = calculateIdWidth().width+4;\r
508 \r
509     if( seqPanel.seqCanvas.getWidth() < pwidth-idWidth)\r
510       pwidth = seqPanel.seqCanvas.getWidth() + idWidth;\r
511 \r
512 \r
513     pg.setColor(Color.white);\r
514     pg.fillRect(0,0,pwidth, pheight);\r
515     pg.setFont( av.getFont() );\r
516 \r
517     ////////////////////////////////////\r
518     /// How many sequences and residues can we fit on a printable page?\r
519     AlignmentI da = av.alignment;\r
520     int endy   = da.getHeight();\r
521     int chunkHeight =  (da.getHeight() + 2)*av.charHeight;\r
522     int chunkWidth  =   (pwidth-idWidth)/av.charWidth;\r
523 \r
524     int noChunksOnPage = pheight / chunkHeight;\r
525     int totalChunks = da.getWidth() / chunkWidth;\r
526 \r
527     if ( pi*noChunksOnPage > totalChunks )\r
528      return Printable.NO_SUCH_PAGE;\r
529 \r
530     ////////////////\r
531     // Draw the ids\r
532     pg.setClip(0,0,pwidth, noChunksOnPage*chunkHeight);\r
533 \r
534     int row = pi*noChunksOnPage;\r
535     pg.setColor(Color.black);\r
536     for(int ypos=2*av.charHeight;\r
537         ypos <= pheight && row*chunkWidth<da.getWidth();\r
538         ypos += chunkHeight, row++ )\r
539     {\r
540       for (int i = 0; i < endy; i++)\r
541       {\r
542         SequenceI s = da.getSequenceAt(i);\r
543         String string = s.getName();\r
544         if (av.getShowFullId())\r
545           string = s.getDisplayId();\r
546 \r
547         pg.drawString(string, 0,\r
548                       AlignmentUtil.getPixelHeight(0, i, av.charHeight) + ypos +\r
549                       av.charHeight - (av.charHeight / 5));\r
550       }\r
551     }\r
552 \r
553     // draw main sequence panel\r
554     pg.translate(idWidth,0);\r
555     seqPanel.seqCanvas.drawWrappedPanel(pg, pwidth-idWidth, pheight, pi*noChunksOnPage*chunkWidth);\r
556 \r
557 \r
558     return Printable.PAGE_EXISTS;\r
559 \r
560   }\r
561 \r
562 \r
563   public void makeEPS()\r
564   {\r
565     int height = (av.alignment.getWidth() / av.getChunkWidth() +1) * av.chunkHeight;\r
566     int width = seqPanel.getWidth() + idPanel.getWidth();\r
567 \r
568     if (!av.getWrapAlignment())\r
569     {\r
570       height = (av.alignment.getHeight()+1) * av.charHeight + 30;\r
571       width = idPanel.getWidth() + av.alignment.getWidth() * av.charWidth;\r
572     }\r
573     if(av.getShowAnnotation())\r
574    {\r
575      height += annotationPanel.getPreferredSize().height;\r
576    }\r
577 \r
578     try\r
579     {\r
580       jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(\r
581           "LAST_DIRECTORY"), new String[]{"eps"}, "Encapsulated Postscript");\r
582       chooser.setFileView(new jalview.io.JalviewFileView());\r
583       chooser.setDialogTitle("Create EPS file from alignment");\r
584       chooser.setToolTipText("Save");\r
585 \r
586       int value = chooser.showSaveDialog(this);\r
587       if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
588         return;\r
589 \r
590       jalview.bin.Cache.setProperty("LAST_DIRECTORY",chooser.getSelectedFile().getPath());\r
591       FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());\r
592       EpsGraphics2D pg = new EpsGraphics2D("Example", out, 0, 0, width, height);\r
593 \r
594         if (av.getWrapAlignment())\r
595           printWrappedAlignment(pg, width, height, 0);\r
596         else\r
597           printUnwrapped(pg, width, height, 0);\r
598 \r
599 \r
600         pg.flush();\r
601         pg.close();\r
602     }\r
603     catch (Exception ex)\r
604     {\r
605       ex.printStackTrace();\r
606     }\r
607   }\r
608 \r
609   public void makePNG()\r
610   {\r
611       int height = (av.alignment.getWidth() / av.getChunkWidth() +1) * av.chunkHeight;\r
612       int width = seqPanel.getWidth() + idPanel.getWidth();\r
613 \r
614       if (!av.getWrapAlignment())\r
615       {\r
616         height = (av.alignment.getHeight()+1) * av.charHeight + 30;\r
617         width = idPanel.getWidth() + av.alignment.getWidth() * av.charWidth;\r
618       }\r
619 \r
620       if(av.getShowAnnotation())\r
621       {\r
622         height += annotationPanel.getPreferredSize().height;\r
623       }\r
624 \r
625 \r
626 System.out.println(width +" "+height);\r
627 \r
628     try\r
629     {\r
630       jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(\r
631           "LAST_DIRECTORY"), new String[]{"png"}, "Portable network graphics");\r
632       chooser.setFileView(new jalview.io.JalviewFileView());\r
633       chooser.setDialogTitle("Create EPS file from alignment");\r
634       chooser.setToolTipText("Save");\r
635 \r
636       int value = chooser.showSaveDialog(this);\r
637       if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
638         return;\r
639 \r
640       jalview.bin.Cache.setProperty("LAST_DIRECTORY",chooser.getSelectedFile().getPath());\r
641       FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());\r
642 \r
643       BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);\r
644       Graphics png = bi.getGraphics();\r
645 \r
646 \r
647         if (av.getWrapAlignment())\r
648           printWrappedAlignment(png, width, height, 0);\r
649         else\r
650           printUnwrapped(png, width, height, 0);\r
651 \r
652         ImageIO.write(bi, "png", out);\r
653         out.close();\r
654     }\r
655     catch (Exception ex)\r
656     {\r
657       ex.printStackTrace();\r
658     }\r
659   }\r
660 \r
661 }\r
662 \r
663 \r
664 \r
665 \r