天天看點

java全自動生成krpano全景漫遊

之前有需求想把krpano功能化,讓背景全自動生成,但是在網上并沒有看到相關的文章,于是我就對krpano研究了一天,總算給實作了,随着VR的發展,這項技術肯定會有更多的人學習,我就把我研究出來的解決過程分享給大家吧!!!

java全自動生成krpano全景漫遊

準備工作:

  1.下載下傳krpano-1.19-pr8(我用的是這個版本),下載下傳位址:https://krpano.com/download/,至于破解我就不講了,網上有很多

2.java開發環境

3.tomcat

原理:下載下傳krpano後解壓檔案夾裡有一個批處理:MAKE VTOUR (MULTIRES) droplet.bat,直接把全景圖檔拖動執行這個批處理就會自動生成相應的全景html檔案夾。

廢話不多說,直接上碼:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.ujum.app.bean.Room;

public class CmdBat {

	public static void main(String[] args) {
		Room r = new Room();
		String dpath = "D:\\Tomcat 8.5\\webapps\\ujum-file\\vshow";
		String file = "0049132f-25dd-4984-8505-f6bdf624c6c3";
		String[] fn1 = { "1049132f-25dd-4984-8505-f6bdf624c6c3",
				"2049132f-25dd-4984-8505-f6bdf624c6c3",
				"3049132f-25dd-4984-8505-f6bdf624c6c3" };
		String[] fn2 = { "客廳", "卧室", "大客廳" };
		String title = "哈哈哈哈哈哈哈哈";
		String music = "vshow/backgroundmusic/default.mp3";
		try {
			setKrpano(r, dpath, file, fn1, fn2, title, music);
		} catch (InterruptedException e) {
			e.printStackTrace();
			System.out.println("上傳失敗");
		}

	}

