6. ImageConsumer接口和PixelGrabber类
接口ImageConsumer用于从图像中提取像素数据,并将这些数据以另一种数据类型方式表示出来。与前面的类ImageProducer接口在功能上相反。一个实现ImageConsumer接口的对像将生成int和byte类型的数组,这些数组代表了一个Image对像的像素。
用PixelGrabber类可以实现ImageConsumer接口。PixelGrabber类与MemoryImageSource类相反,它不是从像素数组中生成图像,而是从现存的图像中提取像素数组。要使用PixelGrabber,首先要定义一个足够大的int型数组来存储图像像素数据,然后生成一个PixelGrabber实例,将要提取的数据放在一个矩形中传递。最后,在这个实例中调用grabPixels()方法实现传递给数组pixel[]。
PixelGrabber的构造方法如下:
PixelGrabber(Image imgObj, int left, int top,
int width, int height, int pixel[],
int offset , int scanLineWidth);
此处imgObj是要被提取像素的对像。left和top的值指定了矩形的左上角,width和height指定了矩形的尺寸,这个矩形中像素是提取的目标。这些像素将被存储在以offset开始的像素数组pixel中,扫描线的宽(常与图像的宽相同)由参数scanLineWidth传递。
grabPixels()方法的定义如下:
boolean grabPixels() throws
InterruptedException
该方法成功时返回true,不成功则返回false。
三、动画制作
1.前景图像透明度处理
本程序使用的前景图如图4。
图4 前景图
若前景图的背景部分不透明,在动画制作中会出现图5的现像。
图5 前景图像不透明产生的效果
这样不会产生动画感。因此,必须对前景图背景部分的透明度作改变,使背景的透明度为全透明。
可以用一些图像处理软件,比如,用Photoshop或某些Windows版本自带的“画图”软件,改变背景的透明度。本文介绍用Java直接改变图像透明度,并对图像像素进行处理的方法。使用如下程序块改变前景图的背景透明度:
ColorModel cm=ColorModel.getRGBdefault();
for(int i=0;i<ih;i++){
for(int j=0;j<iw;j++){
int red,green,blue;
red =cm.getRed(pixels[i*iw+j]);
green=cm.getGreen(pixels[i*iw+j]);
blue =cm.getBlue(pixels[i*iw+j]);
if(red>230&&green>230&&blue>230)
pixels[i*iw+j]=0<<24|red<<16|
green<<8|blue;
}
}
将图像白色背景的Alpha值设置为0,而其余像素的透明度和红、绿、蓝的值不改变。因为前景图的背景白色未必纯白色(255,255,255),所以在程序段中作了一些改变,将满足条件
red>230&&green>230&&blue>230
的像素都作为白色背景处理。
2.海水透明度处理
仅仅对h>=220的海水部分进行透明度处理。参见图6。图6中白色部分的像素未画出。
图6 海水图制作示意图
海水的透明度设计为
alpha=3*h-540; (h>=220)
海水越深,透明度越大,即越不透明。为了加快计算机对图像的处理速度,本程序仅对h>=220的海水部分进行了处理,而其它部分的像素并不放在图像数组pixels内。这样处理的本质是在内存中将图6中处于白色部分的像素进行“剪切”,从而形成一幅全是海水的较小的图像。在画海水图时,也仅需画出海水部分。
3.云层透明度处理
云层的制作类似于海水制作。从背景图中0<=h<=90部分是云层,如图7。图7中,白色部分的像素未画出。云层的透明度设计为
alpha=220-2*h; (0<=h<=90)
云层越往上,透明度值越大,即越不透明。
图7 云层图制作 对云层的处理也与海水部分相同,仅将云层0<=h<=90部分放入图像数组pixels中,“剪切”掉处于白色部分的图像像素,形成一幅较小的云层图。这样在作画时,也仅需画出云层图即可。
|