您的位置:首页 > 编程语言 > Java开发

在Java中实现DeepZoom的初步尝试

2009-12-13 20:24 281 查看
接触过Silverlight的朋友们,可能都对DeepZoom这项技术比较熟悉了。



通过DeepZoom所提供的以交互方式查看高分辨率图像的功能。用户可以快速放大和缩小图像,而不会影响应用程序的性能,基于此项技术,使用者能够将海量图片资源的统一展示给用户,并且不损失其质量。



作为微软替Silverlight准备的高级图像处理技术之一,在很多场合中都能看到DeepZoom的身影。



比如:http://seadragon.com/
上,就存在着很多相关应用示例。其直观缩放效果之佳,堪称令人叹为观止。例如,一张原本模糊不清的自行车广告,放大到最后,我们甚至能将其上的广告词看得一清二楚。



我不得不说,天啊!真是牛X!但Silverlight是如何实现这一切的呢?



原因在于,DeepZoom对于图像的处理并非一整张一揽子的显示给用户,而是将大图“切”成一系列小图,再将大图像分辨率压缩到一定比例展示出去,只有当用户点击某部分请求交互式,才会通过网络将更高分辨率的“小图”逐次传输到前台。



也就是说,当文件初始加载时,只有极少量数据会在屏幕上显示内容,最初加载的都是有损的低分辨率图像,然后根据用户的不同选择, 再分别将更高或更低分辨率的图像传递出来。这也是DeepZoom号称其提供"模糊到鲜亮"体验的原因,也是DeepZoom不管图像有多大都能无缝立即打开图像而不用等待很长时间加载图像数据的原因。



但根究其关键点来说,也无外乎异步加载,逐次传递罢了。比如在Seadragon上,我们随意打开一个示例就会发现,当我们初次点击某一图像时,程序也只是简单的将其“膨化”,图像并不清晰,甚至可说非常的模糊。









然后,程序才会根据用户所点击区域,将x,y坐标与一个区分缩放程度的数值传到后台,再由后台查询对应的分解图,仅将其对应部分传递到前台,达到资源占用的最小化与运行效率的最大化。







所以我们在有时会看到这种情况,就是某一个角落的解析度很高,但整体却非常模糊。事实上,这是由于DeepZoomObject异步加载后台图块所造成的。







事实上,只要开发者有此意愿,无论是Java抑或Flash中,都可以将其轻易地重现出来。比如鄙人在本周为LGame新添加的一个放大镜组件,就可以实现近似功能。(当然,此项功能最主要的作用在于组件和精灵的自动缩放,单独的放大镜组件只是衍生品……)





package org.loon.test;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import org.loon.framework.game.simple.GameScene;
import org.loon.framework.game.simple.core.graphics.Deploy;
import org.loon.framework.game.simple.core.graphics.Screen;
import org.loon.framework.game.simple.core.graphics.window.LButton;
import org.loon.framework.game.simple.core.graphics.window.LMagnifier;
import org.loon.framework.game.simple.core.resource.ZipResource;
import org.loon.framework.game.simple.utils.NumberUtils;
/**
 * Copyright 2008 - 2009
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0  * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 * 
 * @project loonframework
 * @author chenpeng
 * @email:ceponline@yahoo.com.cn
 * @version 0.1
 */
public class Main extends Screen {
	// 放大镜组件
	private LMagnifier magnifier = new LMagnifier(0, 0, 320, 420);
	// zip资源加载器
	private ZipResource res = new ZipResource();
	private int pageNo, prev;
	/**
	 * 图像资源读取点移动
	 * 
	 * @param name
	 */
	private void moveImage(String name) {
		byte[] image = res.loadData(name);
		if (image == null) {
			switch (prev - pageNo) {
			case 1:
				pageNo++;
				break;
			case -1:
				pageNo--;
				break;
			}
		}
		magnifier.loadImage(image);
		centerOn(magnifier);
	}
	public Main() {
		// 设定背景图像
		this.setBackground("images/back.jpg");
		this.pageNo=prev=-1;
		try {
			// 加载jar内zip资源
			res.addArchive("mybook.zip");
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 添加下一步按钮
		LButton buttonNext = new LButton("images/next.png", null, 60, 60, 530,
				220) {
			public void doClick() {
				prev = pageNo;
				moveImage(NumberUtils.addZeros(++pageNo, 3) + ".gif");
			}
		};
		this.add(buttonNext);
		// 添加上一步按钮
		LButton buttonPrev = new LButton("images/prev.png", null, 60, 60, 530,
				140) {
			public void doClick() {
				prev = pageNo;
				moveImage(NumberUtils.addZeros(--pageNo, 3) + ".gif");
			}
		};
		this.add(buttonPrev);
		// 锁定放大镜组件,不允许拖拽
		magnifier.setLocked(true);
		// 组件自动匹配图像大小
		magnifier.setMatching(true);
		// 组件居中显示
		centerOn(magnifier);
		// 添加组件
		add(magnifier);
	}
	public void draw(Graphics2D g) {
	}
	public void leftClick(MouseEvent e) {
	}
	public void middleClick(MouseEvent e) {
	}
	public void rightClick(MouseEvent e) {
	}
	public void onKey(KeyEvent e) {
	}
	public void onKeyUp(KeyEvent e) {
	}
	public static void main(String[] args) {
		GameScene frame = new GameScene("[LGame-simple版使用范例-图像缩放]", 640, 480);
		Deploy deploy = frame.getDeploy();
		deploy.setScreen(new Main());
		deploy.setLogo(false);
		deploy.setShowFPS(false);
		deploy.setFPS(100);
		deploy.mainLoop();
		frame.showFrame();
	}
}






比如,笔者在此处内置了机器猫同人《糟糕小叮当》(又名:野比的后宫)作为示例,以红色圆靶来决定放大的区域。



程序下载地址(源码在jar中,内有《糟糕小叮当》1-519……):http://code.google.com/p/loon-simple/downloads/list










无需用户关心具体细节,只要你会使用鼠标,组件就会根据你的点击位置自动放大指定区域图像到你面前。







当然,目前此部分的Java实现并不完善,只做了前台的图像膨化、柔化、锐化。但事实上,由于此时我们已经获得了该区域的x,y坐标与图像深度值,只要效仿Silverlight多进行一次后台查询与传图,那么实际的运行结果也将是高度一致的了。(这部分预计留待LGame-Simple-0.5版增加网络服务时再提供)



















程序下载地址(源码在jar中,内有《糟糕小叮当》1-519……):http://code.google.com/p/loon-simple/downloads/list

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