??xml version="1.0" encoding="utf-8" standalone="yes"?>一级做a爱片久久毛片,狠狠色丁香婷婷久久综合五月,亚洲日本va午夜中文字幕久久http://www.shnenglu.com/wc250en007/category/13912.html前进的\?/description>zh-cnSat, 25 Sep 2010 04:33:58 GMTSat, 25 Sep 2010 04:33:58 GMT60 BMPd(?OpenGL中位囄操作(glReadPixelsQglDrawPixels和glCopyPixels应用举例)http://www.shnenglu.com/wc250en007/archive/2010/06/02/LoadBMP4.htmlLet me see seeLet me see seeWed, 02 Jun 2010 03:02:00 GMThttp://www.shnenglu.com/wc250en007/archive/2010/06/02/LoadBMP4.htmlhttp://www.shnenglu.com/wc250en007/comments/116993.htmlhttp://www.shnenglu.com/wc250en007/archive/2010/06/02/LoadBMP4.html#Feedback0http://www.shnenglu.com/wc250en007/comments/commentRss/116993.htmlhttp://www.shnenglu.com/wc250en007/services/trackbacks/116993.html原文地址Q?/p>

http://blog.csdn.net/ghost129/archive/2009/08/04/4409565.aspx

1?nbsp;      BMP文g格式单介l?/p>

BMP文g是一U像素文Ӟ它保存(sh)(jin)一q图象中所有的像素。这U文件格式可以保存单色位图?6色或256色烦(ch)引模式像素图?4位真彩色图象Q每U模式种单一像素的大分别ؓ(f)1/8字节Q?/2字节Q?字节?字节。目前最常见的是256色BMP?4位色BMP。这U文件格式还定义?jin)像素保存的几种?gu)Q包括不压羃、RLE压羃{。常见的BMP文g大多是不压羃的?br>q里Z(jin)单v见,我们仅讨?4位色、不使用压羃的BMP。(如果你用Windows自带的画囄序,很容易绘制出一个符合以上要求的BMPQ?br>Windows所使用的BMP文gQ在开始处有一个文件头Q大ؓ(f)54字节。保存(sh)(jin)包括文g格式标识、颜色数、图象大、压~方式等信息Q因为我们仅讨论24位色不压~的BMPQ所以文件头中的信息基本不需要注意,只有“大小”q一对我们比较有用。图象的宽度和高度都是一?2位整敎ͼ在文件中的地址分别?x0012?x0016Q于是我们可以用以下代码来d图象的大信息:(x)


GLint width, height; // 使用OpenGL的GLintcdQ它?2位的?br>                                     // 而C语言本n的int则不一定是32位的?br>FILE* pFile;
// 在这里进?#8220;打开文g”的操?br>fseek(pFile, 0x0012, SEEK_SET);         // Ud?x0012位置
fread(&width, sizeof(width), 1, pFile); // d宽度
fseek(pFile, 0x0016, SEEK_SET);         // Ud?x0016位置
                                        // ׃上一句执行后本就应该?x0016位置
                                        // 所以这一句可省略
fread(&height, sizeof(height), 1, pFile); // d高度

54个字节以后,如果?6色或256色BMPQ则q有一个颜色表Q但24位色BMP没有q个Q我们这里不考虑。接下来是实际的像素数据了(jin)?4位色的BMP文g中,每三个字节表CZ个像素的颜色?br>注意QOpenGL通常使用RGB来表C颜Ԍ但BMP文g则采用BGRQ就是说Q顺序被反过来了(jin)?br>另外需要注意的地方是:(x)像素的数据量q不一定完全等于图象的高度乘(sh)宽度乘(sh)每一像素的字节数Q而是可能略大于这个倹{原因是BMP文g采用?jin)一U?#8220;寚w”的机Ӟ每一行像素数据的长度若不?的倍数Q则填充一些数据它是4的倍数。这样一来,一?7*15?4位BMP大小应该是834字节Q每?7个像素,?1字节Q补充ؓ(f)52字节Q乘?sh)?5得到像素数据总长?80Q再加上文g开始的54字节Q得?34字节Q。分配内存时Q一定要心(j)Q不能直接?#8220;图象的高度乘?sh)宽度乘(sh)每一像素的字节数”来计分配空间的长度Q否则有可能D分配的内存空间长度不I造成界讉KQ带来各U严重后果?br>一个很单的计算数据长度的方法如下:(x)

int LineLength, TotalLength;
LineLength = ImageWidth * BytesPerPixel; // 每行数据长度大致为图象宽度乘?sh)?br>                                         // 每像素的字节?br>while( LineLength % 4 != 0 )             // 修正LineLength使其?的倍数
    ++LineLenth;
TotalLength = LineLength * ImageHeight;  // 数据总长 = 每行长度 * 图象高度

qƈ不是效率最高的Ҏ(gu)Q但׃q个修正本nq算量ƈ不大Q用频率也不高Q我们就不需要再考虑更快的方法了(jin)?br>2、简单的OpenGL像素操作
OpenGL提供?jin)简z的函数来操作像素:(x)
glReadPixelsQ读取一些像素。当前可以简单理解ؓ(f)“把已l绘制好的像素(它可能已l被保存到显卡的昑֭?sh)?j)d到内?#8221;?br>glDrawPixelsQ绘制一些像素。当前可以简单理解ؓ(f)“把内存(sh)一些数据作为像素数据,q行l制”?br>glCopyPixelsQ复制一些像素。当前可以简单理解ؓ(f)“把已l绘制好的像素从一个位|复制到另一个位|?#8221;。虽然从功能上看Q好象等价于先读取像素再l制像素Q但实际上它不需要把已经l制的像素(它可能已l被保存到显卡的昑֭?sh)?j)转换为内存数据,然后再由内存数据q行重新的绘Ӟ所以要比先d后绘制快很多?br>q三个函数可以完成简单的像素d、绘制和复制dQ但实际上也可以完成更复杂的d。当前,我们仅讨Z些简单的应用。由于这几个函数的参数数目比较多Q下面我们分别介l?/p>

3、glReadPixels的用法和举例
3.1 函数的参数说?br>该函数d有七个参数。前四个参数可以得到一个矩形,该矩形所包括的像素都?x)被d出来。(W一、二个参数表CZ(jin)矩Ş的左下角横、纵坐标Q坐标以H口最左下角ؓ(f)Ӟ最右上角ؓ(f)最大|W三、四个参数表CZ(jin)矩Ş的宽度和高度Q?br>W五个参数表C取的内容Q例如:(x)GL_RGB׃(x)依次d像素的红、绿、蓝三种数据QGL_RGBA则会(x)依次d像素的红、绿、蓝、alpha四种数据QGL_RED则只d像素的红色数据(cM的还有GL_GREENQGL_BLUEQ以?qing)GL_ALPHAQ。如果采用的不是RGBA颜色模式Q而是采用颜色索引模式Q则也可以用GL_COLOR_INDEX来读取像素的颜色索引。目前仅需要知道这些,但实际上q可以读取其它内容,例如深度~冲区的深度数据{?br>W六个参数表C取的内容保存到内存时所使用的格式,例如QGL_UNSIGNED_BYTE?x)把各种数据保存(sh)GLubyteQGL_FLOAT?x)把各种数据保存(sh)GLfloat{?br>W七个参数表CZ个指针,像素数据被读取后Q将被保存到q个指针所表示的地址。注意,需要保证该地址有够的可以使用的空_(d)以容U取的像素数据。例如一q大ؓ(f)256*256的图象,如果d其RGB数据Q且每一数据被保存(sh)ؓ(f)GLubyteQd就是:(x)256*256*3 = 196608字节Q即192千字节。如果是dRGBA数据Q则d就?56*256*4 = 262144字节Q即256千字节?/p>

注意QglReadPixels实际上是从缓冲区中读取数据,如果使用?jin)双~冲区,则默认是从正在显C的~冲Q即前缓Ԍ(j)中读取,而绘制工作是默认l制到后~冲区的。因此,如果需要读取已l绘制好的像素,往往需要先交换前后~冲?/p>

再看前面提到的BMP文g中两个需要注意的地方Q?br>3.2 解决OpenGL常用的RGB像素数据与BMP文g的BGR像素数据序不一致问?br>可以使用一些代码交换每个像素的W一字节和第三字节,使得RGB的数据变成BGR的数据。当然也可以使用另外的方式解决问题:(x)新版本的OpenGL除了(jin)可以使用GL_RGBd像素的红、绿、蓝数据外,也可以用GL_BGR按照相反的顺序依ơ读取像素的蓝、绿、红数据Q这样就与BMP文g格式相吻合了(jin)。即使你的gl/gl.h头文件中没有定义q个GL_BGRQ也没有关系Q可以尝试用GL_BGR_EXT。虽然有的OpenGL实现Q尤其是旧版本的实现Qƈ不能使用GL_BGR_EXTQ但我所知道的Windows环境下各UOpenGL实现都对GL_BGR提供?jin)支持,毕竟Windows中各U表C颜色的数据几乎都是使用BGR的顺序,而非RGB的顺序。这可能与IBM-PC的硬件设计有兟?/p>

3.3 消除BMP文g?#8220;寚w”带来的媄(jing)?br>实际上OpenGL也支持用了(jin)q种“寚w”方式的像素数据。只要通过glPixelStore修改“像素保存时对齐的方式”可以了(jin)。像q样Q?br>int alignment = 4;
glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
W一个参数表C?#8220;讄像素的对齐?#8221;Q第二个参数表示实际讄为多。这里像素可以单字节寚wQ实际上是不用对齐)(j)、双字节寚wQ如果长度ؓ(f)奇数Q则再补一个字节)(j)、四字节寚wQ如果长度不是四的倍数Q则补ؓ(f)四的倍数Q、八字节寚w。分别对应alignment的gؓ(f)1, 2, 4, 8。实际上Q默认的值是4Q正好与BMP文g的对齐方式相d?br>glPixelStorei也可以用于设|其它各U参数。但我们q里q不需要深入讨Z(jin)?/p>

现在Q我们已l可以把屏幕上的像素d到内存(sh)(jin)Q如果需要的话,我们q可以将内存?sh)的数据保存到文件。正的对照BMP文g格式Q我们的E序可以把屏幕中的图象保存?sh)BMP文gQ达到屏q截囄效果?br>我们q没有详l介lBMP文g开头的54个字节的所有内容,不过q无伤大雅。从一个正的BMP文g中读取前54个字节,修改其中的宽度和高度信息Q就可以得到新的文g头了(jin)。假设我们先建立一?*1大小?4位色BMPQ文件名为dummy.bmpQ又假设新的BMP文g名称为grab.bmp。则可以~写如下代码Q?/p>

FILE* pOriginFile = fopen("dummy.bmp", "rb);
FILE* pGrabFile = fopen("grab.bmp", "wb");
char  BMP_Header[54];
GLint width, height;

/* 先在q里讄好图象的宽度和高度,即width和height的|q计像素的总长?*/

// ddummy.bmp中的?4个字节到数组
fread(BMP_Header, sizeof(BMP_Header), 1, pOriginFile);
// 把数l内容写入到新的BMP文g
fwrite(BMP_Header, sizeof(BMP_Header), 1, pGrabFile);

// 修改其中的大信?br>fseek(pGrabFile, 0x0012, SEEK_SET);
fwrite(&width, sizeof(width), 1, pGrabFile);
fwrite(&height, sizeof(height), 1, pGrabFile);

// Ud到文件末,开始写入像素数?br>fseek(pGrabFile, 0, SEEK_END);

/* 在这里写入像素数据到文g */

fclose(pOriginFile);
fclose(pGrabFile);

我们l出完整的代码,演示如何把整个窗口的图象抓取出来q保存(sh)ؓ(f)BMP文g?/p>

#define WindowWidth  400
#define WindowHeight 400

#include <stdio.h>
#include <stdlib.h>

/* 函数grab
 * 抓取H口中的像素
 * 假设H口宽度为WindowWidthQ高度ؓ(f)WindowHeight
 */
#define BMP_Header_Length 54
void grab(void)
{
    FILE*    pDummyFile;
    FILE*    pWritingFile;
    GLubyte* pPixelData;
    GLubyte  BMP_Header[BMP_Header_Length];
    GLint    i, j;
    GLint    PixelDataLength;

    // 计算像素数据的实际长?br>    i = WindowWidth * 3;   // 得到每一行的像素数据长度
    while( i%4 != 0 )      // 补充数据Q直到i是的倍数
        ++i;               // 本来q有更快的算法,
                           // 但这里仅q求直观Q对速度没有太高要求
    PixelDataLength = i * WindowHeight;

    // 分配内存和打开文g
    pPixelData = (GLubyte*)malloc(PixelDataLength);
    if( pPixelData == 0 )
        exit(0);

    pDummyFile = fopen("dummy.bmp", "rb");
    if( pDummyFile == 0 )
        exit(0);

    pWritingFile = fopen("grab.bmp", "wb");
    if( pWritingFile == 0 )
        exit(0);

    // d像素
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glReadPixels(0, 0, WindowWidth, WindowHeight,
        GL_BGR_EXT, GL_UNSIGNED_BYTE, pPixelData);

    // 把dummy.bmp的文件头复制为新文g的文件头
    fread(BMP_Header, sizeof(BMP_Header), 1, pDummyFile);
    fwrite(BMP_Header, sizeof(BMP_Header), 1, pWritingFile);
    fseek(pWritingFile, 0x0012, SEEK_SET);
    i = WindowWidth;
    j = WindowHeight;
    fwrite(&i, sizeof(i), 1, pWritingFile);
    fwrite(&j, sizeof(j), 1, pWritingFile);

    // 写入像素数据
    fseek(pWritingFile, 0, SEEK_END);
    fwrite(pPixelData, PixelDataLength, 1, pWritingFile);

    // 释放内存和关闭文?br>    fclose(pDummyFile);
    fclose(pWritingFile);
    free(pPixelData);
}

 

把这D代码复制到以前M评的样例程序中Q在l制函数的最后调用grab函数Q即可把图象内容保存?sh)BMP文g?jin)。(在我写这个教E的时候,不少地方都用q样的代码进行截囑ַ作,q段代码一旦写好,q行h是很方便的。)(j)
4、glDrawPixels的用法和举例
glDrawPixels函数与glReadPixels函数相比Q参数内容大致相同。它的第一、二、三、四个参数分别对应于glReadPixels函数的第三、四、五、六个参敎ͼ依次表示图象宽度、图象高度、像素数据内宏V像素数据在内存?sh)的格式。两个函数的最后一个参C是对应的QglReadPixels中表C像素读取后存放在内存(sh)的位|,glDrawPixels则表C用于绘制的像素数据在内存(sh)的位|?br>注意到glDrawPixels函数比glReadPixels函数了(jin)两个参数Q这两个参数在glReadPixels中分别是表示图象的v始位|。在glDrawPixels中,不必昑ּ的指定绘制的位置Q这是因为绘制的位置是由另一个函数glRasterPos*来指定的。glRasterPos*函数的参CglVertex*cMQ通过指定一个二l?三维/四维坐标QOpenGL自动计出该坐标对应的屏幕位置Qƈ把该位置作ؓ(f)l制像素的v始位|?br>很自然的Q我们可以从BMP文g中读取像素数据,q用glDrawPixelsl制到屏q上。我们选择Windows XP默认的桌面背景Bliss.bmp作ؓ(f)l制的内容(如果你用的是Windows XPpȝQ很可能可以在硬盘(sh)搜烦(ch)到这个文件。当然你也可以用其它BMP文g来代替,只要它是24位的BMP文g。注意需要修改代码开始部分的FileName的定义)(j)Q先把该文g复制一份放到正的位置Q我们在E序开始时Q就d该文Ӟ从而获得图象的大小后,Ҏ(gu)该大来创徏合适的OpenGLH口Qƈl制像素?br>l制像素本来是很单的q程Q但是这个程序在骨架上与前面的各U示例程序稍有不同,所以我q是打算l出一份完整的代码?/p>

