举例解析Java的图像缓冲技术的使用
当图像信息量较大,采用以上直接显示的方法,可能前面一部分显示后,显示后面一部分时,由于后面一部分还未从文件读出,使显示呈斑驳现象。为了提高显示效果,许多应用程序都采用图像缓冲技术,即先把图像完整装入内存,在缓冲区中绘制图像或图形,然后将缓冲区中绘制好的图像或图形一次性输出在屏幕上。缓冲技术不仅可以解决闪烁问题,并且由于在计算机内存中创建图像,程序可以对图像进行像素级处理,完成复杂的图像变换后再显示。
【例】小应用程序程序演示图像缓冲显示技术。程序运行时,当鼠标在图像区域内按下时,图像会出现边框,托动鼠标时,图像也随之移动。抬起鼠标后,边框消失。程序将两种状态的图像先放入两个缓冲区,当鼠标拖动时,不断地在新的位置重绘鼠标按下样式的图像鼠标抬起时,重绘鼠标抬起样式的图像。
importjava.applet.*; importjava.awt.*; imprtjava.awt.image.*; importjavax.swing.*; importjava.event.*; publicclassExample7_6extendsApplet{ ImagemyPicture; /*init()方法中,先定义一个Image对象,并赋予createImage()方法的返回值,接着创建Graphics对象并赋予其图形环境。最后,让Graphics对象调用drawImage()方法显示图像。 由于这里的Graphics对象offScreenGc是非屏幕对象是,小程序窗口不会有图像显示*/ publicvoidinit(){ myPicture=getImage(getCodeBase(),"myPic.JPG"); ImageoffScreenImage=createImage(size().width,size().height); GraphicsoffScreenGc=offScreenImage.getGraphics(); newBufferedDemo(myPicture); } /*drawImage()方法的第四个参数是实现ImageObserver接口,在init()方法中,调用drawImage()方法的参数是this,所以小程序要定义imageUpdate()方法*/ publicbooleanimageUpdate(Imageimg,intinfoFlg,intx,inty,intw,inth){ if(infoFlg=ALLBITS){//表示图像已全部装入内存 repaint(); returnfalse;//防止线程再次调用imageUpdate()方法 } else returntrue; } } /*程序的执行过程是,当小程序调用drawImage()方法时,drawImage()方法将创建一个调用imageUpdate()方法的线程,在imageUpdate()方法中,测定图像是否已在部分调入内存。创建的线程不断调用imageUpdate()方法,直到该方法返回false为止。参数infoFlg使小程序能知道图像装入内存的情况。当infoFlg等于ALLBITS时,表示图像已全部装入内存。当该方法发现图像已全部装入内存后,置imageLoaded为真,并调用repaint()方法重画小程序窗口。方法返回false防止线程再次调用imageUpdate()方法。*/ classBufferedDemoextendsJFrame{ publicBufferedDemo(Imageimg){ this.getContentPane().add(newPicPanel(img)); setTile("双缓技术演示"); setSize(300,300); setVisible(true); } } classPicPaneextendsJPanelimplementsMouseListener,MouseMotionListener{ intx=0,y=0,dx=0,cy=0; BufferedImagebimg1,bimg2; booleanupstate=true; publicpicPanel(Imageimg){ this.setBackground(Color.white); this.addMouseListener(this); this.addMouseMotionListener(this); bimg1=newBufferedImage(img.getWidth(this),img.getHeight(this), BufferedImage.TYPE_INT_ARGB); bimg2=newBufferedImage(img.getWidth(this),img.getHeight(this), BufferedImage.TYPE_INT_ARGB); Graphics2Dg2D1=bimg1.createGraphics(); Graphics2Dg2D2=bimg2.createGraphics(); g2D1.drawImage(img,0,0,this); g2D2.drawImage(img,0,0,this); g2D2.drawRect(1,1,img.getWidth(this)-3,img.getHeight(this)-3); } publicvoidpaintComponent(Graphicsg){ super.painComponent(g); Graphics2Dg2D=(Graphics2D)g; if(upState) g2D.drawImage(bimg1,x,y,this); else g2D.drawImage(bimg2.x,y,this); } publicvoidmousePress(MouseEvente){ if(e.getX()>=x&&e.getX()<x+bimg1.getWidth(this)&&e.getY()>=y&&e.getY()<y+bimg1.getHeight(this)){ upstate=false; setCursor(Cursor.getPredefinedCursor(Coursor.HAND_CURSOR)); dx=e.getX()-x; dy=e.getY()-y; repain(); } } publicvoidmouseExited(MouseEvente){} publicvoidmouseClicked(MouseEvente){} publicvoidmouseEntered(MouseEvente){} publicvoidMouseReleased(MouseEvente){ this.setCursor(Cursor.getpredefinedCursor(Cursor.DEFAULT_CURSOR)); upState=true; repaint(); } publicvoidmouseMoved(MouseEvente){} publicvoidmouseDragged(MouseEvente){ if(!upState){ x=e.getX()-dx; y=e.getY()-dy; repaint(); } } }
程序要创建缓冲区图像,需要引入java.awt.image包中的BufferedImage类。要创建一个缓冲区图,可以调用createImage()方法,该方法返回一个Image对象,然后再将它转换成一个BufferedImage对象。例如,代码:
BufferedImagebimage=(BufferedImage)this.createImage(this.getWidth(),this.getHeight());
也可利用以下构造方法来建立。
BufferedImage(intwidth,intheigh,intimageType);
其中参数imageType是图像类型。
使用缓冲区显示图像,需先在缓冲区中准备好图像,再将缓冲区中的图像显示在界面上。显示图像需要图形对象Graphics,可以通过以下方法建立:
Graphics2Dg2d=bimge.createGraphics();