本文仅供技术交流。
linux上krpano的安装与注册
在linux上,用java执行krpano命令
我以krpano-1.19-pr10为例,不必无官网下载,在这里下: http://pan.baidu.com/s/1bppkEbd 上传到服务器解压就可以了(里面有注册码)。可是,在生成全景图时,会有水印,怎么解决呢?在解压的文件夹里,有个叫Serial.txt文件,是一个注册码。只需要在服务器注册这个注册码就行了,每个用户都注册一遍。
我先把krpano-1.19-pr10上传到/opt目录下,unrar 解压,然后执行krpanotools register命令注册机器:
root@S189919:/opt/krpano-1.19-pr10# /opt/krpano-1.19-pr10/krpanotools register FXsqTqaGNSZER5dSETEm+VzQEh9sWSa5DZMFsSmMxYV9GcXs8W3R8A/mWXrGNUceXvrihmh28hfRF1ivrW0HMzEychPvNiD8B/4/ZzDaUE9Rh6Ig22aKJGDbja1/kYIqmc/VKfItRE2RTSOIbIroxOtsz626NIpxWksAAifwhpNwuPXqDQpz2sRUMBzoPqZktpkItoSenN2mKd8Klfx7pOuB6CIK3e1CDXgyndqOt2mWybLZcU/wfJVAecfxk15ghiqrzaDsbqrdABDowg==
Code registered.
root@S189919:/opt/krpano-1.19-pr10# exit
exit
wen@S189919:~$ cd /opt/krpano-1.19-pr10/
wen@S189919:/opt/krpano-1.19-pr10$ /opt/krpano-1.19-pr10/krpanotools register FXsqTqaGNSZER5dSETEm+VzQEh9sWSa5DZMFsSmMxYV9GcXs8W3R8A/mWXrGNUceXvrihmh28hfRF1ivrW0HMzEychPvNiD8B/4/ZzDaUE9Rh6Ig22aKJGDbja1/kYIqmc/VKfItRE2RTSOIbIroxOtsz626NIpxWksAAifwhpNwuPXqDQpz2sRUMBzoPqZktpkItoSenN2mKd8Klfx7pOuB6CIK3e1CDXgyndqOt2mWybLZcU/wfJVAecfxk15ghiqrzaDsbqrdABDowg==
Code registered.
因为java本身是跨平台的第一语言,所以选择java,就等于成功了一半。但在linux上,用java的runtime.exec与在win上的调用命令不同,文件路径也不同,这是最需要注意的!
以/opt/test/test.jpg的图片为例
krpano在linux执行的命令是:
/opt/krpano-1.19-pr10/krpanotools makepano -config=templates/vtour-normal.config /opt/test/test.jpg
而win是:
cmd /c start f:\\krpano\\krpano-1.19-pr10-postable\\krpanotools32.exe makepano -config=\\templates\\vtour-normal.config f:\\test\\test.jpg
linux的文件目录是”/ “,win是”\\”。
这是完整的krpano工具类:CmdBat
package com.xforce.krpano.util;
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;
public class CmdBat {
/*public static void main(String[] args) {
String dpath = "D:\\apache-tomcat-8.0.33\\webapps\\krpano\\vshow";
String file = "353";
String[] fn1 = {};
String[] fn2 = {};
String title = "yyyyyyyy";
String temppath = "f:\\temp-room\\";
String music = "vshow/backgroundmusic/default.mp3";
try {
setKrpano(dpath, file,temppath, fn1, fn2, title,music);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("上传失败");
}
}*/
public static void setKrpano(final String dpath, final String file,final String temppath,
final String[] fn1, final String[] fn2, final String title,final String music)
throws InterruptedException {
String path = temppath + file;
File targetFile = new File(path);
if(!targetFile.exists()){
targetFile.mkdirs();
}
String ex = "/opt/krpano-1.19-pr10/krpanotools makepano -config=templates/vtour-normal.config "
+ path + "/*.jpg";
Runtime runtime = Runtime.getRuntime();
String[] cmd = new String[]{"/bin/sh","-c", ex };
boolean b = true;
Process p = null;
try {
p = runtime.exec(cmd);
} 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);
//生成成功
/*System.out
.println("XML file updated successfully");*/
} catch (Exception e1) {
e1.printStackTrace();
//生成失败
}
}
}
}
}
} 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");
}
}
}
至于如何调用CmdBat类,看具体的业务需求,我是先把全景图从前台传输到后台,存在uploadtemp目录中,再调用krpano处理全景图,在uploadtemp目录中生成一个图片id的文件夹,里面放vtour,然后把vtour里面的panos、tour.js、tour.xml、tour.swf 复制到tomcat统一存放全景目录vshow中,最后再把uploadtemp删除,页面只需要去vshow中根据图片id就可以访问到每个全景文件。跟在win上的一模一样。仔细研究CmdBat类,看懂了基本就可以用了,调用时很容易的。如果对java的io不太熟悉,看的吃力,多补补基础。
图片id文件夹内部:
jsp页面,把title、图片id(uploadId )从后台传过来即可:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<head>
<base href="<%=basePath%>">
<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" />
<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">
div>
<script src="http://serverIp:8080/K/vshow/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 uploadId = "${uploadId}";
embedpano({swf:"http://serverIp:8080/K/vshow/tour.swf", xml:"http://serverIp:8080/K/vshow/${uploadId }/tour.xml", target:"pano", html5:"prefer", mobilescale:1.0, passQueryParameters:true});
script>
div>
body>
html>
看看最终自豪的效果: