基于java后端的 krpano 功能化

来源:互联网 发布:淘宝关键词可以改吗 编辑:程序博客网 时间:2024/06/03 17:24


最近领导要求全景图的展示效果跟XX公司做的一样,仔细研究了一下XX公司的效果,发现用的是krpano,了解了krpano后,就要将krpano功能化,做成一个功能。很多全景公司采用krpano做,只要集成了一个krpano,效果也可以做的跟他们一样。难点是,krpano每生成处理一张全景图,都会生成很多个文件夹,怎么将它功能化?


第一件想到的当然是百度!可是没找到有价值的情报。


这里写图片描述


于是google,找到了一篇写的很好很好,但是在百度搜索搜不到的博客:http://blog.csdn.net/u012084981/article/details/76382991,博主也是一个很好的人,我向他要了源代码,自己研究,然后根据自己的见解写了这篇博客。

先仔细观察krpano,可以发现,krpano生成的文件夹有一些是可以复用的,看下图,用鼠标将两张图tset.jpg和test2.jpg拖拽进krpano的MAKE VTOUR (NORMAL)droplet.bat


这里写图片描述

会先后生成一个叫vtour的文件夹,为了区分,我重命名为vtuor和vtour2,然后再来看看生成的两个vtour文件夹


这里写图片描述


这里写图片描述

在java web开发环境中,我们新建一个web project,将vtour文件夹拷贝到web root下,发布即可访问,


这里写图片描述



这里写图片描述


当然这是静态的,我们是要做成动态的网页。通过这两个vtour文件夹的对比(用Beyond Compare 4 软件对比),可以发现:

  • panos文件夹保存的是每张全景图生成的小图片,是动态变化的

  • plugins是各种效果的插件文件夹,是公有的

  • skin也是公有的

  • tour.html是一样的,是访问入口,也是公有的

  • tour.js是不一样的

  • tour.swf是不一样的

  • tour.xml是不一样的

    后面的tour_editor.html、tour_testingserver.exe、tour_testingserver_macos这几个是修改全景图的,显示时不会用到的,删掉了。

所以,只要保证tour.html能动态的读取到panos、tour.js、tour.swf、tour.xml就行了,用最笨的方法,在web root新建一个文件夹,专门处理krpano,就是vshow,将静态的文件夹拷进去,当用户每上传一张全景图时,先在临时文件夹为他生成全部文件,然后再将几个不一致的文件整合进一个文件夹,将该文件夹放在vshow里面,这个文件夹是动态的,每个用户都不一样,因此,我是用图片id命名的,生成后的结构如下:


这里写图片描述

这些418、419、420…是动态的,每次访问不同的图片时,前台传给后台图片id即可,至于访问入口,可以把tour.html的内容拷进一个通用的jsp,只要在里面访问不同图片id的不同panos、tour.js、tour.swf、tour.xml就行。

下面的代码除了展示全景效果图外,还有背景音乐!给出核心代码:

CmdBat.java

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 = "krpanotools32.exe makepano -config=\\templates\\vtour-normal.config "                + path + "\\*.jpg";        Runtime runtime = Runtime.getRuntime();        boolean b = true;        Process p = null;        try {            p = runtime.exec("cmd /c start f:\\krpano\\krpano-1.19-pr10-postable\\" + 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);                                                //生成成功                                                /*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");        }    }}


在控制层使用:ShareController.java

package com.xforce.krpano.controller;import java.io.IOException;import java.util.Date;import java.util.HashMap;import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.multipart.MultipartFile;import org.springframework.web.servlet.ModelAndView;import com.xforce.krpano.model.Upload;import com.xforce.krpano.service.ShareService;import com.xforce.krpano.util.CmdBat;import com.xforce.krpano.util.FileUpload;import com.xforce.krpano.util.FileUtil;import com.xforce.krpano.util.GreaterQiniuUtil;import com.xforce.krpano.util.QiniuUtil;@Controller@Scope("prototype")public class ShareController {   ...    //分享    @RequestMapping("share")    public ModelAndView share(Model model, HttpServletRequest request,             @RequestParam(value = "file") MultipartFile file) {        ...        //做处理        String newGilePath = path + "\\"+ upload.getId() + "\\";        FileUtil.moveFile(filePath, newGilePath);        String dpath = request.getSession().getServletContext().getRealPath("vshow");        String[] fn1 = {};        String[] fn2 = {};        String title = "xxxxx";        String music = "vshow\\backgroundmusic\\default.mp3";        String uploadId = upload.getId()+"";        try {            CmdBat.setKrpano(dpath, uploadId , path + "/", fn1, fn2, title,music);        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }               try {                Thread.sleep(4000);                mv = new ModelAndView();                Map<String, Object> map = new HashMap<String, Object>();                map.put("uploadId", Integer.parseInt(uploadId));                map.put("title",title);                mv.addAllObjects(map);                mv.setViewName("share");            } catch (NumberFormatException e) {                // TODO Auto-generated catch block                e.printStackTrace();            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        return mv;    }}


通用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%>">    <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://10.10.3.56:8080/K/vshow/${uploadId }/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://10.10.3.56:8080/K/vshow/${uploadId }/tour.swf", xml:"http://10.10.3.56:8080/K/vshow/${uploadId }/tour.xml", target:"pano", html5:"prefer", mobilescale:1.0, passQueryParameters:true});    </script></div></body></html>


来看看震撼的效果:


这里写图片描述


这里写图片描述

注意事项

  • 1.java执行批处理用的是Runtime.getRuntime().exec(); 这里面全用字符串,利用krpanotools32去执行命令,每个文件夹的关系是\,这和原来的博客区分,原来是:-config=templates,我改为:-config=\templates

  • 2.如果频繁的报删除文件,文件找不到的错,仔细看看临时存放路径有没有错,全景图路径有没有错

  • 3.如果是上传在显示,注意时间,生成文件io操作的速度比跳转页面的速度慢很多,可能会出现页面跳转了,报找不到tour.js(404)错误,只要让执行生成全景文件的线程在跳转线程完成前即可

  • 4.动态化的界面背景音乐不能播放,这个我也没琢磨出来

一定要仔细看路径!!很容易晕,如果有什么问题不解的,欢迎加我qq,个人主页有,要源码的加原来博客博主的微信(文章最后有大牛的联系方式:http://blog.csdn.net/u012084981/article/details/76382991)