采用双缓冲区技术的动态图像显示处理
3 采用双缓冲区技术的动态图像显示处理
李苏文 工程师
()第七二三研究所
摘 要 : 本文介 绍 采 用 双 缓 冲 区 技 术 来 消 除 动 态 图 像 显 示 过 程 中 的 图 像 闪 烁 问 题 , 并 用 I2
AVADRAW 开发工具进行具体的实现 。
关键词 : J ava 线程 图像处理 双缓冲区技术 IAVADRAW 开发工具
1 概述
电影或电视 ,它们通过每秒显示 30 帧左右的图像 ,利用人眼的暂停效应 ,产生一个连贯的动作显示过程 。对跟踪的目标如飞机 、轮船 、卫星进行采集的数据经过处理 、计算生成一幅幅静止的图 形 ,经过编程 ,也可产生一个连贯的动作显示过程 。这些都是典型的动态图像显示处理 。
动态图像显示处理的典型伪码格式是 :
() while moreFrameToPaint
() { paint CurrentFrame ;
Sleep for some time ;
() AdvanceToNextFrame ;
}
这是一个不断绘制图形的循环 ,它是动态图像显示处理程序的运行框架 ,它按照定量的时间间 隔一帧一帧地绘制图像 。
帧速率对于动态图像显示处理的感观效果起决定性作用 ,如果太慢 ,会使处理的图像看起来闪烁 ,如果太快 ,将看不到帧之间的变迁 ,只能看到最后一帧图像 ,因而 ,在显示相连的图像帧之间需 要有空白时间 ,这就是在上面的伪码中为何需要“Sleep for some time”。
( 图像帧能以多快的速度在屏幕上被刷新将限制帧速率的大小 。用普通的方法显示图像帧 如
) 用向量存储的动态处理的图像,由于绘制速度慢 ,常会引起屏幕闪烁 。本文采用双缓冲区技术 ,能 提高图像帧的显示速度 。双缓冲区技术就是把图像的当前帧放到前台图形缓冲区 ,在屏幕上显示 ;
() 同时在后台图形缓冲区中完成对下一帧图像的绘制 这一帧用户是看不见的。当需要显示下一帧 图像时 ,切换前后台图形缓冲区 ,把后台图形缓冲区中的内容显示在屏幕上 ,再在前台图形缓冲区 绘制下一帧图像 ,就可以减少动态图像显示处理的屏幕闪烁 。
2 动态图像显示处理的基础及闪烁的原因
() () 对于小应用程序 applet和大多数应用程序 application而言 ,需要一个单独的线程运行动态图3 收稿日期 :1999 - 10 - 17 。
《舰船科学技术》2000 . 4— 49 —
() () 像显示处理循环 。动态图像显示处理循环不能处于成员函数 paint 或 update 中 。因为这样会占
据主要的 AWT 线程 ,而该线程负责管理所有的绘制和事件处理 。
() 1实现多任务的 J ava 的线程
一个 J ava 线程就是执行时不会垄断计算机的一段程序 。比如我们要显示内有一个 applet 的某 页面 。该 applet 执行一个动态图像显示处理线程 。当执行动态图像显示处理线程时 ,用户能用鼠 标执行其它任务 ,换句话说 ,创建一个动态图像显示处理线程 ,动态图像显示处理就不会垄断计算 机的资源 ,计算机还能“同时”处理其他任务 ,这是 J ava 线程的优点 。
() 2动态图像显示处理的基础
动态图像显示处理的 J ava 线程中 ,完成以下循环的工作 :
) 1将当前帧数加一
) () 2调用成员函数 repaint ,要求显示图像的当前帧
) 3休眠一段时间 ,使帧之间的延迟为 :
() () delay = fp s > 0? 1000/ fp s:100 ;
上式是将每秒播放的帧数转换为帧之间间隔的毫秒数 。
在动态图像显示处理循环中 ,每播放一帧图像就休眠 delay 毫秒 ,这有可能导致休眠太长的时 间 ,因为在执行此循环时你失去了很少的时间 。为了解决这个问题 ,需要记住此循环开始的时间 , 然后计算实际需要休眠的毫秒数 ,从而确保匀速地播放每一帧图像 。
() long startTime = System. currentTimeMillis ;
3 3 () while / 图像显示处理循环仍在运行 / {
. . . . . . ?图像帧数加一 ,显示当前帧
try{
startTime + = delay ; ?获得播放下一帧图像的时间
?startTime 减去当前时间 ,这就是实际需要休眠的时间
((() ) ) Thread. sleep Math. max 0 ,startTime - System. currentTimeMillis ;
}
( ) catch InterruptedException e{
break ;
}
}
() 3动态图像显示闪烁的因素
) 1在连续帧图像之间运动和颜色不连续时就会发生动态图像显示的闪烁 。用 J ava 语言
( ) 设计处理动态图像显示时发生闪烁的几个原因是 : 在省缺的情况下 ,在实现成员函数 paint 被调
( ) 用之前动画的背景被清除 ,整个绘制区域使用背景色重绘 。通过置换成员函数 Update ,使组件在 被重画之前 ,其整个背景不被清除 ,这样因背景色被清除而使动态图像显示处理的闪烁就不存在
了 。
) () 2成员函数 paint 的一次执行时间大于屏幕的一次刷新时间 ,这导致了一帧图形的一 部分在一个刷新周期完成 ,另一部分在下一个或几个刷新周期 。这样在视觉上造成了一种不连贯 的感觉 ,即“爬行”现象 。
— 50 —《舰船科学技术》2000 . 4
3 一种新的处理技术
上节分析了动态图像显示中闪烁的主要几个因素 ,为了消除这些因素 ,采用双缓冲区技术 ,以
提高处理速度 ,消除动态图像显示处理中的“爬行”。 () 1双缓冲区技术的设置及实现
图 1 是为了用 AWT 创建一个后台图
形缓冲区 的 框 图 。先 创 建 一 个 具 有 适 当
尺寸的 Image 对象 , 然后创建一个图形上
下文来管理 Image 对象 , 下面的代码显示
了如何创建图形上下文 。
. . . . . . ?实例变量说明
Dimension offDimension ;
Image off Image ;
Graphics off Graphics ;
. . . . . .
3 ( ) / 在 Update 成员函数中 , d 保存有
3 绘画区域的大小 /
( () ( If off Graphics = = null ?d. width ! )= offDimension. width 图 1( ? d. height ! = offDimension. ) ) height{
offDimension = d ;
( ) off Image = create Image d. width ,d. height;
() off Graphics = off Image . get Graphics ;
}
( ) 在下面的代码段中 ,是新的成员函数 update ,其中包含有关的新的图画代码 ,所有的图画代
码都是针对后台图形缓冲区 :
( ) public void update Graphics g{
. . . ?首先 ,初始化变量并产生后台图形缓冲区
?抹去先前图像
(() ) off Graphics. setColor getBackground ;
() off Graphics. fillRect 0 ,0 ,d. width ,d. height;
( ) off Graphics. setColor Color . black;
()() . . . ?和老的成员函数 paint 一样的代码 取至画矩形框
() if fillSquare{
() off Graphics. fillRect x ,y ,w ,h;
fillSquare = false ;
}else{
fillSquare = true ;
}
《舰船科学技术》2000 . 4 — 51 —
。。。 ?在屏幕上画出图像
() g. drawImage off Image ,0 ,0 ,this;
}
( ) 在上面的代码中 ,我们是在成员函数 update 中完成缓冲区的设置的 。由于在后台缓冲区与
前台缓冲区中分别独立绘制好了图像 ,且交替在屏幕上显示 ,避免了一幅图像在一个周期以上时间
内绘制 ,所以就看不到图像的闪烁了 。
() 2双缓冲区图像显示处理的源程序
3 import java . awt . ;
3 import java . applet . ;
public class MTImage extends Applet implements Runnable{
int frameNumber ;
int delay ; Thread animation Thread ;
Dimension offDimenssion ;
Image off Image ;
Graphics off Graphics ;
Image images;
MediaTracker tracker ;
() public void init {
( () ) setBackground new java . awt . Color 0 ,255 ,0;
() setSize 450 ,300;
String str ;
() str = getParameter ”fp s”;
( ) ( ) int fp s = str ! = null? Integer . parse Int str;10 ;
() () delay = fp s > 0? 1000/ fp s:100 ;
images = new Image 11 ;
() tracker = new MediaTracker this;
() for int i = 1 ;i < = 11 ;i + + {
(() ) imagesi - 1 = get Image getCodeBase ,″li″+ i + ″. gif″;
() tracker . addImage imagesi - 1 ,0 ;
}
}
() public void start {
() if animationThread = = null
{ animationThread = new Thread
() () this; animationThread. start ;
}
}
() public void stop
{ animationThread =
null ; off Image = null ;
— 52 — 《舰船科学技术》2000 . 4
off Graphics = null ;
}
( ) public boolean mouseDown Event e ,int x ,int y{ () if animationThread = = null{
() start ;
}
else{
animationThread = null ;
}
return false ;
}
() public void run {
() long startTime = System. currentTimeMillis ;
( () ) while Thread. currentThread = = animationThread{
() repaint ;
try{
startTime + = delay ;
((() ) ) Thread. sleep Math. max 0 ,startTime - System. currentTimeMillis ;
}
( ) catch InterruptedException e{
break ;
}
frameNumber + + ;
}
}
( ) public void paint Graphics g{
() if off Image ! = null{
() g. drawImage off Image ,0 ,0 ,this;
}
}
( ) public void update Graphics g}
() Dimension d = size ;
( ( ) ( ) ( = offDimenssion. if off Graphics = = null ? d. width != offDimenssion. width ? d. height !
) ) height{
offDimenssion = d ;
( ) off Image = create Image d. width ,d. height;
() off Graphics = off Image . get Graphics ; }
(() ) off Graphics. setColor getBackground ;
() off Graphics. fillRect 0 ,0 ,d. width ,d. height;
《舰船科学技术》2000 . 4 — 53 —
( ) off Graphics. setColor Color . black;
(() ) if tracker . statusID 0 ,true= = MediaTracker . COMPL ETE{
() off Graphics. drawImage imagesframeNumber %14 ,0 ,0 ,this ;
}
() g. drawImage off Image ,0 ,0 ,this;
}
这是把 li . gif 到 li10 . gif 十幅静止的图像处理成连续动态显示的程序 。
4 lavadraw 开发工具对上面程序的演示
() 1GIF 文件
储存图形文件有许多格式 ,包括 BMP ,PCX , PICT ,J PEG 和 GIF 。J ava 可以显示以 GIF 文件存储 的图像 。把需要动态图像显示处理的一幅幅 li1 . gif . 至 li10 . gif 格式图像存入 lavadraw/ Output 中 。
() 2用 lavadraw 工具对动态图像显示处理的实现
打开 lavadraw 开发工具 ,在 project 中新建一个 MTImage . class 。在写字板上写入上面的动态图 像显示处 理 源 程 序 。在 Option/ Compiler 中 进 行 编 译 , 直 到 确 定 没 有 错 误 后 , 就 可 以 执 行 Applet
Viewer ,看到运行的动态图像显示了 。
结5 小
把一幅幅静止的 ,分立的 ,看起来相近的图像处理成连续的动态显示的图像 ,像“电视”效果似的 ,在生活中或在国防建设中都具有重要的意义 。本文通过采用双缓冲区技术的应用 ,把十幅跟踪 的目标的静止的图像处理成动态图像显示 ,产生一种“跟踪的目标实际运动”的效果 。
参 考 文 献
1 [ 美 Nathan Gurewich Ori Gurewich 著《J ava 样本手册》. 电子工业出版社 .
2 [ 美 Patrick Chan ,Rosanna Lee 著《J ava 类库手册》. 北京大学出版社 .
3 [ 美 H. M. Deitel 等著《J ava 语言程序设计大全》. 机械工业出版社
作者简介 :李苏文 ,工程师 ,1966 年 9 月出生 。1988 年毕业于哈尔滨工业大学电气测量技术及仪器专业 ,学士学位 ,从事船用电子仪器仪
研究工作 。
— 54 —《舰船科学技术》2000 . 4