krpano 功能化 -- linux 部署

本文仅供技术交流。

在前面的文章中:基于java后端的 krpano 功能化 已经实现在win平台将krpano功能化,这次我将krpano迁移至服务器:ubuntu 16.04 server。


以win的经验为基础,这里只需解决2个问题:

  • linux上krpano的安装与注册

  • 在linux上,用java执行krpano命令

(1)linux上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.

这样,就会在用户的~/下生成一个.krpanolicense文件


krpano 功能化 -- linux 部署_第1张图片


有了krpanolicense,就不用担心会有水印和版权信息了。


(2)在linux上,用java执行krpano命令

因为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不太熟悉,看的吃力,多补补基础。

vshow:

这里写图片描述

图片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>


看看最终自豪的效果:



后记:用服务器处理全景图是不现实的,只能做做开发,测试用,因为当并发量达到上k时,服务器必定hold不住,最理想的方法是让客户端(安卓、Ios)去切割全景图,把panos文件夹统一上传到第三方存储器或者业务服务器,业务服务器的功能应该是利用krpano去展示效果而已,而且krpano的版权,切割全景图也就没用了。现在切割符合krpano展示的全景图算法还在研究中,不久便可以投入使用!

你可能感兴趣的:(krpano)