	public static void setKrpano(final Room r, final String dpath,
			final String file, final String[] fn1, final String[] fn2,
			final String title, final String music) throws InterruptedException {
		final String temppath = "D:\\temp-room\\";
		String path = temppath + file;
		String ex = "krpanotools32.exe makepano -config=templates\\vtour-multires.config "
				+ path + "\\*.jpg";
		Runtime runtime = Runtime.getRuntime();
		boolean b = true;
		Process p = null;
		try {
			p = runtime.exec("cmd /c start d:\\krpano-1.19-pr8\\" + ex);
		} catch (Exception e) {
			b = false;
		}
		if (b) {
			final InputStream is1 = p.getInputStream();
			final InputStream is2 = p.getErrorStream();
			new Thread() {
				public void run() {
					BufferedReader br1 = new BufferedReader(
							new InputStreamReader(is1));
					try {
						String line1 = null;
						while ((line1 = br1.readLine()) != null) {
							if (line1 != null) {
								System.out.println("=AA==========line1======"
										+ line1);
							}
						}
					} catch (IOException e) {
						e.printStackTrace();
					} finally {
						try {
							is1.close();
							// 執行檔案複制
							File f = new File(dpath + "\\" + file);
							f.mkdirs();// 建立目錄
							// 複制檔案
							boolean b1 = copyFile(temppath + file
									+ "\\vtour\\tour.js", dpath + "\\" + file
									+ "\\tour.js");
							if (b1) {
								boolean b2 = copyFile(temppath + file
										+ "\\vtour\\tour.swf", dpath + "\\"
										+ file + "\\tour.swf");
								if (b2) {
									boolean b3 = copyFile(temppath + file
											+ "\\vtour\\tour.xml", dpath + "\\"
											+ file + "\\tour.xml");
									if (b3) {
										// 複制檔案夾
										boolean b4 = copyFolder(temppath + file
												+ "\\vtour\\panos", dpath
												+ "\\" + file + "\\panos");
										if (b4) {
											// 删除臨時生成檔案
											delFolder(temppath + file);
											// 修改krpano檔案内容
											String xmlPath = dpath + "\\"
													+ file + "\\tour.xml";
											File xmlFile = new File(xmlPath);
											DocumentBuilderFactory dbFactory = DocumentBuilderFactory
													.newInstance();
											DocumentBuilder dBuilder;
											try {
												dBuilder = dbFactory
														.newDocumentBuilder();
												Document doc = dBuilder
														.parse(xmlFile);
												doc.getDocumentElement()
														.normalize();
												for (int i = 0; i < fn1.length; i++) {
													updateAttributeValue(doc,
															fn1[i], fn2[i]);
												}

												// update Element value
												updateElementValue(doc, title);

												// delete element
												deleteElement(doc);

												// add new element
												addElement(doc);

												updateAttributeColorValue(doc,
														"0x000000");
												addMusicElement(doc, music);
												// write the updated document to
												// file or console
												doc.getDocumentElement()
														.normalize();
												TransformerFactory transformerFactory = TransformerFactory
														.newInstance();
												Transformer transformer = transformerFactory
														.newTransformer();
												DOMSource source = new DOMSource(
														doc);
												StreamResult result = new StreamResult(
														new File(xmlPath));
												transformer.setOutputProperty(
														OutputKeys.INDENT,
														"yes");
												transformer.transform(source,
														result);
												// 生成成功執行之後的操作,我這裡是生成之後更改資料庫狀态
												/*r.setMark("1");
												AdminService as = ContextUtil
														.getBean(
																AdminService.class,
																"adminService");
												as.updateRoom(r);*/
												/*
												 * System.out .println(
												 * "XML file updated successfully"
												 * );
												 */

											} catch (
													SAXException
													| ParserConfigurationException
													| IOException
													| TransformerException e1) {
												e1.printStackTrace();
												// 生成失敗執行操作
												/*r.setMark("2");
												AdminService as = ContextUtil
														.getBean(
																AdminService.class,
																"adminService");
												as.updateRoom(r);*/
											}

										}
									}
								}
							}
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
			}.start();
			new Thread() {
				public void run() {
					BufferedReader br2 = new BufferedReader(
							new InputStreamReader(is2));
					try {
						String line2 = null;
						while ((line2 = br2.readLine()) != null) {
							if (line2 != null) {
								System.out.println("=AA==========line2======"
										+ line2);
							}
						}
					} catch (IOException e) {
						e.printStackTrace();
					} finally {
						try {
							is2.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
			}.start();
			p.waitFor();
			p.destroy();
		} else {
			System.out.println("上傳失敗");
		}

	}

	/**
	 * 複制單個檔案
	 * 
	 * @param oldPath
	 *            String 原檔案路徑 如:c:/fqf.txt
	 * @param newPath
	 *            String 複制後路徑 如:f:/fqf.txt
	 * @return boolean
	 */
	public static boolean copyFile(String oldPath, String newPath) {
		try {
			int bytesum = 0;
			int byteread = 0;
			File oldfile = new File(oldPath);
			if (oldfile.exists()) { // 檔案存在時
				InputStream inStream = new FileInputStream(oldPath); // 讀入原檔案
				FileOutputStream fs = new FileOutputStream(newPath);
				byte[] buffer = new byte[1444];
				int length;
				while ((byteread = inStream.read(buffer)) != -1) {
					bytesum += byteread; // 位元組數 檔案大小
					// System.out.println(bytesum);
					fs.write(buffer, 0, byteread);
				}
				inStream.close();
			}
		} catch (Exception e) {
			// System.out.println("複制單個檔案操作出錯");
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 複制整個檔案夾内容
	 * 
	 * @param oldPath
	 *            String 原檔案路徑 如:c:/fqf
	 * @param newPath
	 *            String 複制後路徑 如:f:/fqf/ff
	 * @return boolean
	 */
	public static boolean copyFolder(String oldPath, String newPath) {
		try {
			(new File(newPath)).mkdirs(); // 如果檔案夾不存在 則建立新檔案夾
			File a = new File(oldPath);
			String[] file = a.list();
			File temp = null;
			for (int i = 0; i < file.length; i++) {
				if (oldPath.endsWith(File.separator)) {
					temp = new File(oldPath + file[i]);
				} else {
					temp = new File(oldPath + File.separator + file[i]);
				}

				if (temp.isFile()) {
					FileInputStream input = new FileInputStream(temp);
					FileOutputStream output = new FileOutputStream(newPath
							+ "/" + (temp.getName()).toString());
					byte[] b = new byte[1024 * 5];
					int len;
					while ((len = input.read(b)) != -1) {
						output.write(b, 0, len);
					}
					output.flush();
					output.close();
					input.close();
				}
				if (temp.isDirectory()) {// 如果是子檔案夾
					copyFolder(oldPath + "/" + file[i], newPath + "/" + file[i]);
				}
			}
		} catch (Exception e) {
			// System.out.println("複制整個檔案夾内容操作出錯");
			e.printStackTrace();
			return false;
		}
		return true;
	}

	// 删除檔案夾
	public static void delFolder(String folderPath) {
		try {
			delAllFile(folderPath); // 删除完裡面所有内容
			String filePath = folderPath;
			filePath = filePath.toString();
			java.io.File myFilePath = new java.io.File(filePath);
			myFilePath.delete(); // 删除空檔案夾
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static boolean delAllFile(String path) {
		boolean flag = false;
		File file = new File(path);
		if (!file.exists()) {
			return flag;
		}
		if (!file.isDirectory()) {
			return flag;
		}
		String[] tempList = file.list();
		File temp = null;
		for (int i = 0; i < tempList.length; i++) {
			if (path.endsWith(File.separator)) {
				temp = new File(path + tempList[i]);
			} else {
				temp = new File(path + File.separator + tempList[i]);
			}
			if (temp.isFile()) {
				temp.delete();
			}
			if (temp.isDirectory()) {
				delAllFile(path + "/" + tempList[i]);// 先删除檔案夾裡面的檔案
				delFolder(path + "/" + tempList[i]);// 再删除空檔案夾
				flag = true;
			}
		}
		return flag;
	}

	private static void addElement(Document doc) {
		NodeList employees = doc.getElementsByTagName("krpano");
		Element emp = null;

		// loop for each employee
		for (int i = 0; i < employees.getLength(); i++) {
			emp = (Element) employees.item(i);
			Element vtourskin = doc.createElement("include");
			vtourskin.setAttribute("url", "../skin/vtourskin.xml");
			emp.appendChild(vtourskin);
			Element skinselect = doc.createElement("include");
			skinselect.setAttribute("url", "../skinselect.xml");
			emp.appendChild(skinselect);
		}
	}

	private static void addMusicElement(Document doc, String music) {
		NodeList employees = doc.getElementsByTagName("krpano");
		Element emp = null;

		// loop for each employee
		for (int i = 0; i < employees.getLength(); i++) {
			emp = (Element) employees.item(i);
			Element musicEl = doc.createElement("action");
			musicEl.setAttribute("name", "bgsnd_action");
			musicEl.setAttribute("autorun", "onstart");
			musicEl.appendChild(doc.createTextNode("playsound(bgsnd, '" + music
					+ "', 0);"));
			emp.appendChild(musicEl);
		}
	}

	private static void deleteElement(Document doc) {
		NodeList employees = doc.getElementsByTagName("krpano");
		Element emp = null;
		// loop for each employee
		for (int i = 0; i < employees.getLength(); i++) {
			emp = (Element) employees.item(i);
			Node genderNode = emp.getElementsByTagName("include").item(0);
			emp.removeChild(genderNode);
		}

	}

	private static void updateElementValue(Document doc, String title) {
		NodeList employees = doc.getElementsByTagName("krpano");
		Element emp = null;
		// loop for each employee
		for (int i = 0; i < employees.getLength(); i++) {
			emp = (Element) employees.item(i);
			emp.setAttribute("title", title);
		}
	}

	private static void updateAttributeValue(Document doc, String oldname,
			String newname) {
		NodeList employees = doc.getElementsByTagName("scene");
		Element emp = null;
		// loop for each employee
		for (int i = 0; i < employees.getLength(); i++) {
			emp = (Element) employees.item(i);
			if (emp.getAttribute("title").equals(oldname)) {
				emp.setAttribute("title", newname);
				break;
			}
		}
	}

	private static void updateAttributeColorValue(Document doc, String newname) {
		NodeList employees = doc.getElementsByTagName("skin_settings");
		Element emp = null;
		// loop for each employee
		for (int i = 0; i < employees.getLength(); i++) {
			emp = (Element) employees.item(i);
			emp.setAttribute("design_bgcolor", newname);
			emp.setAttribute("design_bgalpha", "0.8");
		}
	}
}
           

這些代碼主要意思是用代碼來拖動全景圖檔去執行那個批處理,然後等待生成之後修改生成之後的檔案以及删除一切多餘的檔案,因為我做過N次實驗及對比,我發現執行後生成的很多檔案都是一緻的,是以我就整理了一個通用的包(放在vshow檔案夾),因為生成檔案後必須還得自動釋出,所有vshow這個檔案夾我是直接放在項目裡的:

java全自動生成krpano全景漫遊

至于vshow裡的檔案内容你自己生成一次之後保留這些東西就可以了,繼續回到正題,我這個是将全景圖檔上傳了之後,先存放在D:\\temp-room\\裡,然後執行cmd指令自動生成,生成了之後将需要的檔案複制到vshow檔案夾裡,隻要你仔仔細細看我代碼就能明白所有的事情,生成這些檔案處理完後,前台通路就直接用一個通用的jsp檔案來通路,直接貼上我的源碼吧,一定要仔細看代碼,不然真的很難懂:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html>
<head>
<base href="<%=basePath%>" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" >
	<title>${title }</title>
	<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
	<meta name="apple-mobile-web-app-capable" content="yes" />
	<meta name="apple-mobile-web-app-status-bar-style" content="black" />
	<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
	<meta http-equiv="x-ua-compatible" content="IE=edge" />
	<link rel="shortcut icon" href="images/favicon.png" target="_blank" rel="external nofollow" >
	<style>
		@-ms-viewport { width:device-width; }
		@media only screen and (min-device-width:800px) { html { overflow:hidden; } }
		html { height:100%; }
		body { height:100%; overflow:hidden; margin:0; padding:0; font-family:Arial, Helvetica, sans-serif; font-size:16px; color:#FFFFFF; background-color:#000000; }
	</style>
</head>
<body>
<div style="position: absolute;z-index: 1;margin-top: 10px;margin-left: 10px">
<a href="<%=basePath%>" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" ><img src="images/logo.png" style="height: 50px"></a>
</div>
<script src="http://www.sxujum.com/ujum-file/vshow/${vid }/tour.js"></script>
<div id="pano" style="width:100%;height:100%;">
	<noscript><table style="width:100%;height:100%;"><tr style="vertical-align:middle;"><td><div style="text-align:center;">ERROR:<br/><br/>Javascript not activated<br/><br/></div></td></tr></table></noscript>
	<script>
	var vid = "${vid}";
		embedpano({swf:"http://www.sxujum.com/ujum-file/vshow/${vid }/tour.swf", xml:"http://www.sxujum.com/ujum-file/vshow/${vid }/tour.xml", target:"pano", html5:"prefer", mobilescale:1.0, passQueryParameters:true});
	</script>
</div>

</body>
</html>
           

源碼位址:http://download.csdn.net/download/u012084981/10107545

如果放伺服器上有水印,破解工具:https://download.csdn.net/download/u012084981/10695498