`
defrag_sly
  • 浏览: 131430 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

关于image,ImageDescriptor,imageRegistry

阅读更多
相信不需要多说,大家都明白调用本地资源例如(icon)这类的资源是需要消耗很多性能的。SWT提供了Image这个对象,如果大家看看Image这个类,就会发现,对与图片的颜色,大小,色调等等所有的图形信息,封装到了ImageData(其实ImageData里还有个PaletteData,这个对象占用了很多资源)里面。也就是说每创建一次image就需要重新构筑一次ImageData。所以对于同一图片如果只创建一次,就会对效率有很大的提高。相信这是所有人都希望做的的事。
所以SWT对image提供了ImageDescriptor进行描述或者说代理,imageRegistry进行管理。在我们的实际开发中发现许多人使用方式不同,就会产生效率上的差异。
以下我对几种不同的使用方式进行了测试,有些错误方式甚至在eclipse源代码中都有使用。

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.widgets.Display;

public class ImageTester {

	private static int size;
	private static final String imagePath = "F:/slyworkspace/myTest/gefTree/aaaaaaaa/icons/Control_Treeview.jpg";

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		size = 1000;
		ImageTester imageTester = new ImageTester();
		System.out.println("===========createByDescriptor=============");
		long start = System.currentTimeMillis();
		System.out.println("start : " + start);
		for (int i = 0; i < size; i++)
			imageTester.createByDescriptor();
		long end = System.currentTimeMillis();
		System.out.println("end : " + end);
		System.out.println("time : " + (end - start));

		// =================================================
		System.out.println("===========createByImageData=============");
		start = System.currentTimeMillis();
		System.out.println("start : " + start);
		for (int i = 0; i < size; i++)
			imageTester.createByImageData();
		end = System.currentTimeMillis();
		System.out.println("end : " + end);
		System.out.println("time : " + (end - start));

		// =================================================
		System.out.println("===========createByRegistry=============");
		start = System.currentTimeMillis();
		System.out.println("start : " + start);

		for (int i = 0; i < size; i++)
			imageTester.createByRegistry();
		end = System.currentTimeMillis();
		System.out.println("end : " + end);
		System.out.println("time : " + (end - start));

		// =================================================
		System.out.println("===========createByRegistryWrong=============");
		start = System.currentTimeMillis();
		System.out.println("start : " + start);
		for (int i = 0; i < size; i++)
			imageTester.createByRegistryWrong();
		end = System.currentTimeMillis();
		System.out.println("end : " + end);
		System.out.println("time : " + (end - start));
	}

	public Image createByDescriptor() {
		URL fullPathString = null;
		try {
			fullPathString = new File(imagePath).toURL();
		} catch (MalformedURLException e) {
			return null;
		}
		ImageDescriptor desc = ImageDescriptor.createFromURL(fullPathString);
		Image createImage = desc.createImage();
		return createImage;
	}

	public Image createByImageData() {
		Image image = new Image(Display.getCurrent(), new ImageData(imagePath));
		return image;
	}

	public Image createByRegistry() {

		ImageRegistry imageRegistry = JFaceResources.getImageRegistry();
		String key = "ImageTestter";
		Image image = imageRegistry.get(key);
		if (image == null) {
			URL fullPathString = null;
			try {
				fullPathString = new File(imagePath).toURL();
			} catch (MalformedURLException e) {
				return null;
			}
			ImageDescriptor imageDescriptor = ImageDescriptor
					.createFromURL(fullPathString);
			if (imageDescriptor != null) {
				imageRegistry.put(key, imageDescriptor);
				image = imageRegistry.get(key);
			}
		}
		return image;
	}

	public Image createByRegistryWrong() {
		ImageRegistry imageRegistry = JFaceResources.getImageRegistry();
		String key = "ImageTestter";
		ImageDescriptor descriptor = imageRegistry.getDescriptor(key);
		if (descriptor == null) {
			URL fullPathString = null;
			try {
				fullPathString = new File(imagePath).toURL();
			} catch (MalformedURLException e) {
				return null;
			}
			ImageDescriptor imageDescriptor = ImageDescriptor
					.createFromURL(fullPathString);
			if (imageDescriptor != null) {
				imageRegistry.put(key, imageDescriptor);
			}
		}
		descriptor = imageRegistry.getDescriptor(key);

		Image createImage = descriptor.createImage();
		return createImage;
	}
}



测试的结果:

===========createByDescriptor=============
start : 1235712247921
end : 1235712254859
time : 6938
===========createByImageData=============
start : 1235712254859
end : 1235712261187
time : 6328
===========createByRegistry=============
start : 1235712261187
end : 1235712261468
time : 281
===========createByRegistryWrong=============
start : 1235712261468
end : 1235712267937
time : 6469



从结果可以发现,使用createByRegistry这个方法是极大的提高了效率,原因是:ImageRegistry内维护了一个key-->descriptor&image的一个map。将image缓存了起来。
相信绝大部分人不会用createByImageData这个方法,但是大家可能发现为什么这个方法比createByDescriptor还要快呢?这是由于Descriptor.create其实和new Image()是一样的,并没有把image缓存。相反createByDescriptor这个方法错误的使用了Descriptor浪费了时间。最后一个方法createByRegistryWrong是我发现大多数人最容易错的使用方法,只是简单的将Descriptor缓存起来但是在得到image时仍然与createByImageData没有差别,这也浪费了一些时间,size的增加createByImageData与createByRegistryWrong会越来越接近,但是与createByDescriptor会越来越大。
方法createByRegistry无疑是效率最优的方法。
ps:在我的机器上size=10000时候,甚至出现了没有足够handls的情况。(双盒1g的哦)
虽然以上的测试仅仅是一些极限的测试,对于同一图片使用1000次的情况,在eclipse中或许并不常见,所以才会出现eclipse的源代码中存在错误的使用方法吧。
不过效率的差别的确真的很明显。
总结一下,使用中Image类对于我们来讲是禁止使用的,如果需要image的一些信息,需要从Descriptor对象中获得,控制ImageData对象的后加载,需要image对象的时候利用Registry。
最好的方式是将Descriptor放到Registry中,使用Registry同一管理。
3
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics