何杰 王大立
摘要:在化工仿真中,為了貼近真實,可以將實物圖片貼于所繪化工單元設備、管道、框架、廠房等結構體表面。BMP圖像可被用作紋理圖。依據圖像顏色點陣數據(WinHex),編寫相關程序可對位圖進行像素級編輯,實現如顏色拾取、圖片移動、旋轉、翻轉、鏡像、摳圖等變換操作。作者編寫了位圖旋轉變換操作程序 (Visual C++,OpenGL),為將計算機圖形學編程用于化工仿真、虛擬現實進行了應用基礎研究;在程序for循環主代碼中,用“fread(&pixVal, sizeof(BYTE), 1, fp);”讀數據,用“fwrite(&pixVal, sizeof(BYTE), 1, pFile);”寫數據。其基本操作過程與手工刺繡或搭積木類似。讓計算機程序組織那些像素點“對號入座”,有秩序地從原圖像素網格中取出一個個像素單元格,再有秩序地放入變換后圖像像素網格中,實現預想像素級圖像變換操作。
關鍵詞:圖形學編程;位圖旋轉;像素讀寫;位圖;化工仿真;虛擬現實
中圖分類號:TN919.8? ? ?文獻標識碼:A
文章編號:1009-3044(2021)25-0004-03
在化工設計中,常用制圖軟件是AutoCAD, 3DS MAX, SOLIDWORKS, SketchUp等。這些軟件基本共同使用方法是主要通過操作鼠標、鍵盤直接在電腦屏幕上繪制出各種圖元,即點、線、面、體,再排列、組合,得到特定組合結構、形體、場景,所見即所得。另一區別制圖方法是,編寫、運行計算機制圖程序,生成目標圖形、場景。兩者各有優劣。在虛擬現實中,需要展現真實感圖形、場景、實現人機交互、動畫、視圖旋轉、漫游、科學計算可視化、仿真實驗等,后者對這些提供了可能,而且實現起來便捷、高效,程序運行流暢、穩定[1-6]。它在虛擬現實、化工仿真中獨樹一幟,不容小覷。可它目前并不為化工專業人員所普遍知曉,也很少被使用。
紋理映射允許把一個現實場景圖貼于3D結構體表面,更逼真,在虛擬現實(VR)場景模擬中作用突出。使用OpenGL (Open Graphics Library) 編程接口,能夠增強三維場景真實性。OpenGL提供了位圖操作函數。它是被用于渲染2D、3D矢量圖形、跨語言、跨平臺的應用程序編程接口。實現用C++結合OpenGL制作出一個虛擬化工廠,類似使用AutoCAD Plant 3D,可以考慮先用C++結合OpenGL繪制出化工3D圖形結構單元。然而,相比一般3D建模軟件,OpenGL并非卓爾不群,自成一格。將OpenGL與一般3D建模軟件結合起來,相輔相成,更行之有效。柳暗花明又一村,原來,由于OpenGL是圖形底層圖形庫,沒有提供幾何實體圖元,不能被直接用以描述場景。但是,通過一些轉換程序,可以很方便地提取出自AutoCAD, 3DS MAX, SOLIDWORKS等的DXF, 3DS, OBJ, STL模型文件OpenGL頂點數組,進而對其再處理[7-9]。
宋葉未等[10]對BMP格式位圖文件結構和內容進行了詳細分析,給出了一種通用、易于移植的BMP格式位圖文件顯示算法。尹航等[11]討論了在VS2005環境下借助OpenGL和第三方庫CxImage,利用PNG圖片進行紋理映射。CxImage類庫是一個優秀圖像操作類庫,可以被用來快捷存取、顯示、轉換各種圖像。薛兆井等[12]研究了基于OpenGL讀取bmp圖像實現紋理映射的一種新方法。韓姣[13]探討了在VC++環境下BMP與GIF圖像文件格式轉換,編程實現了BMP圖像讀取、顯示和保存等相關操作。本文作者用C++結合OpenGL編寫了計算機程序,實現了位圖旋轉變換操作。
1 Bitmap-File解析
BMP文件由文件頭 (bitmap-file header)、信息頭 (bitmap-information header)、彩色表 (color table) 和位圖數據 (bitmap data) 四部分組成。如圖1a所示,點 (0,0) 和點 (514,0) 在其圖像數據表中對應No. 267289 pixel, No. 267803 pixel。其間點數是(267803-267289)+1=515 points,與例圖寬515 pixels吻合。在圖像數據表末,自左向右“F6 F6F6”分別表示該像素顏色BGR值,對應原圖10進制RGB分量, “246 246 246”,一致。如圖1b所示,隨意指定原圖中一點 (45,194),檢索到該點在圖像數據表中相應位置。
2 4 Bytes對齊問題
BMP文件有個重要特性是對于圖像數據區域,位圖每一行像素所占Byte數必須被4整除,否則,在該位圖每一行16進制碼末尾補1至3 Bytes “00”。“補零”只針對位圖寬檢驗。要行補位是因為32位Windows操作系統4-Bytes (32位) 處理速度較快。一個掃描行所占Byte數:(biwidth*biBitCount/8+3)/4*4或(biWidth*biBitCount+31)/32*4或((width*biBitCount+31) >> 5)<< 2。其中,如圖1,其每行數據大小為515 pixels×3 Bytes/pixel = 1545 Bytes,不能被4整除,用“000000”補全,變為1548 Bytes ((515*24+31)/32*4=1548)。第515列為行補位列。同樣,VC++程序讀入BMP圖像,必須把每行Byte數轉換為4整數倍 (即以long為單位)。
biWidth 圖像寬度,以pixel為單位。
biBitCount bits/pixel
biWidth*biBitCount 一行所占位數