#include <gl/glut.h>

#define FileName "Bliss.bmp"

static GLint    ImageWidth;
static GLint    ImageHeight;
static GLint    PixelLength;
static GLubyte* PixelData;

#include <stdio.h>
#include <stdlib.h>

void display(void)
{
    // 清除屏幕q不必要
    // 每次l制Ӟ画面都覆盖整个屏q?br>    // 因此无论是否清除屏幕Q结果都一?br>    // glClear(GL_COLOR_BUFFER_BIT);

    // l制像素
    glDrawPixels(ImageWidth, ImageHeight,
        GL_BGR_EXT, GL_UNSIGNED_BYTE, PixelData);

    // 完成l制
    glutSwapBuffers();
}

int main(int argc, char* argv[])
{
    // 打开文g
    FILE* pFile = fopen("Bliss.bmp", "rb");
    if( pFile == 0 )
        exit(0);

    // d图象的大信?br>    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;

    // d像素数据
    PixelData = (GLubyte*)malloc(PixelLength);
    if( PixelData == 0 )
        exit(0);

    fseek(pFile, 54, SEEK_SET);
    fread(PixelData, PixelLength, 1, pFile);

    // 关闭文g
    fclose(pFile);

    // 初始化GLUTq运?br>    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(ImageWidth, ImageHeight);
    glutCreateWindow(FileName);
    glutDisplayFunc(&display);
    glutMainLoop();

    // 释放内存
    // 实际上,glutMainLoop函数永远不会(x)q回Q这里也永远不会(x)到达
    // q里写释攑ֆ存只是出于一U个Z(fn)?br>    // 不用担心(j)内存无法释放。在E序l束时操作系l会(x)自动回收所有内?br>    free(PixelData);

    return 0;
}

 

q里仅仅是一个简单的昄24位BMP图象的程序,如果读者对BMP文g格式比较熟?zhn)Q也可以写出适用于各UBMP图象的显C程序,在像素处理时Q它们所使用的方法是cM的?br>OpenGL在绘制像素之前,可以对像素进行若q处理。最常用的可能就是对整个像素图象q行攑֤/~小。用glPixelZoom来设|放?~小的系敎ͼ该函数有两个参数Q分别是水^方向pL和垂直方向系数。例如设|glPixelZoom(0.5f, 0.8f);则表C水qx(chng)向变?sh)原来?0%大小Q而垂直方向变?sh)原来?0%大小。我们甚臛_以用负的系敎ͼ使得整个图象q行水^方向或垂直方向的{Q默认像素从左绘制到叻I但翻转后从右绘制到左。默认像素从下绘制到上,但翻转后从上绘制到下。因此,glRasterPos*函数讄?#8220;开始位|?#8221;不一定就是矩形的左下角)(j)?br>5、glCopyPixels的用法和举例
从效果上看,glCopyPixelsq行像素复制的操作,{h(hun)于把像素d到内存,再从内存l制到另一个区域,因此可以通过glReadPixels和glDrawPixelsl合来实现复制像素的功能。然而我们知道,像素数据通常数据量很大,例如一q?024*768的图象,如果使用24位BGR方式表示Q则需要至?024*768*3字节Q即2.25兆字节。这么多的数据要q行一ơ读操作和一ơ写操作Qƈ且因为在glReadPixels和glDrawPixels中设|的数据格式不同Q很可能涉及(qing)到数据格式的转换。这对CPU无疑是一个不的负担。用glCopyPixels直接从像素数据复制出新的像素数据Q避免了(jin)多余的数据的格式转换Qƈ且也可能减少一些数据复制操作(因ؓ(f)数据可能直接由显卡负责复Ӟ不需要经q主内存Q,因此效率比较高?br>glCopyPixels函数也通过glRasterPos*pd函数来设|绘制的位置Q因Z需要涉?qing)到d存,所以不需要指定数据在内存?sh)的格式Q也不需要用Q何指针?br>glCopyPixels函数有五个参敎ͼW一、二个参数表C复制像素来源的矩Ş的左下角坐标Q第三、四个参数表C复制像素来源的举行的宽度和高度Q第五个参数通常使用GL_COLORQ表C复制像素的颜色Q但也可以是GL_DEPTH或GL_STENCILQ分别表C复制深度缓冲数据或模板~冲数据?br>值得一提的是,glDrawPixels和glReadPixels中设|的各种操作Q例如glPixelZoom{,在glCopyPixels函数中同h效?br>下面看一个简单的例子Q绘制一个三角Ş后,复制像素Qƈ同时q行水^和垂直方向的{Q然后羃?yu)?f)原来的一半,q绘制。绘制完毕后Q调用前面的grab函数Q将屏幕中所有内容保存(sh)ؓ(f)grab.bmp。其中WindowWidth和W(xu)indowHeight是表C窗口宽度和高度的常量?/p>

void display(void)
{
    // 清除屏幕
    glClear(GL_COLOR_BUFFER_BIT);

    // l制
    glBegin(GL_TRIANGLES);
        glColor3f(1.0f, 0.0f, 0.0f);    glVertex2f(0.0f, 0.0f);
        glColor3f(0.0f, 1.0f, 0.0f);    glVertex2f(1.0f, 0.0f);
        glColor3f(0.0f, 0.0f, 1.0f);    glVertex2f(0.5f, 1.0f);
    glEnd();
    glPixelZoom(-0.5f, -0.5f);
    glRasterPos2i(1, 1);
    glCopyPixels(WindowWidth/2, WindowHeight/2,
        WindowWidth/2, WindowHeight/2, GL_COLOR);

    // 完成l制Qƈ抓取图象保存?sh)BMP文g
    glutSwapBuffers();
    grab();
}

 

 

 

结Q?br>本课l合Windowspȝ常见的BMP图象格式Q简单介l了(jin)OpenGL的像素处理功能。包括用glReadPixelsd像素、glDrawPixelsl制像素、glCopyPixels复制像素?br>本课仅介l了(jin)像素处理的一些简单应用,但相信大家已l可以体?x)到Q围l这三个像素处理函数Q还存在一?#8220;外围”函数Q比如glPixelStore*QglRasterPos*Q以?qing)glPixelZoom{。我们仅使用?jin)这些函数的一部分功能?br>本课内容q不多,例子_丰富Q三个像素处理函数都有例子,大家可以l合例子来体?x)?/p>

 

附录(其它位色的BMP文g?:

BMP文gl成
  BMP文g由文件头、位图信息头、颜色信息和囑Ş数据四部分组成?
   BMP文g?
  BMP文g头数据结构含有BMP文g的类型、文件大和位图起始位置{信息?
  其结构定义如?  
  typedef struct tagBITMAPFILEHEADER
  {
  WORDbfType; // 位图文g的类型,必须为BM
  DWORD bfSize; // 位图文g的大,以字节ؓ(f)单位
  WORDbfReserved1; // 位图文g保留字,必须?
  WORDbfReserved2; // 位图文g保留字,必须?
  DWORD bfOffBits; // 位图数据的v始位|,以相对于位图
  // 文g头的偏移量表C,以字节ؓ(f)单位
  } BITMAPFILEHEADER;
  

位图信息?
  
  BMP位图信息头数据用于说明位囄寸{信息?br>  typedef struct tagBITMAPINFOHEADER{
  DWORD biSize; // 本结构所占用字节?br>  LONGbiWidth; // 位图的宽度,以像素ؓ(f)单位
  LONGbiHeight; // 位图的高度,以像素ؓ(f)单位
  WORD biPlanes; // 目标讑֤的别,必须?
  WORD biBitCount// 每个像素所需的位敎ͼ必须?(双色),
  // 4(16?Q?(256??4(真彩?之一
  DWORD biCompression; // 位图压羃cdQ必L 0(不压~?,
  // 1(BI_RLE8压羃cd)?(BI_RLE4压羃cd)之一
  DWORD biSizeImage; // 位图的大,以字节ؓ(f)单位
  LONGbiXPelsPerMeter; // 位图水^分L率,每米像素?br>  LONGbiYPelsPerMeter; // 位图垂直分L率,每米像素?br>  DWORD biClrUsed;// 位图实际使用的颜色表中的颜色?br>  DWORD biClrImportant;// 位图昄q程中重要的颜色?br>  } BITMAPINFOHEADER;
  

颜色?
  颜色表用于说明位图中的颜Ԍ它有若干个表,每一个表Ҏ(gu)一个RGBQUADcd的结构,定义一U颜艌ӀRGBQUADl构的定义如?
  
  typedef struct tagRGBQUAD {
  BYTErgbBlue;// 蓝色的亮?D围ؓ(f)0-255)
  BYTErgbGreen; // l色的亮?D围ؓ(f)0-255)
  BYTErgbRed; // U色的亮?D围ؓ(f)0-255)
  BYTErgbReserved;// 保留Q必Mؓ(f)0
  } RGBQUAD;
  颜色表中RGBQUADl构数据的个数有biBitCount来确?
  当biBitCount=1,4,8Ӟ分别?,16,256个表?
  当biBitCount=24Ӟ没有颜色表项?br>  位图信息头和颜色表组成位图信息,BITMAPINFOl构定义如下:
  typedef struct tagBITMAPINFO {
  BITMAPINFOHEADER bmiHeader; // 位图信息?br>  RGBQUAD bmiColors[1]; // 颜色?br>  } BITMAPINFO;

位图数据
  位图数据记录?jin)位囄每一个像素|记录序是在扫描行内是从左到?扫描行之间是从下C。位囄一个像素值所占的字节?
  
  当biBitCount=1Ӟ8个像素占1个字?
  当biBitCount=4Ӟ2个像素占1个字?
  当biBitCount=8Ӟ1个像素占1个字?
  当biBitCount=24?1个像素占3个字?
  Windows规定一个扫描行所占的字节数必L
  4的倍数(即以long为单?,不的以0填充Q?br>  一个扫描行所占的字节数计方?
  DataSizePerLine= (biWidth* biBitCount+31)/8;
  // 一个扫描行所占的字节?br>  DataSizePerLine= DataSizePerLine/4*4; // 字节数必L4的倍数
  位图数据的大?不压~情况下):
  DataSize= DataSizePerLine* biHeight;

 

 



Let me see see 2010-06-02 11:02 发表评论
]]>
BMPd(?http://www.shnenglu.com/wc250en007/archive/2010/05/29/LoadBMP3.htmlLet me see seeLet me see seeSat, 29 May 2010 03:22:00 GMThttp://www.shnenglu.com/wc250en007/archive/2010/05/29/LoadBMP3.htmlhttp://www.shnenglu.com/wc250en007/comments/116671.htmlhttp://www.shnenglu.com/wc250en007/archive/2010/05/29/LoadBMP3.html#Feedback0http://www.shnenglu.com/wc250en007/comments/commentRss/116671.htmlhttp://www.shnenglu.com/wc250en007/services/trackbacks/116671.html      在读取BMP囑փ的时候,主要处理?4位和32位图像,在处?4位BMP囑փ的时候,BMP囑փ的数据已l被修改以便4字节自动寚wQ?br> 对于24位BMP囑փ而言Q最需要注意的一Ҏ(gu)Q规定了(jin)每条行扫描线的数据大必L4的整数倍,如果不是4的整数倍,那么需要在行末?/span>q行?Q否则数据读取将出现偏移Q直接导致的l果Q?span style="COLOR: red">?x)加载出一张倾斜的图?/span>。这个补0的操作叫做数据宽度对齐?br>      很抽象?举个例子Q对?00×400?4位BMP囑փ而言Q行扫描?00pxQ是4的整数倍,那么无需q行?操作。如果是30×38Q本每张麻牌素材的尺寸)(j)Q那么行扫描昄不是4的整数倍。对?4位BMP而言Q一个像素由RGB三字节组成,那么一个行扫描的total字节?0 × 3 = 90字节Q进行数据宽度对齐之后,行扫描的实际total字节?0 × 3 + 2 = 92字节。如此,才能?整除。换句话_(d)每一行多?个无用的字节。这在编E中Q需要进行处理丢弃,否则囑փ再次变Ş
    

            int channel= 0;
            
if ( texture->bpp == 24 ){
                channel 
= 3;
                texture
->imageType = GL_RGB;
            }
else{
                channel 
= 4;
                texture
->imageType = GL_RGBA;
            }

            
int biWidth = 0;                                                //每行补齐字节?如果?4位的话需要补齐成4字节的倍数
            if ( (texture->width*channel) % 4 != 0 )
                biWidth 
= 4 - ( (texture->width*channel) % 4 );
            
我们求出每行自动填充的字节数Q先d数据Q然后蟩q自动添加的字节敎ͼ再接着d下一行数?/span>
            forint i = 0; i < height; i++ ){
                GLubyte
* pdest = texture->imageData + i * width * channel;
                fread( pdest, 
1, width * channel,file );

                
forint j = 0; j < width* channel; j+=channel ){
                    pdest[ j ] 
^= pdest[j+2^= pdest[j] ^= pdest[j+2];                //BGR转ؓ(f)RGB,BMP数据从左下角到右上角的方式存?/span>
                }

                
                fseek( file, biWidth, SEEK_CUR );                                    
//丢弃补字节Q开始填充下一?nbsp;   
            }

d数据完毕Q可以打印检验一下,用WINHEX打开看下QNoPropblem
因ؓ(f)我读取的囄不全?12*512,256*256,.......,所以我用OPENGL生成U理的时候用?jin)个gluBuild2DMipmaps
BOOL bRes = gluBuild2DMipmaps( GL_TEXTURE_2D,  texture->bpp/8, texture->width,texture->height, texture->imageType, GL_UNSIGNED_BYTE, texture->imageData );
d来后又成斜着的图像了(jin)Q数据也没问题,只能说是生成MipMap 的时候读取数据跨度有问题Q但是我传递的?2位图像的时候,生成的MIPMAP没Q何问题,即囑փ大小不能?整除Q即?12*512,256*256,.......
所以我做了(jin)个比较恶?j)的做?br>
    if ( bMipmap ){
        
if ( texture->imageType == GL_RGB ){
            GLubyte
* data = new GLubyte[texture->width*texture->height*4 ];
            
int counter = 0;
            
forint i = 0; i < texture->width*texture->height*3; i+=3 ){
                data[i
+counter] = texture->imageData[i];
                data[i
+1+counter] = texture->imageData[i+1];
                data[i
+2+counter] = texture->imageData[i+2];
                data[i
+3+counter] = 1.f;
                counter
++;
            }

            BOOL bRes 
= gluBuild2DMipmaps( GL_TEXTURE_2D,  4, texture->width,texture->height, GL_RGBA, GL_UNSIGNED_BYTE, data );
            delete[] data;
        }
