imagemagick 批次轉換影像為 PNG8

由於通用電子地圖位元深度為 24bit 而客戶的 GIS 軟體只吃 8bit png 檔案,幾番折騰後發現可以用 imagemagick 這神器轉換。需要特別注意的是使用預設的 PNG8 會出現圖片有莫名其妙的粉紅雜點,故需要加上 -colors 256 參數。

粉紅雜點錯誤

另外在執行 windows 需要寫 magick convert ,而 ubuntu 則直接寫 convert。

windows

for /R %x in (*.png) do magick convert "%x" -colors 256 PNG8:"%x"

linux

首先查看 png 資訊,可以確認為 24 bit

file 0.png

0.png: JPEG image data, JFIF standard 1.01, resolution (DPI), density 96×96, segment length 16, baseline, precision 8, 256×256, frames 3

安裝 imagemagick 並執行遞迴批次轉換

sudo apt-get install imagemagick
find -name "*.png" -exec convert {} -colors 256 PNG8:{} \;

最後確認檔案是否轉換成功,最後輸出 8-bit 成功轉換

file 0.png

0.png: PNG image data, 256 x 256, 8-bit colormap, non-interlaced

 

通用電子地圖 Open Data 初體驗

國土測繪中心提供了 GIS 用的目錄式及 mbtiles 格式的圖資,由於筆者一時無法解譯 GIS 的目錄規則 (可能是 ArcGIS? 沒用過不曉得),故在此下載 mbtiles 圖資並且搭配 MBUtil 解壓。

圖資下載網址

https://maps.nlsc.gov.tw/

MBUtil 下載位置

https://github.com/mapbox/mbutil

使用上還是挺方便的,需要注意就是目錄名稱是不存在的,在此設定同名就可以輕鬆導出規則為 z/x/y 圖磚目錄。

mb-util TaiwanEMap6.mbtiles TaiwanEMap6

佈署方式也相當容易,只需將整個目錄丟到喜歡的 webserver 底下即可使用。在此就偷懶用 GeoServer 內建的 jetty 發佈,將 TaiwanEMap6 整個目錄丟到 webapps 底下即可。

後記

在開發 Openlayer 相關應用時發現對岸高手寫了這篇 (不曉得原作是何方妖孽?),因而確定是 ArcGIS 的圖磚目錄結構,後續再補上轉換規則說明。

OSM 簡體轉繁體

由於不是每個人都看得懂簡體字,此外台商、新加坡、香港等…看繁體字也相對有親切感,因而寫了這篇。首先使用 OSM Export 下載局部檔案,以下是我使用的範圍圖資。 (下載回來後的 map.osm 其實就是 xml 格式)

https://www.openstreetmap.org/export#map=14/18.2486/109.5229

接著使用一套強大的簡轉繁軟體 OpenCC 來達成需求

https://github.com/BYVoid/OpenCC

sudo apt-get install openccopencc -i map.osm -o map_zhtw.osm s2tw.json

確認測試結果無誤後在到以下網站下載中國 OSM 資料,特別注意要下載 bz2 格式,解壓縮以後即為 xml 檔。

http://download.geofabrik.de/asia.html

GeoServer NetCDF Extension 安裝

由於混飯的需求會使用到網格資料 netcdf 及 grib 這兩種聽都沒聽過奇怪的格式,預設的 GeoServer 是沒有支援此類格式,必須安裝 extension。選擇 Coverage Formats 底下的 netcdf , grib 選項下載即可,此外下載時須注意版號一致否則無法使用。

http://geoserver.org/release/stable/

將載完以後的檔案解壓縮到 webapps/geoserver/WEB-INF/lib,從新啟動 GeoServer 應該就會生效。

測試資料集則可以使用 NOAA 的海洋資料,方便測試只使用較小的資料 (5° grid)

https://www.nodc.noaa.gov/cgi-bin/OC5/woa18/woa18.pl

下圖是發佈後的結果,沒意外的很醜,後續將安裝其他 Extension 及自訂 SLD 來解決此問題。

Cesium 初體驗

載點

https://cesiumjs.org/downloads/

下載回來最主要會引用的是 Build/CesiumUnminified 或 Build/Cesium 這兩個資料夾內的檔案。因為我是使用 vscode 進行開發所以就不用他預設的 nodejs 啟動方式,而直接使用 live server。

值得一提的是我以為偷懶把通用電子地圖直接丟到 geoserver 的 webapps 目錄底下就可以動了,但卻出現了跨域魔咒,可見 geoserver 的跨域設定只對自己有效,對偷懶丟到 webapps 的是不起作用的,最後只好偷懶丟到 vscode 開發目錄底下讓他形成同個 domain 才順利搞定。

Access to XMLHttpRequest at ‘http://127.0.0.1:8080/TGOS/4/13/5.png’ from origin ‘http://127.0.0.1:5500’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

以下為我串接通用電子地圖的結果。

<!DOCTYPE html>
<html lang="en">

