图形与多媒体处理.docx
《图形与多媒体处理.docx》由会员分享,可在线阅读,更多相关《图形与多媒体处理.docx(18页珍藏版)》请在冰豆网上搜索。
![图形与多媒体处理.docx](https://file1.bdocx.com/fileroot1/2023-5/21/3c5cd95d-505c-4c0f-8c32-2ef1fbae4f13/3c5cd95d-505c-4c0f-8c32-2ef1fbae4f131.gif)
图形与多媒体处理
实验七图形与多媒体处理
一.实验目的:
1)熟悉图形、图像的使用方法,
2)理解计算机动画的原理和Java的多线程处理机制,能够编写Applet中使用的动画。
二.实验要求
1)掌握使用图形类Graphics画出不同图形的方法。
2)掌握在容器中输入图像、播放音乐的方法。
3)理解计算机动画原理,掌握图形双缓冲技术,能够设计计算机动画。
4)理解多线程机制,掌握线程的使用方法。
3.实验内容
3.1使用图形类Graphics
在Java中基本图形包括点、线、圆、矩形等,是构成复杂图形的基础。
绘制基本图形要使用AWT包中的Graphics类,它提供了各种基本图形的绘制方法,可以直接引用这些方法画点、线、圆、矩形等。
1.创建在Applet上画出不同的图形的程序
(1)程序功能:
在Applet上使用不同的颜色画出直线、圆、方块、圆弧等图形。
(2)编写LX7_1.java程序文件,源代码如下。
importjava.applet.Applet;
importjava.awt.Graphics;
importjava.awt.Color;
publicclassLX7_1extendsApplet{
publicvoidpaint(Graphicsg){
g.drawLine(10,10,50,10);//画线(确定两点)
g.setColor(Color.red);//设置红颜色
g.drawOval(35,35,100,60);//画椭圆(圆心、宽和高)
g.fillOval(200,15,60,100);//画具有填充色的圆
g.setColor(Color.blue);//设置蓝颜色
g.drawRect(20,130,80,80);//画矩形
g.fillRect(120,130,80,80);//画具有填充色的矩形
g.drawRoundRect(220,130,80,80,20,20);//画圆角矩形
g.fillRoundRect(320,130,80,80,20,20);//画具有填充色的圆角矩形
g.setColor(newColor(255,255,0));//设置黄颜色
g.drawArc(250,20,100,100,0,90);
g.fillArc(380,20,100,100,90,90);
g.fillArc(300,25,100,100,180,90);
g.drawArc(330,25,100,100,0,-90);
}
}
(3)编译程序LX7_1.java。
(4)编写显示LX7_1.class的页面文件,在浏览器中显示结果如图7.1所示
2.创建使用画布对象的Applet应用程序
(1)程序功能:
创建一个带有多边形、圆的自定义画布类,在Applet上显示自定义画布的对象。
(2)编写LX7_2.java程序文件,源代码如下。
importjava.applet.Applet;
importjava.awt.*;
importjava.awt.Color;
publicclassLX7_2extendsApplet{
publicvoidinit(){
Colorcol=newColor(20,55,75);
setBackground(col);//设置Applet的背景色
setForeground(Color.yellow);//设置Applet的前景色
MyCanvas1c=newMyCanvas1();//创建画布对象
c.setBackground(Color.white);//设置画布的背景色
c.setSize(300,200);//设置画布的大小
add(c);
}
}
classMyCanvas1extendsCanvas{
publicvoidpaint(Graphicsg){
g.setColor(Color.red);
g.fillOval(40,20,80,80);//画圆
g.setColor(Color.cyan);//设置青色
intp1X[]={20,20,100,20};//多边形的x坐标
intp1Y[]={20,80,20,20};//多边形的y坐标
intp1=3;//多边形的边数
g.fillPolygon(p1X,p1Y,p1);//画填充多边形
intp2X[]={280,120,50,90,210,280};
intp2Y[]={20,50,100,110,70,20};
intp2=5;
g.drawPolygon(p2X,p2Y,p2);//画多边形
}
}
(3)编译程序LX7_2.java。
(4)编写显示LX7_2.class的页面文件,在浏览器中显示结果如图7.2所示。
3.在Applet上输出不同类型的数据变量
(1)程序功能:
在Applet上设置不同背景色、前景色,并使用不同字体、颜色显示不同类型的数据变量。
(2)编写LX7_3.java程序文件,源代码如下。
importjava.applet.Applet;
importjava.awt.*;
importjava.awt.Color;
publicclassLX7_3extendsApplet{
Strings="这是字符串类数据变量Thisisastring";
charc[]={'这','是','一','个','字','符','数','组'};
byteb[]={97,'','b','y','t','e','',97,114,114,97,121};
publicvoidinit(){
Colorcol=newColor(20,55,75);
setBackground(col);//设置Applet的背景色
setForeground(Color.yellow);//设置Applet的前景色
//repaint();
}
publicvoidpaint(Graphicsg){
g.setFont(newFont("黑体",Font.PLAIN,20));//正常的
g.drawString(s,30,30);//写出字符串
g.setFont(newFont("宋体",Font.BOLD,20));//加粗的
g.setColor(Color.red);//设置青色
g.drawChars(c,0,8,30,60);//写出字符变量
g.setFont(newFont("SansSerif",Font.ITALIC,24));//倾斜的
g.drawBytes(b,0,12,30,90);//写出字节变量
}
}
(3)编译程序LX7_3.java。
(4)编写显示LX7_3.class的页面文件,在浏览器中显示结果如图7.3所示。
3.2插入图像与播放音乐
1.在Applet中插入图像播放音乐
(1)程序功能:
在Applet中插入3种大小的图像,并在打开文件时部分背景音乐。
(2)编写LX7_4.java程序文件,源代码如下。
importjava.awt.*;
importjava.applet.*;
publicclassLX7_4extendsApplet{
Imageimg;
publicvoidinit(){
img=getImage(getCodeBase(),"image/飞机.gif");//获取图像文件地址读取图
像文件到内存
play(getDocumentBase(),"WAV/Sound.wav");//播放声音文件
}
publicvoidpaint(Graphicsg){
intw=img.getWidth(this);
inth=img.getHeight(this);
g.drawImage(img,20,10,this);//画出原图
g.drawImage(img,20,100,w/2,h/2,this);//画出缩小一倍的图
g.drawImage(img,160,0,w*2,h*2,this);//画出放大一倍的图
}
}
(3)编译程序LX7_4.java。
(4)编写显示LX7_4.class的页面文件,在浏览器中显示结果如图7.4所示。
2.随时播放声音文件的程序
(1)程序功能:
在Applet中使用下拉框显示音乐文件的名字,在程序中使用AudioClip类
控制播放的音乐文件,使用“播放”、“连续”、“停止”按钮控制和选择播放音乐的状态。
(2)编写LX7_5.java程序文件,源代码如下。
importjava.awt.*;
importjava.awt.event.*;
importjava.applet.Applet;
importjava.applet.AudioClip;
publicclassLX7_5extendsAppletimplementsItemListener,ActionListener{
AudioClipsound;
Choicec=newChoice();
Buttonplay=newButton("播放");
Buttonloop=newButton("连续");
Buttonstop=newButton("停止");
publicvoidinit(){
c.add("space.au");c.add("flute.aif");c.add("trip.mid");
c.add("jungle.rmf");c.add("Sound.wav");
add(c);c.addItemListener(this);
add(play);add(loop);add(stop);
play.addActionListener(this);
loop.addActionListener(this);
stop.addActionListener(this);
sound=getAudioClip(getCodeBase(),"WAV/Sound.wav");}
publicvoiditemStateChanged(ItemEvente){
sound.stop();
sound=getAudioClip(getCodeBase(),"WAV/"+c.getSelectedItem());
}
publicvoidactionPerformed(ActionEvente){
if(e.getSource()==play)sound.play();
elseif(e.getSource()==loop)sound.loop();
elseif(e.getSource()==stop)sound.stop();}
}
(3)编译程序LX7_5.java。
(4)编写显示LX7_5.class的页面文件,在浏览器中显示结果如图7.5所示。
三.多线程与动画
程序(program)是对数据描述与操作的代码的集合,是应用程序执行的脚本。
进程(process)是程序的一次执行过程,是操作系统运行程序的基本单位。
程序是静态的,进程是动态的。
系统运行一个程序就是一个进程从创建、运行到消亡的过程。
线程是比进程更小的运行单位,是程序中单个顺序的流控制。
一个进程中可以包含多个线程。
线程是一种特殊的多任务方式。
当一个程序执行多线程时,可以运行两个或更多的由同一个程序启动的任务。
这样,一个程序可以使得多个活动任务同时发生。
动画是指连续而平滑地显示多幅图像。
计算机动画原理十分简单,首先在屏幕上显示出第一帧画面,过一会儿把它擦掉,然后再显示下一帧画面,如此循环往复。
由于人的眼睛存在着一个视觉差,所以感觉好像画面中的物体在不断运动。
在计算机上,只要以10~30幅/每秒钟的速度显示图像即可达到满意的动画质量。
1.一个简单的动画程序
(1)程序功能:
在Applet中添加一个“天空”背景图像,然后令一个“飞机”图像从右移
动到左。
(2)编写LX7_6.java程序文件,源代码如下。
importjava.awt.*;
importjava.applet.*;
publicclassLX7_6extendsApplet{
Imagestar,rocket;
intx=0;
publicvoidinit(){
star=getImage(getCodeBase(),"image/天空.JPG");
rocket=getImage(getCodeBase(),"image/飞机.gif");
}
publicvoidpaint(Graphicsg){
g.drawImage(star,0,0,this);
g.drawImage(rocket,310-x,10,this);
try{
Thread.sleep(50);
x+=5;
if(x==310){
x=0;
Thread.sleep(1000);
}
}catch(InterruptedExceptione){}
repaint();
}
}
(3)编译程序LX7_6.java。
(4)编写显示LX7_6.class的页面文件,在浏览器中显示结果如图7.6所示。
(5)程序分析:
程序中创建了两个Image对象t1和t2,在init方法中分别加载了两个图像文件。
使用变量x用来改变“飞机”图像画出的位置(310-x,10),因为x的值是不断变化的,所以看起来图像在移动。
真正使“飞机”图像实现动画效果的代码在try…catch块中。
程序调用了Thread类的sleep方法(因为Thread类属于Java.lang包的类,其sleep静态类方法可直接调用),因为sleep方法会产生中断异常,所以必须放在try…catch块中。
如果不使用sleep方法,程序将全速运行,必将导致换帧速度太快,画面闪烁严重(你可以自己去掉sleep方法试一试)。
休眠时间设定为50毫秒,相当于换帧速度每秒20(1000/50)。
休眠结束后x的值加5,意味着下一帧跳伞画面的显示位置向左移动5个像素点。
当跳伞移动到最右边即310点位置时,将x赋值0,跳伞重新回到了起点。
程序中paint方法的最后一条语句是调用repaint()方法,repaint方法的功能是重画图像,它先调用update方法将显示区清空,再调用paint方法画出图像。
它们形成一个循环,paint调用repaint,repaint调用paint,使“飞机”图像不间断地反复画出,人看到的是图像在移动。
但运行这个Applet时,画面有闪烁现象。
一般来说,画面越大,update以背景色清除显示区所占用的时间就越长,不可避免地会产生闪烁。
如何解决这个问题呢?
2.使用双缓冲创建动画的程序
(1)程序功能:
使用双缓冲来建立动画的效果,清除闪烁的现象。
(2)编写LX7_7.java程序文件,源代码如下。
importjava.awt.*;
importjava.applet.*;
publicclassLX7_7extendsApplet{
Imagebuffer,img,star;
Graphicsg1;
Threadtd;
intx=0;
publicvoidinit(){
buffer=createImage(getWidth(),getHeight());//创建图像缓冲区
g1=buffer.getGraphics();//创建绘图区
img=getImage(getCodeBase(),"image/飞机.gif");
star=getImage(getCodeBase(),"image/天空.JPG");
}
publicvoidpaint(Graphicsg){
g1.drawImage(star,0,0,this);//将图像先画到缓冲区
g1.drawImage(img,310-x,20,this);//将图像先画到缓冲区
g.drawImage(buffer,0,0,this);//将缓冲区占的图像画出
try{
Thread.sleep(10);
x+=2;
if(x==310){
x=2;
Thread.sleep(1000);
}
}catch(InterruptedExceptione){}
repaint();
}
publicvoidupdate(Graphicsg){
paint(g);
}
}
(3)编译程序LX7_7.java。
(4)编写显示LX7_7.class的页面文件,在浏览器中显示结果如图7.7所示。
(5)程序说明:
改进后的程序比原程序增加了Image类对象buffer和Graphics类对象g1。
覆盖了update方法。
换帧速度提高到100(1000/10),飞机每次移动2个点,动画效果更加平滑而且无闪烁。
新增的buffer对象,用作屏幕缓冲区。
新增的g1对象,用作屏幕绘图区。
在init方法中,程序调用Image对象的createImage方法,按照Applet的宽度和高度创建了屏幕缓冲区,然后调用getGraphics方法创建了Image对象buffer的绘图区。
在paint方法中通过g1.drawImage改变了图像输出的方向,图像被画在屏幕缓冲区内。
由于屏幕缓冲区不可见,使得画面交替时的闪烁现象也不
可见。
当屏幕缓冲区上的画图完成以后,再调用g.drawImage方法将整个屏幕缓冲区拷贝到屏幕上,这个过程是直接覆盖,不会产生闪烁。
上述方式被称为图形双缓冲技术。
图形双缓冲技术实际上是创建了一个不可见的后台屏幕,进行幕后操作,图像画在后台屏幕上,画好之后再拷贝到前台屏幕上。
这种技术圆满解决了画面交替时的闪烁,但图像显示速度变慢,内存占用较大,用户离开网页后,嵌入的Applet会继续运行,占用CPU时间。
3.使用线程创建动画的程序
(1)程序功能:
创建一个显示小球不断跳动并显示不同状态的动画程序。
要达到无闪烁现象,显示速度快,占用内存较小的要求。
即要使用双缓冲技术创建图像的显示方式,清除闪烁现象。
使用线程分别解决准备图像、显示图像的任务,解决显示速度慢,占用内存较大的问题。
(2)准备10个图像文件(T1.JPG~T10.JPG),它们分别显示小球不同时间的高度和状态,存放在“程序/image”目录下。
这是创建动画的基础工作,是动画显示的内容,应用程序只是解决图像“动”,即显示的方式。
(3)编写LX7_8.java程序文件,源代码如下。
(4)编译程序LX7_8.java。
importjava.awt.*;
importjava.applet.*;
publicclassLX7_8extendsAppletimplementsRunnable{
Imageimg[]=newImage[10];
Imagebuffer;
Graphicsg1;
Threadtd;
intindex=0;
publicvoidinit(){
buffer=createImage(getWidth(),getHeight());//创建图像缓冲区
g1=buffer.getGraphics();//创建绘图区
for(inti=0;i<10;i++)
img[i]=getImage(getCodeBase(),"image/"+"T"+(i+1)+".JPG");
}
publicvoidstart(){
if(td==null){
td=newThread(this);//创建线程对象
td.start();
}
}
publicvoidstop(){
if(td!
=null)
td=null;
}
publicvoidrun(){
while(true){
g1.drawImage(img[index],10,20,this);//画图像到缓冲区
repaint();//画出图像
try{
td.sleep(50);
}catch(InterruptedExceptione){}
g1.clearRect(10,20,100,100);//清除缓冲区中的图像
index=++index%10;}
}
publicvoidpaint(Graphicsg){
g.drawImage(buffer,0,0,this);//画出缓冲区中图像
}
publicvoidupdate(Graphicsg){
paint(g);
}
}
(5)编写显示LX7_8.class的页面文件,在浏览器中显示结果如图7.8所示。
(6)程序说明:
程序中使用图形双缓冲技术,显示一组图像。
程序实现Runnable接口中的run方法,这是一个和Applet同时运行的线程。
对线程的控制由Applet的start和stop方法完成,Applet运行时,就在start方法中启动线程,Applet停止时,就在stop方法中停止线程。
在线程td的run方法中的永恒循环当中,实现图像的轮流显示使小球不停的跳动。
首先调用绘图对象g1的drawImage方法把当前图像画在屏幕缓冲区内,在paint方法中把屏幕缓冲区拷贝到屏幕上。
但paint方法无法直接调用,因为要传递给它一个图形参数g,故调用repaint方法间接调用paint方法。
repaint方法无参数,它将调用update方法,由update方法调用paint方法并传递g参数。
这就是曾介绍过的一个线程负责准备图像而另一个线程负责显示图像的动画方法。