else{
            BOOL bRes 
= gluBuild2DMipmaps( GL_TEXTURE_2D,  texture->bpp/8, texture->width,texture->height, texture->imageType, GL_UNSIGNED_BYTE, texture->imageData );
        }

        
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR );
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);    

?4位的囑փ生成U理的时候,我把数据转换?2位的没问题?sh)(jin),一直没更好的办法,请大家不吝指?br>
题外文章Q?br>BMP文g的结构,从大的分cL看,可以分成2部分Q头部信息区和图像数据区。其中头部信息区中,保存?sh)(jin)图像的各种属性,如文件格式,囄宽度Q调色板{等。过?jin)头部信息区之后Q就是用来呈现图像的真正的数据区?jin)。BMP文g属于像素文gQ也是_(d)数据Z的数据,其实是记录?jin)图像中每一个像素的颜色Q以32位BMP囄来说Q每一个像素由ARGB四个字节保存光Ԍ其中A是透明度。那么,一?00×400?2位BMP囑փQ就?60000个像素组成,则,数据区大?160000×4byte = 640000byte = 640kbQ所以也不难怪,BMP囑փ文glh的印象就是文仉常大?

       那么BMP文g中的像素逐个d数据~冲再显C,是否p正常昄?jin)呢Q显然不是的。前面说?jin),在文件开头有一块头部信息区Q如果把q些数据也一赯q缓Ԍ那么囑փ是无法最l显C的。因此,通常载入BMP囑փ的首要Q务是要知道这块头部信息区的大,也就是数据区的偏U量offsetQ再利用fseekd到这个位|,再进行逐个像素的解析。而头部信息区的大D似在头部信息区的某个字节中有的,只需要读取该字节Q便可知道。对?4位和32位的BMP囑փ而言Q这个offsetgؓ(f)0x36Q也是头部信息区的大小?4个字节?/p>

       如果你要把加载图像的函数做的通用一些的话,那么囄的宽度和高度也是需要获取的Q对?4位BMP囑փQ这两个值可以分别在0x12?x16q行d得到Q注意fread需要读双字Q即4字节Q否则会(x)出错?/p>

       对于24位BMP囑փ而言Q最需要注意的一Ҏ(gu)Q规定了(jin)每条行扫描线的数据大必L4的整数倍,如果不是4的整数倍,那么需要在行末端进行补0Q否则数据读取将出现偏移Q直接导致的l果Q会(x)加蝲Z张倾斜的图像。这个补0的操作叫做数据宽度对齐?/p>

       很抽象?举个例子Q对?00×400?4位BMP囑փ而言Q行扫描?00pxQ是4的整数倍,那么无需q行?操作。如果是30×38Q本每张麻牌素材的尺寸)(j)Q那么行扫描昄不是4的整数倍。对?4位BMP而言Q一个像素由RGB三字节组成,那么一个行扫描的total字节?0 × 3 = 90字节Q进行数据宽度对齐之后,行扫描的实际total字节?0 × 3 + 2 = 92字节。如此,才能?整除。换句话_(d)每一行多?个无用的字节。这在编E中Q需要进行处理丢弃,否则囑փ再次变Ş?/p>

       最后一个需要注意的细节是QBMP囑փ的原点坐标,都是以左下角为基准,向右、向上增加。所以,在编E时Q需要对y轴数据做一些小变换。否则将?x)得Cq颠倒的囑փQ此外,BMP的三原色序是BGRQ注意编E中的处理?/p>