<head>
  <!-- Use correct character set. -->
  <meta charset="utf-8">
  <!-- Tell IE to use the latest, best version. -->
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
  <meta name="viewport"
    content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
  <title>喇低喇賽</title>

  <style>
    @import url(./CesiumUnminified/Widgets/widgets.css);

    html,
    body,
    #cesiumContainer {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
      overflow: hidden;
    }

    /*去除 credits*/
    .cesium-widget-credits {
      display: none !important;
      visibility: hide !important;
    }


    #creditContainer {
      position: absolute;
      top: 0;
      left: 0;
      z-index: 3;
      visibility: visible;


      font-family: 微軟正黑體;
      font-size: 36pt;
      border-radius: 5px;
      padding: 3px;
      margin: 5px;
      color: white;
    }
  </style>
</head>

<body>
  <!--放logo用的-->
  <div id="creditContainer">
    喇低喇賽
  </div>

  <!--cesium本體-->
  <div id="cesiumContainer"></div>

  <script src="./CesiumUnminified/Cesium.js"></script>
  <script src="./jquery/jquery-3.3.1.js"></script>

  <script>
    //基本圖層
    imageryProviderViewModels = [];
    imageryProviderViewModels.push(new Cesium.ProviderViewModel({
      name: '開放街圖',
      iconUrl: Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/openStreetMap.png'),
      tooltip: '通用電子地圖',
      creationFunction: function () {
        var custom = new Cesium.UrlTemplateImageryProvider({
          url: 'http://127.0.0.1:5500/TGOS/{z}/{x}/{y}.png'
        });

        return custom;
      }
    }));

    var viewer = new Cesium.Viewer('cesiumContainer', {

      animation: false,
      baseLayerPicker: true,
      fullscreenButton: false,
      geocoder: false,
      homeButton: true,
      infoBox: true,
      sceneModePicker: false,
      selectionIndicator: true,
      timeline: false,
      navigationHelpButton: false,
      navigationInstructionsInitiallyVisible: false,
      scene3DOnly: true,
      clockViewModel: null,

      imageryProviderViewModels: imageryProviderViewModels
      //creditContainer: 'creditContainer'
    });

    viewer.camera.setView({
      destination: Cesium.Cartesian3.fromDegrees(120.827262, 24.608264, 1550000)
    });
  </script>
</body>

</html>

 

Openlayers 初體驗

載點

https://openlayers.org/download/

不知不覺中 Openlayers 已經從我剛開始用的 3.x 上升到了 5.x 我到現在只有更新到 4.x 。5.x 感覺變革還是挺多的用起來不太習慣。尤其是他官方的 example 全部都採用 import 真是很不方便… 所幸發現他有個老式的 QuickStart

關鍵就是要把他 import 的部分如創建 OSM 圖層時

new OSM 等價於 new ol.source.OSM

<!DOCTYPE html>
<html>

<head>
    <title>XYZ</title>
    <link rel="stylesheet" href="./v5.3.0-dist/ol.css" type="text/css">
    <style>
        body{
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
        .map{
            height:100%;
            width:100%;
        }
    </style>
</head>

<body>
    <div id="map" class="map"></div>
    <script src="./v5.3.0-dist/ol.js"></script>
    <script>
        var map = new ol.Map({
            target: 'map',
            layers: [
                new ol.layer.Tile({
                    source: new ol.source.XYZ({
                        url: 'http://127.0.0.1:5500/TGOS/{z}/{x}/{y}.png'
                    })
                })
            ],
            view: new ol.View({
                center: ol.proj.fromLonLat([120.5, 23.5]),
                zoom: 8
            })
        });
    </script>
</body>

</html>

NCL 安裝

方法1(推薦)

先至 ncl 官網下載
http://www.ncl.ucar.edu/Download/list_of_binaries.shtml

接著設定環境變數NCARG_ROOT

gedit ~/.bash_profile
export NCARG_ROOT=/home/yourname/ncl
export PATH=$NCARG_ROOT/bin:$PATH

最後別忘了讓設定啟用

source ~/.bash_profile

方法2

直接使用command安裝

sudo apt-get install ncl-ncarg

不過用這方法引用$NCARG_ROOT載入script時會出現錯誤

所以可以參考下面這篇的解法

http://mailman.ucar.edu/pipermail/ncl-install/2018-February/002567.html

加碼推薦 vscode NCL extension

由於 NCL 沒有比較好用的 editor ,某天寫網頁時無聊搜尋了一下,看看有無 NCL 的 extension 想不到還真的有,寫起來果真飛快。

GeoServer 安裝

先至官網下載最新版本目前為 2.15.0

http://geoserver.org/release/stable/

比較需要注意的是有兩種選項,我用於測試所以選擇Platform Independent Binary,日後正式環境跑在tomcat上在用 Web Archive (war) for servlet containers

啟動 GeoServer

cd geoserver-2.15.0java -jar start.jar

若 port 被其他服務占用則可以修改 start.ini 檔案,預設為 8080

#jetty.port=8080jetty.port=8088

啟動後,比較訝異的是以前使用 2.14 時會有很多預設的資料集,但在這個版本全部都不見了,不曉得是否因為我下載的是 Platform Independent Binary 的緣故,日後再研究。

測試發佈 WMS 服務,從 diva-gis.org 下載測台灣的 shapefile 檔案

http://www.diva-gis.org/gdata

Done!