Qt OpenGL教程 29 Blitter函式

2021-07-04 15:15:51 字數 4259 閱讀 4169

第29課:blitter函式 (參照nehe)

這次教程中,我們將介紹類似於directdraw的blit(其實blit函式在許多繪相簿都有),我們將用**自己來實現它。它的作用非常簡單,就是把一塊紋理的貼到另一塊紋理上。想想,有了這個函式,我們就可以自由拼接紋理了,是不是很棒?

這一課中,我們不但會實現blit函式,我們還將講解如何來載入特定的*.raw。raw格式的,可以理解為cmos或者ccd影象感應器將捕捉到的光源訊號轉化為數碼訊號的原始資料。可悲的是,qt並沒有提供載入raw的方法,所以我們只能自己寫了(這是處理影象的一課,與opengl關係不大)!

程式執行時效果如下:

下面進入教程:

我們這次將在第06課的基礎上修改**,我們只講解新的內容,舊的內容到這裡大家應該掌握得很好了才對。首先開啟myglwidget.h檔案,將類宣告修改如下:

#ifndef myglwidget_h

#define myglwidget_h

#include #include typedef struct texture_image //影象結構體

* p_texture_image;

class myglwidget : public qglwidget

;#endif // myglwidget_h

首先我們新定義了乙個結構體texture_image,把其指標重新命名為p_texture_image。結構體中width、height指影象畫素的寬和高;format指每乙個畫素的位深,也就是每乙個畫素所佔的記憶體大小;data指向用於儲存影象資料的記憶體。接著我們定義了該結構體的兩個指標t1、t2。最後,我們宣告了5個新的函式,函式的作用大家先看注釋,後面定義的時候再一起解釋。

接下來,我們需要開啟myglwidget.cpp,加上宣告#include ,對建構函式進行修改,很簡單不多解釋,具體**如下:

myglwidget::myglwidget(qwidget *parent) :

qglwidget(parent)

下面,我們來看allocatetexturebuffer()、deallocatetexture()函式的定義,具體**如下:

p_texture_image myglwidget::allocatetexturebuffer(gluint w, gluint h, gluint f)

else

}else

return ti; //返回影象結構體指標

}

void myglwidget::deallocatetexture(p_texture_image t)

free(t); //釋放影象結構體的記憶體}}

首先是allocatetexturebuffer()函式,這個函式用來為影象結構體分配記憶體。函式中,我們為ti和c分別分配記憶體,其中為c分配時,其大小是w*h*f;然後如果分配不成功,則利用qmessagebox來報告錯誤,並退出程式。

然後是deallocatetexture()函式,這個函式用來釋放我們分配的記憶體。函式中,我們把t和data指向的記憶體都釋放掉。

繼續,我們來看loadrawdata()和buildtexture()函式的定義,具體**如下:

void myglwidget::loadrawdata(const char *filename, p_texture_image buffer)

*p = 255; //把255儲存在alpha通道中

p++;}}

fclose(f); //關閉檔案

}else

}

gluint myglwidget::buildtexture(p_texture_image tex)

首先是loadrawdata()函式,這個函式用於載入raw影象的資料

。我在網上查到raw影象的格式似乎根據硬體的不同,是由差別的,所以nehe給的這個函式應該是只針對他給的是有效的(雖然有點可惜,但是我們還是有收穫的)。函式中,我們先定義了變數stride來儲存每一行資料的位元組數,接著開啟檔案,如果檔案不存在則報錯退出程式;如果檔案存在,我們通過乙個迴圈來讀取我們的資料,我們從影象的最下面一行開始,一向上行一行地讀取每一行的資料。然後我們再利用乙個迴圈來讀取每一行的資料,並在內層再加乙個迴圈來讀取每乙個畫素的資料,並把alpha設定為255。

然後是buildtexture()函式,這個函式利用我們定義的影象結構體裡的資料來建立紋理。一開始呼叫glgentextures為紋理分配空間,然後繫結紋理,設定過濾器,然後利用結構體裡的資料建立乙個紋理,最後返回紋理的位址。

還有,我們來定義blit函式,這才是我們這節課的重點,前面4個函式都是直接或間接為了這個函式作鋪墊,具體**如下:

/*blit函式將乙個紋理貼到另乙個紋理上

* src為源影象,dst為目標影象

* src_xstart,src_ystart為要複製的部分在源影象中的位置

* src_width,src_height為複製的部分的寬度和高度

* dst_xstart,dst_ystart為複製到目標影象時的起始位置

* blend設定是否啟用混合,true為啟用,false為不啟用

* alpha設定源影象中在混合時所佔的百分比

*/void myglwidget::blit(p_texture_image src, p_texture_image dst, int src_xstart,

int src_ystart, int src_width, int src_height,

int dst_xstart, int dst_ystart, bool blend, int alpha)

if (alpha < 0)

//計算要複製的畫素在源影象資料中的開始行

unsigned char *s = src->data + (src_ystart*src->width*src->format);

//計算要複製的畫素在目標影象資料中的開始行

unsigned char *d = dst->data + (dst_ystart*dst->width*dst->format);

for (int i=0; iformat); //移動到這一行要複製畫素的開始位置

d = d + (dst_xstart*dst->format);

for (int j=0; jformat; k++, d++, s++) //複製每乙個位元組

else}}

//移動到下一行

d = d + (dst->width - (src_width+dst_xstart))*dst->format;

s = s + (src->width - (src_width+src_xstart))*src->format;}}

函式的引數有點多,在函式開頭有各個引數的注釋,大家自己看。一開始,我們先保證傳進來的alpha值為0~255,接著我們讓指標s和d分別指向源影象和目標影象要複製的起始行。進入迴圈,我們讓s和d指向當前行要複製的畫素的開始位置,然後迴圈複製每一行。複製過程,我們檢查blend是否為true,如果為true,則根據alpha的值計算顏色值,否則直接複製顏色值,一次迴圈的結束,把指標s和d移動到需要要複製的下一行。

最後,對於initializegl()、resizegl()、paintgl()函式,後兩個函式可以繼續用第06課的,我們只需要修改initializegl()函式,具體**如下:

void myglwidget::initializegl()                         //此處開始對opengl進行所以設定

函式只是做了小的改動,我們自己呼叫自己寫的函式為影象分配記憶體,讀入資料,完成拼接,轉換為紋理後,我們釋放了之前分配的記憶體。並不難理解,大家自己看吧。

現在就可以執行程式檢視效果了!

Qt OpenGL教程 20 蒙板

第20課 蒙板 參照nehe 這次教程中,我們教介紹opengl的蒙板技術。到目前為止,我們已經學會如何使用alpha混合,把乙個透明物體渲染到螢幕上了,但有時使用它看起來並不是那麼的復合我們的心意。使用蒙板技術,將會使影象按照我們設定的蒙板位置精確地繪製。直到現在,我們在把影象載入到螢幕上時都沒有...

Qt OpenGL教程 16 看起來很酷的霧

第16課 看起來很酷的霧 參照nehe 程式執行時效果如下 下面進入教程 我們這次將在第07課的基礎上修改 我只會講解有修改的部分,希望大家先找到第07課的 再跟著我一步步走。首先開啟myglwidget.h檔案,將類宣告更改如下 ifndef myglwidget h define myglwid...

菜鳥教程 練習例項29 (python3)

題目 給乙個不多於5位的正整數,要求 一 求它是幾位數,二 逆序列印出各位數字。程式分析 學會分解出每一位數。coding utf 8 defmain sum 1 int input 請輸入乙個數 a int sum 1 10000 b int sum 1 1000 10 c int sum 1 1...