原文地址QBMP文g的结构,从大的分cL看,可以分成2部分Q头部信息区和图像数据区。其中头部信息区中,保存?sh)(jin)图像的各种属性,如文件格式,囄宽度Q调色板{等。过?jin)头部信息区之后Q就是用来呈现图像的真正的数据区?jin)。BMP文g属于像素文gQ也是_(d)数据Z的数据,其实是记录?jin)图像中每一个像素的颜色Q以32位BMP囄来说Q每一个像素由ARGB四个字节保存光Ԍ其中A是透明度。那么,一?00×400?2位BMP囑փQ就?60000个像素组成,则,数据区大?160000×4byte = 640000byte = 640kbQ所以也不难怪,BMP囑փ文glh的印象就是文仉常大?

       那么BMP文g中的像素逐个d数据~冲再显C,是否p正常昄?jin)呢Q显然不是的。前面说?jin),在文件开头有一块头部信息区Q如果把q些数据也一赯q缓Ԍ那么囑փ是无法最l显C的。因此,通常载入BMP囑փ的首要Q务是要知道这块头部信息区的大,也就是数据区的偏U量offsetQ再利用fseekd到这个位|,再进行逐个像素的解析。而头部信息区的大D似在头部信息区的某个字节中有的,只需要读取该字节Q便可知道。对?4位和32位的BMP囑փ而言Q这个offsetgؓ(f)0x36Q也是头部信息区的大小?4个字节?/p>

       如果你要把加载图像的函数做的通用一些的话,那么囄的宽度和高度也是需要获取的Q对?4位BMP囑փQ这两个值可以分别在0x12?x16q行d得到Q注意fread需要读双字Q即4字节Q否则会(x)出错?/p>

       对于24位BMP囑փ而言Q最需要注意的一Ҏ(gu)Q规定了(jin)每条行扫描线的数据大必L4的整数倍,如果不是4的整数倍,那么需要在行末端进行补0Q否则数据读取将出现偏移Q直接导致的l果Q会(x)加蝲Z张倾斜的图像。这个补0的操作叫做数据宽度对齐?/p>

       很抽象?举个例子Q对?00×400?4位BMP囑փ而言Q行扫描?00pxQ是4的整数倍,那么无需q行?操作。如果是30×38Q本每张麻牌素材的尺寸)(j)Q那么行扫描昄不是4的整数倍。对?4位BMP而言Q一个像素由RGB三字节组成,那么一个行扫描的total字节?0 × 3 = 90字节Q进行数据宽度对齐之后,行扫描的实际total字节?0 × 3 + 2 = 92字节。如此,才能?整除。换句话_(d)每一行多?个无用的字节。这在编E中Q需要进行处理丢弃,否则囑փ再次变Ş?/p>

       最后一个需要注意的细节是QBMP囑փ的原点坐标,都是以左下角为基准,向右、向上增加。所以,在编E时Q需要对y轴数据做一些小变换。否则将?x)得Cq颠倒的囑փQ此外,BMP的三原色序是BGRQ注意编E中的处理?/p>
