2012-08-16 53 views
0

這是我的情況:我需要預先加載2000張圖像並按順序將它們顯示爲60 fps的動畫。目前,我使用OpenGL加載bmp文件,但由於內存限制,我只能預加載多達500多個圖像。我怎麼解決這個問題?到目前爲止,我可以想出兩個解決方案:首先,也許我可以加載8位bmp圖像來節省內存。但我在使用glDrawPixels時遇到困難。其次,如果可能,我可以直接加載jpeg嗎?感謝您的任何建議!如何使用OpenGL加載8位bmp?

不使用視頻的原因是我需要通過跳過一個或多個圖像來更改動畫速度,如代碼中所示(imgCount + = stp; // stp表示有多少圖像可以逃脫。視頻更快)。而在我的動畫中,幀率非常重要,低於50的FPS顯示閃爍。

下面是代碼:

void Frame::LoadBMP(void){ 

FILE *in; 


in=fopen(file,"rb");//open file 
if(in==NULL){ 

    exit(0); 
} 
fread(&(this->bmfh),sizeof(BITMAPFILEHEADER),1,in);//read bmp file header 
fread(&(this->bmih),sizeof(BITMAPINFOHEADER),1,in);//read bmp infomation header 

colours=new RGBQUAD[bmih.biBitCount]; 
fread(colours,sizeof(RGBQUAD),bmih.biBitCount,in);//read bmp colour table 

size=bmfh.bfSize-bmfh.bfOffBits; 
tempPixelData=new GLubyte[size]; 

if(tempPixelData==NULL) { 
    fclose(in); 
} 
fread(tempPixelData,sizeof(GLubyte),size,in);//read bmp image data 
fclose(in); 
} 

,我將顯示圖像序列,顯示代碼:

void display(void){ 

static clock_t start=clock(); 
static clock_t end=clock(); 

CurrtempPixelData=msFrame[offset]->tempPixelData; 

glEnable(GL_ALPHA_TEST); 
glEnable(GL_BLEND); 

glDrawPixels(frWidth, frHeight, GL_RGBA, GL_UNSIGNED_BYTE, msFrame[offset]->tempPixelData); 

for(int i=0;i<m;i++){ 
    clock_t c=clock(); 
} 

glutSwapBuffers(); 
imgCount+=stp; // stp means how many images to escape. it can make video faster. 
offset=imgCount%numFrame; 
glutPostRedisplay(); 

} 
+1

您無法首先在OpenGL中加載位圖,所以我猜JPEG不會更容易。但考慮使用壓縮紋理,無論您如何加載實際圖像數據。 – 2012-08-16 07:40:59

回答

2

您不應該使用glDrawPixels,這是不建議使用的功能。做到這一點的最好方法可能是繪製一個屏幕大小的四邊形(-1,-1 => 1,1,沒有任何矩陣變換),用這些圖像紋理化。

對於紋理,您可以在glTexImage2D和類似功能中指定幾種內部格式。例如,您可以使用GL_R3_G3_B2​格式來獲得8位大小,但也可以使用壓縮格式,如S3TC。例如,您可以通過COMPRESSED_SRGB_S3TC_DXT1_EXT,這應該將您的圖像大小減少到每像素4位,這可能比8位格式的質量更好。您不能在OpenGL中將JPEG用作壓縮格式(這太複雜了)。

最後,你爲什麼要通過OpenGL來做到這一點?將圖像傳輸到常規窗口可能會給您足夠的性能。然後你甚至可以將你的圖像序列存儲爲視頻,然後將解碼幀輸出。在這種情況下,你不可能得到內存問題。

+0

感謝KillianDS您的有用建議。我會稍後再嘗試。而我之所以使用OpenGL只是爲了方便。其實,我最初使用C#來播放我的圖像序列。但它有一個輕彈的問題,所以我改用OpenGL。你能解釋一下「將圖像傳送到常規窗口」是什麼意思嗎?如何實現這一目標?聽起來像一個簡單的解決方案!由於我對編程非常陌生,所以感謝您的耐心等待! – 2012-08-19 15:38:28

+0

在大多數窗口API中,您可以直接在窗口/屏幕上繪製矩形,這個一般過程稱爲blitting(將矩形繪製到另一個矩形)。確切的接口依賴於API到API,例如在SDL中,您將使用['SDL_BlitSurface'](http://www.libsdl.org/docs/html/sdlblitsurface.html) – KillianDS 2012-08-20 06:29:44

2

也許你並不需要有2000張圖像,並在顯示出來60fps呢?穩定的25fps對於任何電影來說都足夠了。

我鼓勵你重新考慮你最初的問題,並提出了一個更適合的解決方案(視頻,動畫,向量,也許別的東西)

至於原來的問題:

如果你需要的圖像只有一次 - 當你需要它們時把它們記憶到內存中,並在顯示後立即丟棄它們。

使用DXT打包圖像。質量略有下降,可以獲得恆定的x4/x8壓縮比。

如今,OpenGL並不擅長處理調色板的紋理(許多供應商實施不善)。但是你可以用着色器來實現它。

+0

謝謝你,克羅姆。你的建議非常鼓舞人心。你是對的,我可以使用視頻。但就我而言,我需要在播放動畫的過程中進行一些操作,特別是我需要改變動畫的速度。總而言之,我有7種不同的速度條件。所以,在開始時,我想可能更容易將一個數組中的所有圖像記錄下來,然後對其進行循環。所以我得到了內存問題。 – 2012-08-19 15:17:41