关于awt 不实用第三方类库 实现 图片旋转,变形等处理

来源:互联网 发布:dj网络红歌 编辑:程序博客网 时间:2024/06/05 06:33

<本文来自cnmm22:http://blog.csdn.net/cnmm22/article/details/44628881>


● 一般实际应用中可能会直接g.drawImage 的时候 传入参数,来调整图片x,y坐标,甚至大小,所以重点是关于图片的旋转;


● 一般控制旋转 要结合到 TimerTask 类;

好下面说重点:


//===========================================================
要在 java 中处理图片,比较痛苦,要处理好图片的显示和效果,下面的概念
必须搞懂,无法绕过。

1、BufferedImage,ImageIO;    //
BufferedImage

2、MediaTracker;    //媒体最终器

3、AffineTransform; //仿射变换对象

//==========================================================

达到的效果:
图片

实现动画(比如旋转,移动)思路:先将素材图片放到内存中,在内存中处理图片旋转,方位、尺寸变换;通过 repaint 机制,或者 
TimerTask  调度,刷新图片。

有时,我们还会应用一些双缓冲 或者三缓冲技术,这里我们只说最基本的操作。

1、
先将素材图片放到内存中:
 ◆ 
javaImage对象不能当作BufferedImage对象使用,这对我们进行ImageIO操作有很多不便;
 
◆ Image是一个抽象列,BufferedImageImage的实现;
 ◆ ImageBufferedImage的主要作用就是将一副图片加载到内存中;

明白了这些,剩下就是去学习怎样引入图片到 
BufferedImage 中了,一般有两种方法
 BufferedImage biFlip ImageIO.read(u);
 BufferedImage biFlip = new BufferedImage(height, width, bi.getType());

下面 偶 上一段代码:两种方法都用到了

BufferedImage image;
URL u = this.getClass().getClassLoader().getResource("images/1/yqp.gif");

try {
image = ImageIO.read(u);
} catch (IOException e) {
e.printStackTrace();
} // 取得图像 
mt = new MediaTracker(t);// 实例化媒体加载器
mt.addImage(image, 0); // 增加图像到加载器中
try {
mt.waitForAll(200); // 等待图片加载
} catch (Exception ex) {
ex.printStackTrace(); // 输出出错信息
} 
 
originalBufImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB); // 创建原始缓冲区图像,注意,这里已经引入两个BufferedImage 了。


这是一个完整的放入内存,建立 
BufferedImage 的代码,照这个写。

利用反射,拿到URL(固定写法,不用深究)。 
ImageIO,try catch 把第原图转换成第一个 BufferedImage ,这样就能得到Image的属性,比如宽高,着色位宽,灰度等,这些参数也不用深究,拿到他们仅仅是为了方便创建一个另一个 BufferedImage:originalBufImage  。

这里的关键,引入了 
MediaTracker ,这不是一个很常见的类,但是一个很好用的类,比如用在:预加载资源文件。

他的主要用法:
waitForAll(200); // 等待图片加载

MediaTracker 的使用不是必须,但要处理好 图片等资源,必须有它。

2、处理图像:我 这里使用 
TimerTask举例(实际 在repaint 里实现更简单):

BufferedImage bufImage;   //第三个BufferedImage 

if (timer1 == null) {
timer1 = new Timer();
}
task1 = new TimerTask() {
public void run() {

bufImage = originalBufImage;
bufImageG = bufImage.createGraphics(); // 创建bufImage的图形环境
bufImageG.drawImage(image, 0, 0, null); // 传输源图像数据到缓冲区图像中
int r1 = r.nextInt(100);
angle += 50 + r1;
double angleValue = Math.toRadians(angle);
if (bufImage == null)
return; // 如果bufImage为空则直接返回
BufferedImage filteredBufImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB); // 过滤后的图像 

这里引入了一个关键的步骤: 
bufImageG = bufImage.createGraphics(); ,生出一个处理画布,如果不了解这个步骤的含义,照做,或者只能去学习了。首先要明白,它的作用也很简单,所以不要想复杂了。
另外bufImageG.drawImage(image, 0, 0, null);,后面的0,0定义了缓冲区图像作画起点,一般就是0,0。最后null是观察者。

3、旋转图像:利用
AffineTransform、AffineTransformOp 。

                                AffineTransform transform = new AffineTransform(); // 仿射变换对象
// 后面参数是核心
                                transform.rotate(angleValue, 123, 119); // 旋转图像 
AffineTransformOp imageOp = new AffineTransformOp(transform, null);// 创建仿射变换操作对象
imageOp.filter(originalBufImage, filteredBufImage);// 过滤图像,目标图像在filteredBufImage
bufImage = filteredBufImage; // 让用于显示的缓冲区图像指向过滤后的图像
if (false == live) {
timer1.cancel();  //这里只是模拟了使计划任务停止的方法,一定不要忘了停止
}
}
};
timer1.schedule(task1, 0, 60);  //每60毫秒旋转一次角度,并处理好图片放在缓冲区中供你使用。

这里涉及到 AffineTransform类的使用,关于这个类,现成教材几乎没有,这里只要按我的写法去做,并且能够解决问题就行了,适当的时候你可能还需运用AffineTransform 做一些尺寸、坐标变换方面的工作,这些功能也是由AffineTransform来实现。这个时候你需要查API。记住,他只是一个工具,什么仿射变换,图像过滤,去您娘滴蛋,我可以明确的说,这些设计一点都不方便使用。

这里要注意  transform.rotate(angleValue, 123, 119); // 旋转图像 这段代码,后面的参数123, 119是旋转的圆心 

而angleValue角度 timer1.schedule 每执行一次就变换一次。

4、最后,我在调用整个Frame 窗口重绘的地方:

g.drawImage(bufImage, x, y, W, H, null);

完事,这里,  x, y, W, H, 都是动态计算的,所以达到了变换尺寸和坐标的作用,具体做法:

if (!k) {        //boolean k;
W += 2;
x -= 1;
H += 2;
y -= 1;
}

if (k) {
W -= 2;
x += 1;
y += 1;
H -= 2;
}

if (W > 271) {
k = true;

}
if (W < 237) {
k = false;


x = d.n.getX() + d.n.getW() / 2 - 123;
y = d.n.getY() + d.n.getH() / 2 - 119; 

这段代码一共用了3个
BufferedImage 就是3个缓冲区图像来处理一个动画的效果,这酸爽,谁用谁知道,在java里,图片处理的问题从此得到了解决……
0 0
原创粉丝点击