原文地址Q?a >http://naozifangde.blog.163.com/blog/static/1280042642009101614938531/

Let me see see 2010-05-29 11:22 发表评论
]]>
BMPd(?http://www.shnenglu.com/wc250en007/archive/2010/05/28/LoadBMP2.htmlLet me see seeLet me see seeFri, 28 May 2010 06:14:00 GMThttp://www.shnenglu.com/wc250en007/archive/2010/05/28/LoadBMP2.htmlhttp://www.shnenglu.com/wc250en007/comments/116603.htmlhttp://www.shnenglu.com/wc250en007/archive/2010/05/28/LoadBMP2.html#Feedback0http://www.shnenglu.com/wc250en007/comments/commentRss/116603.htmlhttp://www.shnenglu.com/wc250en007/services/trackbacks/116603.html阅读全文

Let me see see 2010-05-28 14:14 发表评论
]]>
BMPd(一)http://www.shnenglu.com/wc250en007/archive/2010/05/28/LoadBMP.htmlLet me see seeLet me see seeFri, 28 May 2010 03:00:00 GMThttp://www.shnenglu.com/wc250en007/archive/2010/05/28/LoadBMP.htmlhttp://www.shnenglu.com/wc250en007/comments/116578.htmlhttp://www.shnenglu.com/wc250en007/archive/2010/05/28/LoadBMP.html#Feedback0http://www.shnenglu.com/wc250en007/comments/commentRss/116578.htmlhttp://www.shnenglu.com/wc250en007/services/trackbacks/116578.html阅读全文

Let me see see 2010-05-28 11:00 发表评论
]]>
TGAd(?http://www.shnenglu.com/wc250en007/archive/2010/05/26/TGARead2.htmlLet me see seeLet me see seeWed, 26 May 2010 02:05:00 GMThttp://www.shnenglu.com/wc250en007/archive/2010/05/26/TGARead2.htmlhttp://www.shnenglu.com/wc250en007/comments/116359.htmlhttp://www.shnenglu.com/wc250en007/archive/2010/05/26/TGARead2.html#Feedback0http://www.shnenglu.com/wc250en007/comments/commentRss/116359.htmlhttp://www.shnenglu.com/wc250en007/services/trackbacks/116359.html阅读全文

Let me see see 2010-05-26 10:05 发表评论
]]>
TGAd( 一 )http://www.shnenglu.com/wc250en007/archive/2010/05/26/TGA_READ1.htmlLet me see seeLet me see seeWed, 26 May 2010 01:40:00 GMThttp://www.shnenglu.com/wc250en007/archive/2010/05/26/TGA_READ1.htmlhttp://www.shnenglu.com/wc250en007/comments/116357.htmlhttp://www.shnenglu.com/wc250en007/archive/2010/05/26/TGA_READ1.html#Feedback0http://www.shnenglu.com/wc250en007/comments/commentRss/116357.htmlhttp://www.shnenglu.com/wc250en007/services/trackbacks/116357.html阅读全文

Let me see see 2010-05-26 09:40 发表评论
]]>
þùƷ| vavavaþ| ŷҹƷþþþþ˳| ƷþòҰ| 鶹AVһþ | þþƷ99Ʒ| þþƷ| ھƷ˾þþþӰԺ԰| ԭ1769þѲ| ޹Ʒþþþ| Ʒ˾þþþӰԺ | ˾Ʒþ| þþۺ| Ʒ91þþþþþa| þۺŷ| һŮȫƾþƬ| vĻþ| ݺɫþۺ| ѾþҹƷ| þù׽| Ʒպҹþ| Ʒþһ| ٸþ| þֻ⾫Ʒ99| ޳avƬþ| þùҹaӰԺ| ƷҹþøƬ| ھƷþþþӰԺ| ƷƵþþþ| þӰ㶮| þþþһ| Ʒþþþ9999| þҹɫƷվ| һõþۺϺݺݰ| þþƵ| þþþþúݺݶ| þ| þ99ۺϾƷҳ| þƵ6| þùƷþ| 99ȾƷþֻоƷ|