3、glDrawPixels 的用法和舉例
glDrawPixels:繪制一些像素。目前可以簡單了解為“把記憶體中一些資料作為像素資料,進行繪制”。
glDrawPixels 函數與 glReadPixels 函數相比,參數内容大緻相同。它的第一、二、三、四個參數分别對應于 glReadPixels 函數的第三、四、五、六個參數,依次表示圖象寬度、圖象高度、像素資料内容、像素資料在記憶體中的格式。兩個函數的最後一個參數也是對應的,glReadPixels 中表示像素讀取後存放在記憶體中的位置,glDrawPixels 則表示用于繪制的像素資料在記憶體中的位置。
注意到 glDrawPixels 函數比 glReadPixels 函數少了兩個參數,這兩個參數在glReadPixels 中分别是表示圖象的起始位置。在 glDrawPixels 中,不必顯式的指定繪制的位置,這是因為繪制的位置是由另一個函數 glRasterPos來指定的。glRasterPos函數的參數與 glVertex*類似,通過指定一個二維/三維/四維坐标,OpenGL 将自動計算出該坐标對應的螢幕位置,并把該位置作為繪制像素的起始位置。
自己畫一個dummy.bmp檔案,程式如下
// glDrawPixels舉例.cpp : 此檔案包含 "main" 函數。程式執行将在此處開始并結束。
#include "pch.h"
#include <iostream>
#include <gl/glut.h>
#define FileName "dummy.bmp"
static GLint ImageWidth;
static GLint ImageHeight;
static GLint PixelLength;
static GLubyte* PixelData;
#include <stdio.h>
#include <stdlib.h>
void display(void)
{
// 清除螢幕并不必要
// 每次繪制時,畫面都覆寫整個螢幕
// 是以無論是否清除螢幕,結果都一樣
// glClear(GL_COLOR_BUFFER_BIT);
// 繪制像素
glDrawPixels(ImageWidth, ImageHeight,GL_BGR_EXT, GL_UNSIGNED_BYTE, PixelData);
// 完成繪制
glutSwapBuffers();
}
int main(int argc, char* argv[])
{
// 打開檔案
FILE* pFile;
errno_t err;
err= fopen_s(&pFile,"C:\\*********\\dummy.bmp", "rb");
if (pFile == 0)
exit(0);
// 讀取圖象的大小資訊
fseek(pFile, 0x0012, SEEK_SET);
fread(&ImageWidth, sizeof(ImageWidth), 1, pFile);
fread(&ImageHeight, sizeof(ImageHeight), 1, pFile);
// 計算像素資料長度
PixelLength = ImageWidth * 3;
while (PixelLength % 4 != 0)
++PixelLength;
PixelLength *= ImageHeight;
// 讀取像素資料
PixelData = (GLubyte*)malloc(PixelLength);
if (PixelData == 0)
exit(0);
fseek(pFile, 54, SEEK_SET);
fread(PixelData, PixelLength, 1, pFile);
// 關閉檔案
fclose(pFile);
// 初始化 GLUT 并運作
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(ImageWidth, ImageHeight);
glutCreateWindow(FileName);
glutDisplayFunc(&display);
glutMainLoop();
// 釋放記憶體
// 實際上,glutMainLoop 函數永遠不會傳回,這裡也永遠不會到達
// 這裡寫釋放記憶體隻是出于一種個人習慣
// 不用擔心記憶體無法釋放。在程式結束時作業系統會自動回收所有記憶體
free(PixelData);
return 0;
}

運作結果
OpenGL 在繪制像素之前,可以對像素進行若幹處理。最常用的可能就是對整個像素圖象進行放大/縮小。使用 glPixelZoom來設定放大/縮小的系數,該函數有兩個參數,分别是水準方向系數和垂直方向系數。例如設定 glPixelZoom(0.5f, 0.8f);則表示水準方向變為原來的 50%大小,而垂直方向變為原來的 80%大小。我們甚至可以使用負的系數,使得整個圖象進行水準方向或垂直方向的翻轉(預設像素從左繪制到右,但翻轉後将從右繪制到左。預設像素從下繪制到上,但翻轉後将從上繪制到下。是以,glRasterPos*函數設定的“開始位置”不一定就是矩形的左下角)。