GDAL是一個操做各類柵格地理數據格式的庫。包括讀取、寫入、轉換、處理各類柵格數據格式(有些特定的格式對一些操做如寫入等不支持)。它使用了一個單一的抽象數據模型就支持了大多數的柵格數據(GIS對柵格,矢量,3D數據模型的抽象能力實在使人歎服)。固然除了柵格操做,這個庫還同時包括了操做矢量數據的另外一個有名的庫ogr(ogr這個庫另外介紹),這樣這個庫就同時具有了操做柵格和矢量數據的能力,買一送一,這麼合算的買賣爲何不作。最最最重要的是這個庫是跨平臺的,開源的!現在這個庫對各類數據格式的支持強大到使人嘖嘖的地步了。若是你對他的強大有什麼懷疑的話,看看這裏一大串的GDAL所支持格式清單,嚇到了吧!再看看它的主頁最後那些使用了它做爲底層數據處理的軟件列表吧!其中你能夠不知道GRASS,你也能夠不知道Quantum GIS (QGIS),可是你總該知道Google Earth吧!
你即便不玩GIS,這個庫也是滿有用的。首先,哪一個庫支持這麼多柵格(圖片)格式,哪一個庫在C/C++/python/ruby/VB/java/C#(這個暫時不徹底支持)下都能用,並且都同樣用?退一步講,3S軟件又不必定要用在3S下(不少醫學影像就是用PCI軟件來處理的)。再退一步,你的生活即便和3S一點關係都沒有,柵格數據又不僅僅只有GIS下才用到。你大可用這個庫來讀取jpg,gif,tif,xpm等格式。並且對各類格式支持得不是通常的好,很大一部分非標準格式照樣支持得很是好。我曾經在java下玩過jai,以及一系列jai的擴展庫,一些圖像格式在不少圖片瀏覽器中均可以正確讀取(有的甚至不是非標準格式),用jai死活就讀不出來!
這個庫的python版和其餘的python庫結合的很好。最直接、明顯的支持是使用Numeric庫來進行數據讀取和操做。各類矩陣魔術能夠發揮得淋漓盡致(圖像其實就是矩陣)。並且按個人觀點,python對矩陣的操做比其餘的語言有明顯的優點。寫出來的東西比其餘語言寫出來的短小的多,並且好看得多。而且python的弱類型在處理柵格數據格式類型的時候代碼量比強類型的語言少了數倍(不用double,byte,short等等分開處理,這簡直就是先天上的優點)。因此我就喜歡用python作圖像的處理。因此就連GIS界的微軟ESRI也直接在ARCGIS9中用python來做柵格數據的導入導出。一句話,真是太方便啦!java
2. 安裝
2.1. windows下的安裝
官方安裝文檔在這裏。下面是我本身的實踐步驟:
先去http://www.gdal.org/dl/下一個版本,解壓。 打開控制檯,輸入: 「D:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" 註冊vc的編譯環境。
打 開gdal文件夾下的nmake.opt修改GDAL_HOME = "C:\warmerda\bld"把路徑改到須要把gdal安裝的地方。不改也能夠。這裏須要添加python支持,因此修改PY_INST_DIR = (GDAL_HOME)\pymod把路徑改爲python下的Lib\site-packages文件夾下。PYDIR = "C:\Software\Python24" 改爲python的安裝路徑。 下面的參數愛改什麼就把前面的#刪除(要看您有沒有那些庫的源碼),注意一下路徑就能夠了。我是都沒改。 後面就依次運行 Toggle line numbers 1 nmake /f makefile.vc 2 nmake /f makefile.vc install 3 nmake /f makefile.vc devinstall 最後最後,還要去GDAL_HOME目錄下的bin文件夾下把gdal13.dll (也有多是gdal12.dll)copy到PY_INST_DIR路徑下 到此處就完成安裝gdal(python)的工做。 最後須要注意一下,gdal在.net2005下只能順利編譯1.2,1.3以上版本不能順利編譯,有一個地方指針轉換出錯。多是2005的編譯器比以往的嚴厲一點吧。另外,安裝了QGIS,對編譯也有一些影響,主要是proj庫的衝突,致使一個找不到"d:/program.obj"文件的錯誤,若是你有靜態編譯過proj,那麼你能夠打開nmake.opt修改有關proj的設置,若是搞不定,就卸載QGIS,而後編譯,編譯後再安裝QGIS.呵呵,還好QGIS的體積沒有ArcGIS那麼可怕. 2.2. linux下的安裝 linux下的安裝就更簡單了。直接 Toggle line numbers 1 ./configure 2 make 3 su 4 make install 5 ldconfig 就ok(默認就已經支持python)。固然在第一步的時候須要看看是否依賴的庫都安裝了。若是缺乏,就去安裝一個。若是對configure的條件不理解,就用./configure --help看看具體狀況。 2.3. 安裝其餘驅動 這裏講一個安裝hdf4的驅動的例子(默認狀況下gdal是不安裝hdf4的),其餘驅動應該和這個也差不了多少吧,能夠做爲其餘的參考。完整步驟以下: 在windows下的安裝: 從ftp://ftp.ncsa.uiuc.edu/HDF/HDF/HDF%5FCurrent/bin/windows/下載42r1-win.ZIP,解壓。 編輯gdal根目錄下的nmake.opt,找到「# Uncomment the following and update to enable NCSA HDF Release 4 support.」這一行 把下面兩行前面的#去掉,而後改爲: HDF4_DIR = D:\warmerda\42r1-win\release #HDF4_LIB = /LIBPATH:<?XML:NAMESPACE PREFIX = "[default] http://www.w3.org/1998/Math/MathML" NS = "http://www.w3.org/1998/Math/MathML" />(GDAL_HOME)\pymod把路徑改爲python下的Lib\site-packages文件夾下。PYDIR = "C:\Software\Python24" 改爲python的安裝路徑。 下面的參數愛改什麼就把前面的#刪除(要看您有沒有那些庫的源碼),注意一下路徑就能夠了。我是都沒改。 後面就依次運行 Toggle line numbers 1 nmake /f makefile.vc 2 nmake /f makefile.vc install 3 nmake /f makefile.vc devinstall 最後最後,還要去GDAL_HOME目錄下的bin文件夾下把gdal13.dll (也有多是gdal12.dll)copy到PY_INST_DIR路徑下 到此處就完成安裝gdal(python)的工做。 最後須要注意一下,gdal在.net2005下只能順利編譯1.2,1.3以上版本不能順利編譯,有一個地方指針轉換出錯。多是2005的編譯器比以往的嚴厲一點吧。另外,安裝了QGIS,對編譯也有一些影響,主要是proj庫的衝突,致使一個找不到"d:/program.obj"文件的錯誤,若是你有靜態編譯過proj,那麼你能夠打開nmake.opt修改有關proj的設置,若是搞不定,就卸載QGIS,而後編譯,編譯後再安裝QGIS.呵呵,還好QGIS的體積沒有ArcGIS那麼可怕. 2.2. linux下的安裝 linux下的安裝就更簡單了。直接 Toggle line numbers 1 ./configure 2 make 3 su 4 make install 5 ldconfig 就ok(默認就已經支持python)。固然在第一步的時候須要看看是否依賴的庫都安裝了。若是缺乏,就去安裝一個。若是對configure的條件不理解,就用./configure --help看看具體狀況。 2.3. 安裝其餘驅動 這裏講一個安裝hdf4的驅動的例子(默認狀況下gdal是不安裝hdf4的),其餘驅動應該和這個也差不了多少吧,能夠做爲其餘的參考。完整步驟以下: 在windows下的安裝: 從ftp://ftp.ncsa.uiuc.edu/HDF/HDF/HDF%5FCurrent/bin/windows/下載42r1-win.ZIP,解壓。 編輯gdal根目錄下的nmake.opt,找到「# Uncomment the following and update to enable NCSA HDF Release 4 support.」這一行 把下面兩行前面的#去掉,而後改爲: HDF4_DIR = D:\warmerda\42r1-win\release #HDF4_LIB = /LIBPATH:(HDF4_DIR)\lib hd421m.lib
HDF4_LIB = (HDF4DIR)\dll\hd421m.lib(HDF4DIR)\dll\hd421m.lib(HDF4_DIR)\dll\hm421m.lib \
(HDF4DIR)\lib\hd421.lib(HDF4DIR)\lib\hd421.lib(HDF4_DIR)\lib\hm421.lib
用HDF4_LIB=/LIBPATH:這種形式彷佛能夠創建gdal的庫,可是往下編譯會出錯。並且要把(HDF4DIR)\dll和(HDF4DIR)\dll和(HDF4_DIR)\lib拷貝到同一個目錄下,否則會提示找不到庫
你也能夠試一試在D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat文件中添加HDF4_LIB路徑到「@set LIB=」這行的末尾(不要忘記;的分割符)。
而後找一下"INC="這行,把 -I(HDF4DIR)\include加到下一行的末尾(應該也能夠在vsvars32.bat中添加路徑,不過要重啓命令行)。而後編譯吧!祝你好運。注意:上面的HDF4DIR是我本機的路徑,你要根據你本身的路徑進行設置(想起個人一個老師說過的話:「抄人家的做業能夠,不要連名字也一塊兒抄走啊」),下面的(HDF4DIR)\include加到下一行的末尾(應該也能夠在vsvars32.bat中添加路徑,不過要重啓命令行)。而後編譯吧!祝你好運。注意:上面的HDF4DIR是我本機的路徑,你要根據你本身的路徑進行設置(想起個人一個老師說過的話:「抄人家的做業能夠,不要連名字也一塊兒抄走啊」),下面的(HDF4_DIR)能夠不用改,那個是變量,會自動替代HDF4_DIR 路徑。
編譯成功後,要HDF4能運行,還須要兩個庫,一個是zlib,一個是szip,能夠到下面兩個連接去下載一個
ftp://hdf.ncsa.uiuc.edu/lib-external/zlib/1.2/bin
ftp://hdf.ncsa.uiuc.edu/lib-external/szip/2.0/bin/windows
把這兩個庫下載後解壓,而後設置PATH系統變量,使得它們在默認狀態下也能夠被動態連接成功 。
在Linux下比在Windows下簡單:
只要用./configure --help察看一下打開HDF4的編譯開關(包括庫路徑,頭文件路徑等,看清楚),而後在./configure 後面加上那個開關以及hdf4的安裝路徑後就能夠了。在configure後gdal會提示是否支持HDF4。 編譯後也要把zlib和szip的動態連接庫設置好 。
到此你已經能夠用C/C++來操做gdal讀寫hdf4的格式了!
最後,爲了讓Python可以支持hdf的讀寫,別忘了把從新生成安裝後的pymod目錄下的內容,還有gdal13,還有那兩個hdf的庫,還有zlib,szip的庫拷貝到Python的Lib\site-packages目錄下 。
2.4. 下載
若是你實在玩不轉,能夠在這裏下載已經編譯好的gdal1.3.2程序庫 以及其依賴的其餘庫,其中包括hdf4,hdf5支持,以及proj,geos插件。注意,這裏的geos是靜態連接的,注意版權(geos是LGPL的license)。hdf4和hdf5用的是release版本。這裏是個人nmake配置文件,你能夠對照你的實際狀況參考一下。
3. 快速開始
其實在主站的教程裏已經有python的示例了。可是咱們仍是按照本身的思路來開始吧。
第一步就是打開一個數據集。對於「數據集」這個名詞你們可能不會太習慣,可是對於通常的格式來講,一個「數據集」就是一個文件,好比一個gif文件就是一個以gif爲擴展名的文件。可是對於衆多RS數據來講,一個數據集包含的絕對不只僅是一個文件。對於不少RS數據,他們把一張圖像分紅數個圖像文件,而後放在一個文件夾中,用一些額外的文件來組織它們之間的關係,造成一個「數據集」。若是你不理解,那麼就算了,當成jpg或者gif文件好了。
下面咱們打開一個tiff文件(GeoTIFF)。這個文件是我從GRASS的示例數據spearfish中導出的一個同名影像數據。
Toggle line numbers
1 >>> import gdal
2 >>> dataset = gdal.Open("j:/gisdata/gtif/spot.tif")
3 >>> dir(dataset)
4 ['AddBand', 'AdviseRead', 'BuildOverviews', 'FlushCache', 'GetDescription', 'Get
5 Driver', 'GetGCPCount', 'GetGCPProjection', 'GetGCPs', 'GetGeoTransform', 'GetMe
6 tadata', 'GetProjection', 'GetProjectionRef', 'GetRasterBand', 'GetSubDatasets',
7 'RasterCount', 'RasterXSize', 'RasterYSize', 'ReadAsArray', 'ReadRaster', 'Refr
8 eshBandInfo', 'SetDescription', 'SetGCPs', 'SetGeoTransform', 'SetMetadata', 'Se
9 tProjection', 'WriteRaster', '__del__', '__doc__', '__init__', '__module__', '_b
10 and', '_o']
11 >>>
這樣咱們就打開了這個文件。而且咱們能夠看到能夠供咱們調用的函數們(更具體的API列表能夠看這裏)。如今咱們不作修改,不作添加,因此只要帶有Set開頭的函數以及有Write開頭的函數咱們暫時都無論。由於RS影像必然要和地理上的位置掛上鉤,才能把圖像正確鋪展到一個座標系中。其中的信息和對應關係有點複雜,不適合在快速開始中介紹,咱們暫時也先無論。這裏須要注意的就是幾個函數。
GetDescription 得到柵格的描述信息。
Toggle line numbers
1 >>> dataset.GetDescription()
2 'j:/gisdata/gtif/spot.tif'
3 >>>
看來這裏的圖像描述是圖像的路徑名,可是這是和各類不一樣數據集相關的,不一樣數據集可能有不一樣的描述。這要看讀取驅動的實現做者的高興了。
RasterCount 得到柵格數據集的波段數。
GetRasterBand 得到柵格數據集的波段。
Toggle line numbers
1 >>> dataset.RasterCount
2 1
3 >>> band = dataset.GetRasterBand(1)
4 >>>
Band這個詞能夠翻譯成「波段。
這裏咱們獲取了第一個波段(紅色值組成的表)。注意!這裏的波段獲取和一般的C數組獲取不同,開始是1不是0。獲取了波段,咱們就能夠在下面的操做中讀取這個波段的全部數值。
RasterXSize 圖像的寬度(X方向上的像素個數)
RasterYSize 圖像的高度(Y方向上的像素個數)
Toggle line numbers
1 >>> dataset.RasterXSize
2 950
3 >>> dataset.RasterYSize
4 700
5 >>>
能夠看出咱們的圖像大小是950*700。仍是很小的一張圖。
ReadRaster 讀取圖像數據(以二進制的形式)
ReadAsArray 讀取圖像數據(以數組的形式)
Toggle line numbers
1 >>> help(dataset.ReadRaster)
2 Help on method ReadRaster in module gdal:
3 ReadRaster(self, xoff, yoff, xsize, ysize, buf_xsize=None, buf_ysize=None, buf_t
4 ype=None, band_list=None) method of gdal.Dataset instance
5 >>> help(dataset.ReadAsArray)
6 Help on method ReadAsArray in module gdal:
7 ReadAsArray(self, xoff=0, yoff=0, xsize=None, ysize=None) method of gdal.Dataset
8 instance
9 >>>
這兩個函數很重要,它們直接讀取圖像的數據,能夠看到兩個函數的幫助中有一大溜的參數。解釋一下: xoff,yoff,xsize,ysize 你可能不想讀取整張圖像。只想讀取其中的一部分。那麼就用xoff,yoff指定想要讀取的部分原點位置在整張圖像中距離全圖原點的位置。用xsize和ysize指定要讀取部分圖像的矩形大小。
buf_xsize buf_ysize 你能夠在讀取出一部分圖像後進行縮放。那麼就用這兩個參數來定義縮放後圖像最終的寬和高,gdal將幫你縮放到這個大小。
buf_type 若是你要讀取的圖像的數據類型不是你想要的(好比原圖數據類型是short,你要把它們縮小成byte),就能夠設置它。
band_list 這就適應上面多波段的狀況。你能夠指定讀取的波段序列。要哪幾個波段,不要哪幾個波段,你說了算。
舉個例子吧:
Toggle line numbers
1 >>> dataset.ReadAsArray(230,270,10,10)
2 array([[255, 255, 255, 232, 232, 255, 255, 255, 255, 222],
3 [255, 255, 255, 255, 255, 255, 210, 110, 11, 122],
4 [255, 255, 255, 255, 255, 255, 210, 255, 11, 243],
5 [201, 255, 255, 255, 255, 200, 200, 110, 122, 243],
6 [111, 211, 255, 201, 255, 255, 100, 11, 132, 243],
7 [255, 100, 100, 100, 110, 100, 110, 111, 122, 243],
8 [255, 255, 255, 255, 255, 255, 122, 222, 255, 255],
9 [255, 255, 255, 255, 255, 255, 243, 243, 255, 255],
10 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
11 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]],'b')
12 >>> dataset.ReadRaster(230,270,10,10)
13 '\xff\xff\xff\xe8\xe8\xff\xff\xff\xff\xde\xff\xff\xff\xff\xff\xff\xd2n\x0bz\xff\
14 xff\xff\xff\xff\xff\xd2\xff\x0b\xf3\xc9\xff\xff\xff\xff\xc8\xc8nz\xf3o\xd3\xff\x
15 c9\xff\xffd\x0b\x84\xf3\xffdddndnoz\xf3\xff\xff\xff\xff\xff\xffz\xde\xff\xff\xff
16 \xff\xff\xff\xff\xff\xf3\xf3\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff
17 \xff\xff\xff\xff\xff\xff\xff\xff\xff'
18 >>>
咱們就把圖像中位於230,270,寬度10高度10的數據讀取出來了。
咱們看完了數據集的主要函數。彷佛已經夠用了。的確,若是隻是爲了顯示圖像,這些的確已經夠了。可是若是須要更多信息,咱們就不得不進入波段操做數據(實際上咱們大多數時候都須要進入band獲取信息)。下面咱們如今來看看剛纔讀取出來的那個band有些什麼東西能夠供咱們操做的(具體的API列表看這裏)。
Toggle line numbers
1 >>> dir(band)
2 ['AdviseRead', 'Checksum', 'ComputeBandStats', 'ComputeRasterMinMax', 'DataType'
3 , 'Fill', 'FlushCache', 'GetDefaultHistogram', 'GetDescription', 'GetHistogram',
4 'GetMaximum', 'GetMetadata', 'GetMinimum', 'GetNoDataValue', 'GetOffset', 'GetO
5 verview', 'GetOverviewCount', 'GetRasterColorInterpretation', 'GetRasterColorTab
6 le', 'GetScale', 'GetStatistics', 'ReadAsArray', 'ReadRaster', 'SetDefaultHistog
7 ram', 'SetDescription', 'SetMetadata', 'SetNoDataValue', 'SetRasterColorInterpre
8 tation', 'SetRasterColorTable', 'WriteArray', 'WriteRaster', 'XSize', 'YSize', '
9 __doc__', '__init__', '__module__', '_o']
10 >>>
挑幾個有用的吧。
Toggle line numbers
1 >>> band.XSize
2 950
3 >>> band.YSize
4 700
5 >>> band.DataType
6 1
7 >>>
不用解釋了吧,波段圖像的寬和高(象元爲單位)。DataType,圖像中實際數值的數據類型。具體數據類型定義在gdalconst模塊裏。使用的時候用import gdalconst引入。
Toggle line numbers
1 >>> import gdalconst
2 >>> dir(gdalconst)
3 ['CE_Debug', 'CE_Failure', 'CE_Fatal', 'CE_None', 'CE_Warning', 'CPLES_Backslash
4 Quotable', 'CPLES_CSV', 'CPLES_SQL', 'CPLES_URL', 'CPLES_XML', 'CPLE_AppDefined'
5 , 'CPLE_AssertionFailed', 'CPLE_FileIO', 'CPLE_IllegalArg', 'CPLE_NoWriteAccess'
6 , 'CPLE_None', 'CPLE_NotSupported', 'CPLE_OpenFailed', 'CPLE_OutOfMemory', 'CPLE
7 _UserInterrupt', 'CXT_Attribute', 'CXT_Comment', 'CXT_Element', 'CXT_Literal', '
8 CXT_Text', 'DCAP_CREATE', 'DCAP_CREATECOPY', 'DMD_CREATIONDATATYPES', 'DMD_CREAT
9 IONOPTIONLIST', 'DMD_EXTENSION', 'DMD_HELPTOPIC', 'DMD_LONGNAME', 'DMD_MIMETYPE'
10 , 'GA_ReadOnly', 'GA_Update', 'GCI_AlphaBand', 'GCI_BlackBand', 'GCI_BlueBand',
11 'GCI_CyanBand', 'GCI_GrayIndex', 'GCI_GreenBand', 'GCI_HueBand', 'GCI_LightnessB
12 and', 'GCI_MagentaBand', 'GCI_PaletteIndex', 'GCI_RedBand', 'GCI_SaturationBand'
13 , 'GCI_Undefined', 'GCI_YellowBand', 'GDT_Byte', 'GDT_CFloat32', 'GDT_CFloat64',
14 'GDT_CInt16', 'GDT_CInt32', 'GDT_Float32', 'GDT_Float64', 'GDT_Int16', 'GDT_Int
15 32', 'GDT_TypeCount', 'GDT_UInt16', 'GDT_UInt32', 'GDT_Unknown', 'GF_Read', 'GF_
16 Write', 'GPI_CMYK', 'GPI_Gray', 'GPI_HLS', 'GPI_RGB', 'GRA_Bilinear', 'GRA_Cubic
17 ', 'GRA_CubicSpline', 'GRA_NearestNeighbour', '__builtins__', '__doc__', '__file
18 __', '__name__']
19 >>>
那些GDT開頭的就是數值數據類型。
Toggle line numbers
1 >>> band.GetNoDataValue()
2 65535.0
3 >>> band.GetMaximum()
4 >>> band.GetMinimum()
5 >>> band.ComputeRasterMinMax()
6 (1.0, 255.0)
7 >>>
Maximum 是表示在本波段數值中最大的值,Minimum固然就是表示本波段中最小的值啦。咱們能夠看到在一開始這兩個都沒有值。由於對於文件格式不會有固有的最大最小值。因此咱們經過函數ComputeRasterMinMax計算獲得了。注意!這裏的最大最小值不包括「無心義值」!也就是上面顯示的NoDataValue。須要解釋一下「無心義值」。不要覺得0或者255在任何狀況下都無心義。在不少狀況下0,255須要和其餘值同樣表示一個實際意義。雖然可能它最終會被顯示得和黑色同樣。而一些位置上的點要表示的意思是「什麼也不是」,它在那個位置上只是爲了佔一個位置,使得總體圖像看起來像個矩形而已。在作實際應用的時候兩種值的處理將會徹底不同。因此須要設置無心義值,來和其餘的值區別開來。而用ComputeRasterMinMax算出的最大最小值,是排除了無心義值後計算出來的最大最小值。
Toggle line numbers
1 >>> band.GetRasterColorInterpretation()
2 2
3 >>> gdalconst.GCI_PaletteIndex
4 2
5 >>> colormap = band.GetRasterColorTable()
6 >>> dir(colormap)
7 ['Clone', 'GetColorEntry', 'GetColorEntryAsRGB', 'GetCount', 'GetPaletteInterpre
8 tation', 'SetColorEntry', '__del__', '__doc__', '__init__', '__module__', '__str
9 __', '_o', 'own_o', 'serialize']
10 >>> colormap.GetCount()
11 256
12 >>> colormap.GetPaletteInterpretation()
13 1
14 >>> gdalconst.GPI_RGB
15 1
16 >>> for i in range(colormap.GetCount()):
17 ... print colormap.GetColorEntry(i),
18 ...
19 (0, 0, 0, 255) (0, 0, 28, 255) (0, 0, 56, 255) (0, 0, 85, 255) (0, 0, 113, 255)
20 (0, 0, 142, 255) (0, 0, 170, 255) (0, 0, 199, 255) (0, 0, 227, 255) (0, 0, 255,
21 255) (0, 28, 0, 255) (0, 28, 28, 255) (0, 28, 56, 255) (0, 28, 85, 255) (0, 28,
22 113, 255) (0, 28, 142, 255) (0, 28, 170, 255) (0, 28, 199, 255) (0, 28, 227, 255
23 ) (0, 28, 255, 255) (0, 56, 0, 255) (0, 56, 28, 255) (0, 56, 56, 255) (0, 56, 85
24 , 255) (0, 56, 113, 255) (0, 56, 142, 255) (0, 56, 170, 255) (0, 56, 199, 255) (
25 0, 56, 227, 255) (0, 56, 255, 255) (0, 85, 0, 255) (0, 85, 28, 255) (0, 85, 56,
26 255) (0, 85, 85, 255) (0, 85, 113, 255) (0, 85, 142, 255) (0, 85, 170, 255) (0,
27 85, 199, 255) (0, 85, 227, 255) (0, 85, 255, 255) (0, 113, 0, 255) (0, 113, 28,
28 255) (0, 113, 56, 255) (0, 113, 85, 255) (0, 113, 113, 255) (0, 113, 142, 255) (
29 0, 113, 170, 255) (0, 113, 199, 255) (0, 113, 227, 255) (0, 113, 255, 255) (0, 1
30 42, 0, 255) (0, 142, 28, 255) (0, 142, 56, 255) (0, 142, 85, 255) (0, 142, 113,
31 255) (0, 142, 142, 255) (0, 142, 170, 255) (0, 142, 199, 255) (0, 142, 227, 255)
32 (0, 142, 255, 255) (0, 170, 0, 255) (0, 170, 28, 255) (0, 170, 56, 255) (0, 170
33 , 85, 255) (0, 170, 113, 255) (0, 170, 142, 255) (0, 170, 170, 255) (0, 170, 199
34 , 255) (0, 170, 227, 255) (0, 170, 255, 255) (0, 199, 0, 255) (0, 199, 28, 255)
35 (0, 199, 56, 255) (0, 199, 85, 255) (0, 199, 113, 255) (0, 199, 142, 255) (0, 19
36 9, 170, 255) (0, 199, 199, 255) (0, 199, 227, 255) (0, 199, 255, 255) (0, 227, 0
37 , 255) (0, 227, 28, 255) (0, 227, 56, 255) (0, 227, 85, 255) (0, 227, 113, 255)
38 (0, 227, 142, 255) (0, 227, 170, 255) (0, 227, 199, 255) (0, 227, 227, 255) (0,
39 227, 255, 255) (0, 255, 0, 255) (0, 255, 28, 255) (0, 255, 56, 255) (0, 255, 85,
40 255) (0, 255, 113, 255) (0, 255, 142, 255) (0, 255, 170, 255) (0, 255, 199, 255
41 ) (0, 255, 227, 255) (0, 255, 255, 255) (28, 0, 0, 255) (28, 0, 28, 255) (28, 0,
42 56, 255) (28, 0, 85, 255) (28, 0, 113, 255) (28, 0, 142, 255) (28, 0, 170, 255)
43 (28, 0, 199, 255) (28, 0, 227, 255) (28, 0, 255, 255) (28, 28, 0, 255) (28, 28,
44 28, 255) (28, 28, 56, 255) (28, 28, 85, 255) (28, 28, 113, 255) (28, 28, 142, 2
45 55) (28, 28, 170, 255) (28, 28, 199, 255) (28, 28, 227, 255) (28, 28, 255, 255)
46 (28, 56, 0, 255) (28, 56, 28, 255) (28, 56, 56, 255) (28, 56, 85, 255) (28, 56,
47 113, 255) (28, 56, 142, 255) (28, 56, 170, 255) (28, 56, 199, 255) (28, 56, 227,
48 255) (28, 56, 255, 255) (28, 85, 0, 255) (28, 85, 28, 255) (28, 85, 56, 255) (2
49 8, 85, 85, 255) (28, 85, 113, 255) (28, 85, 142, 255) (28, 85, 170, 255) (28, 85
50>>>
經過GetRasterColorInterpretation,咱們知道咱們的圖像是一個顏色表索引的圖像而不是純粹的黑白灰度圖像(PaletteIndex,其餘的顏色模型,能夠察看gdalconst模塊中GCI打頭的枚舉值)。這意味着咱們讀出的數據有可能不是真實的數據。這些數據只是一個個實際數據的索引。真實數據存儲在另外一個表中。咱們經過ReadRaster讀出的數據值只是對應到這個表的一個索引而已。咱們須要經過讀出這些數據,並在真實數據表中找出真實數據,從新組織成一個RGB表才能用來繪製。若是咱們不通過對應,咱們繪製出來的東西可能什麼東西都不是。
用GetRasterColorTable得到了顏色表,經過GetPaletteInterpretation咱們知道咱們得到的顏色表是一個RGB顏色表。GDAL支持多種顏色表,具體能夠參考gdalconst模塊中GPI打頭的枚舉值。而後咱們能夠經過GetCount得到顏色的數量。經過GetColorEntry得到顏色表中的值。這裏的顏色值都是一個4值的元組。裏面有意義的只有前三個(若是顏色模型是GPI_RGB, GPI_HLS,都使用前3個,若是採用GPI_CMYK,則4個值都有意義了)。
Toggle line numbers
1 >>> help(band.ReadAsArray)
2 Help on method ReadAsArray in module gdal:
3 ReadAsArray(self, xoff=0, yoff=0, win_xsize=None, win_ysize=None, buf_xsize=None
4 , buf_ysize=None, buf_obj=None) method of gdal.Band instance
5 >>> help(band.ReadRaster)
6 Help on method ReadRaster in module gdal:
7 ReadRaster(self, xoff, yoff, xsize, ysize, buf_xsize=None, buf_ysize=None, buf_t
8 ype=None) method of gdal.Band instance
9 >>>
顯然,band裏的ReadAsArray參數顯然比dataset裏面的要好用,而ReadRaster則差很少。可是ReadAsArray讀出的是數組,能夠用Numeric模塊進行矩陣魔法。ReadRaster讀出的是二進制,雖然能夠直接繪製,可是對於一些繪圖API來講,對[[RRR...][GGG...][BBB...]]表的處理明顯不如[[RGB][RGB]...],有的甚至不支持。雖然能夠用struct.unpack來拆封,可效率上就差不少(並且拆封出來仍是數組)。數組在矩陣魔法的控制之下則會顯得十分方便快捷,最後用tostring直接轉化稱爲二進制繪製,速度也至關快。
好了,快速開始已經使咱們能夠初步看清楚了gdal中圖像的組織。下面用一句話總結一下:波段組成圖像,波段指揮顏色。python