krpano 功能化 -- linux 部署

將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.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

這樣,就會在用戶的~/下生成一個.krpanolicense文件


這裏寫圖片描述


有了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
  • 1

而win是:

cmd /c start f:\\krpano\\krpano-1.19-pr10-postable\\krpanotools32.exe makepano -config=\\templates\\vtour-normal.config  f:\\test\\test.jpg
  • 1

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");
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405


至於如何調用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+"/";
%>
<!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://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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

後記:用服務器處理全景圖是不現實的,只能做做開發,測試用,因爲當併發量達到上k時,服務器必定hold不住,最理想的方法是讓客戶端(安卓、Ios)去切割全景圖,把panos文件夾統一上傳到第三方存儲器或者業務服務器,業務服務器的功能應該是利用krpano去展示效果而已,而且krpano的版權,切割全景圖也就沒用了。現在切割符合krpano展示的全景圖算法還在研究中,不久便可以投入使用!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章