zoukankan      html  css  js  c++  java
  • 《OpenGL游戏程序设计》学习笔记第七章图像、位图与OpenGL

    OpenGL游戏程序设计》 K.霍金/D.阿斯特     田昱川    

    1.       OpenGL位图

    OpenGL位图被定义为像素的矩阵阵列,每个像素对应矩阵中一个位的数据(0

             1),被当做窗口中一个矩形区域的绘制掩膜,通常用于字符。

    比如一个16*16的位图,将其分割成一个16*16的栅格,如果一个像素对应的栅格中的值为1,那么就用当前的光栅颜色(就是glColor3f()这类函数设置的颜色)绘制该像素,如果为0,就什么也不绘制。

    OpenGL位图转换成栅格阵列时,从位图的左下角开始:先画最下面的一行,然后是这行的上一行

    例如位图是:(只说最后两行)

    ······

    ······(上面的行省略)

    1·1·0·1·1·1·1·1·1·1·1·1·1·0·1·1(倒数第二行)

    1·1·0·0·0·0·0·0·0·0·0·0·0·0·1·1(最后一行)

    则转换成信息阵列是(每行用两位的十六进制表示)

    unsigned char letter[]=

    {

             0xC0,0x03 ,//最后一行(共16位)

             0xDF,0xFB ,//倒数第二行

             ······

             ······

    };

    a)         glRasterPos*()

    用来指定将要绘制位图或图像的屏幕位置,传递给此函数的坐标值定义了位图的左下角的位置。

    void glRasterPos[234][sifd](TYPE x, TYPE  y, TYPE z,TYPE w);

    void glRasterPos[234][sifd]v(TYPE *coords);

    除非为2D绘制指定了具体的模型视图矩阵和投影矩阵,否则传递给glRasterPos*()函数的坐标值就是相应的屏幕坐标。下面是使用glOrtho()函数定义一个2D视区,其宽度和高度定义了窗口的宽度和高度

    glViewport(0,0,width,height);将视区设置为新的大小尺寸

    glMatrixMode(GL_PROJECTION)投影矩阵设置为当前矩阵

    glLoadIdentity();复位投影矩阵

     

    定义2D视区

    glOrtho(0.0f,  width-1.0,  0.0,  height-1.0,  -1.0,  1.0);

     

    glMatrixMode(GL_MODELVIEW);设置模型视图矩阵

    glLoadIdnetity()复位模型视图矩阵

    b)         glBitmap()

    设置了当前光栅位置之后,可以调用glBitmap()函数绘制位图

    void glBitmap(GLsizei  width,GLsizei height,GLfloat  xOrigin, GLfloat yOrigin,

    GLfloat xIncrement ,GLfloat yIncrement ,const GLubyte *bitmap);

    函数在当前光栅位置的(xOrigin,yOrigin)坐标处,以指定的宽度和高度绘制一个位图,(xIncrement,yIncrement)坐标指定绘制完成后用于设置新的光栅位置的坐标增量。

    OpenGl位图不能被旋转不能被缩放

     

    c)          

    2.       图像的使用

    1.       图像的绘制

    假设图像数据被载入到了内存中,可以调用glDrawPixels()函数来在窗口中指定的光栅位置显示这些图像数据。

    void glDrawPixels(GLsizei width,GLsizei height ,Glenum format ,GLenum type,const GLovid *pixels);

    format:

    GL_ALPHA    alpha颜色像素

    GL_BGR               像素顺序为蓝色、绿色、红色

    GL_BGRA            像素顺序为蓝色、绿色、红色、alpha

    GL_BLUE             蓝色像素

    GL_COLOR_INDEX 索引颜色像素

    GL_GREEN          绿色像素

    GL_RED               红色像素

    GL_RGB               像素顺序为红色、绿色、蓝色

    GL_RGBA            像素顺序为红色、绿色、蓝色、alpha

    type:(不太理解

    GL_BITMAP 单个的位 0或者1

    GL_BYTE   有符号的8bit整数  2字节

    GL_UNSIGNED_BYTE  无符合的8bit整数 2字节

    GL_SHORT   有符合的16bit整数  4字节

    GL_UNSIGNED_SHORT  无符合的16bit整数,4字节

    GL_INT                 有符合的32bit整数  8字节

    GL_UNSIGNED_INT 无符合的32bit整数 8字节

     

    图像数据存储在imageData中,在屏幕300300位置绘制图像

    glRasterPos2i(300,300);

    glDrawPixels(imageWidth,imageHeight,GL_RGB,GL_UNSIGNED_BYTE,imageData);

    2.       屏幕的读取

    void glReadPixels(Glint x,Glint y,GLsizei width ,GLsizei height ,GLenum format,GLenum type,GLvoid *pixels);

    x,y 指定要从屏幕上读取矩形的左下角,widthheight定义矩形区域的大小。

    将窗口的上半部分读取到一个RGB缓存中:

    void *imageData;

    int screenWidth,screenHeight;

    glReadPixels(0,screenHeight/2,screenWidth,screenHeight/2,GL_RGB,GL_UNSIGNED_BYTE, imageData);

    3.       屏幕的复制

    glCopyPixels()函数将屏幕上的一个部分的像素复制到另一个部分

    glCopyPixels(Glint  x ,Glint y,GLsizei width,GLsizei height ,GLenum buffer);

    函数将帧缓存中的一个矩形区域的像素数据复制到当前的光栅位置,矩形区域的左下角是(xy),(widthheight)是宽和高

    4.       放大、缩小、翻转

    void glPixelZoom(GLfloat  xZoom,GLfloat yZoom);

    默认情况下xZoomyZoom的值都是1.0,是一个正常的图像

    0.0~1.0会缩小图像,大于1.0会放大图像

    参数指定为负值,图像将相对于当前的光栅位置进行翻转

    glPixelZoom(-1.0f,-1.0f);在垂直和水平方向上翻转图像

    glPixelZoom(0.5f,0.5f);缩小到原来的一半

    glPiexlZoom(5.0f,5.0f);各个方向放大5

    5.       放大镜和狙击步枪的瞄准镜实现

    利用glCopyPixel()复制指定区域并结合glPixelZoom()

     

    3.       像素存储的管理

    应用程序从一台电脑移动到另一台电脑,运行速度可能变慢,有可能是内存中数据的边界对准问题引起。

    在内存中数据是248字节边界对齐的话,有些计算机能更快的传输数据

    可以通过glPixelStorei()函数控制数据对齐

    void glPixelStorei(GLenum pname ,TYPE param);

    pname:

    GL_PACK_ALIGNMENT 通知OpenGl如何将数据装入内存

    GL_UNPACK_ALIGNMENT 如何从内存中提取数据

    param1248

    默认情况下GL_PACK_ALIGNMENT GL_UNPACK_ALIGNMENT都是4

    ···········································································

    glReadPixels

    glPixelStorei

    以上内容,在OpenGL_ESgl.h只找到这两个。。。。

    ···········································································

    4.       Windows位图

    BMP不使用任何压缩算法,文件大,易于读取和使用

    1.       文件格式

    BMP文件由3部分构成:位图文件头、位图信息头、实际的位图数据

    位图文件头

    位图信息头

    (调色板数据)

    位图数据

     

    位图文件头数据结构:

    typedef struct tagBITMAPFILEHEADER

    {

       WORD              bfType;  指定文件类型,必须是BM0x4D42

       DWORD           bfSize;  按字节指定位图文件的大小

       WORD               bfReserved1; 必须为0

       WORD              bfReserved2; 必须为0

       DWORD            bOffBits; 按字节指定从BITMAPFILEHEADER数据结构到位图数据偏移

    }BITMAPFILEHEADER;

    typedef struct tagBITMAPINFOHEADER

    {

    DWORD  biSize;

    LONG     biWidth;以像素指定位图的宽度

    LONG          biHeight; 以像素指定位图的高度

    WORD       biplanes;  颜色平面数,必须为1

    WORD         biBitCount; 每个像素的数据位数1.4.8.16.24.32之一

    DWORD   biCompression;压缩类型 BI_RGB表面无压缩

    DWORD      biSizeImage;  按字节指定图像数据的大小,只包括位图数据

    LONG    biXPelsPerMeter;  X轴上每米的像素数

    LONG    biYPelsPerMeter;  y轴上每米的像素数

    DWORD    biClrUsed;   指定位图使用的颜色数

    DWORD    biClrImportant  指定重要颜色的数量

    }BITMAPINFOHEADER;

     

    位图的颜色格式为BGR,需要交换RB的值,得掉RGB数据

     

    2.       BMP的载入

     

    unsigned char *LoadBitmapFile(char *filename,BITMAPINFOHEADER *bitmapInfoHeader)

    {

       FILE                              *filePtr;                      //文件指针

       BITMAPFILEHEADER        bitmapFileHeader;  //位图头文件

       unsigned char           *bitmapImage;                  //位图图像数据

       int                                          imageIdx =0;             //位图索引计时器

       unsigned char           tempRGB;                           //交换变量

     

       filePtr=fopen(filename,"rb");                     //以读二进制模式打开文件

       if (filePtr==NULL)

       {

                return       NULL;

       }

       fread(&bitmapFileHeader,sizeof(BITMAPFILEHEADER),1,filePtr);

     

       if (bitmapFileHeader.bfType!=0x4d42)    //检查是否是BMP图像

       {

                fclose(filePtr);

                return       NULL;

       }

       fread(&bitmapInfoHeader,sizeof(BITMAPINFOHEADER),1,filePtr);//读取图像信息头

     

       fseek(filePtr,bitmapFileHeader.bfOffBits,SEEK_SET);                        //将文件指针移动到位图数据开始处

     

       bitmapImage = (unsigned char *)malloc(bitmapInfoHeader->biSizeImage);

     

       if (!bitmapImage)

       {

                free(bitmapImage);

                fclose(filePtr);

                return       NULL;

       }

     

       fread(bitmapImage,1,bitmapInfoHeader->biSizeImage,filePtr);   //读入位图图像数据

     

       if(bitmapImage==NULL)

       {

                fclose(filePtr);

                return       NULL;

       }

     

       //位图的颜色格式是BGR,交换RB的值

       for(imageIdx=0;imageIdx<bitmapInfoHeader->biSizeImage;imageIdx+=3)

       {

                tempRGB          = bitmapImage[imageIdx];

                bitmapImage[imageIdx] = bitmapImage[imageIdx+2];

                bitmapImage[imageIdx+2]      =       tempRGB;

       }

     

       fclose(filePtr);

       return       bitmapImage;

     

    }

     

    简单应用:

    BITMAPINFOHEADER  bitmapInfoHeader;

    unsigned char *      bitmapData;

    bitmapData  =LoadBitmapFile(“test.bmp”,&bitmapInfoHeader);

    glPixelStorei(GL_UNPACK_ALIGNMENT,4);

    glRasterPos2i(100,100);

    glDrawPixels(bitmapInfoHeader.biWidth,bitmapInfoHeader.biHeight,GL_RGB,GL_UNSIGNED_BYTE,bitmapData);

    3.       BMP的输出

     

    int WriteBitmapFile(char *filename,int width,int height,unsigned char *imageData)

    {

       FILE           *filePtr;             //      文件指针

       BITMAPFILEHEADER        bitmapFileHeader;  //位图文件头

       BITMAPINFOHEADER      bitmapInfoHeader; //位图信息头

     

       int                       imageIdx;                   //用于RGB->BGR交互

     

       unsigned char tempRGB;                  //用于RGB->BGR交互

     

       filePtr = fopen(filename,"wb");

       if(!filePtr)

                return       0;

     

       //定义位图文件头

       bitmapFileHeader.bfSize = sizeof(BITMAPFILEHEADER);

       bitmapFileHeader.bfType = 0x4D42;

       bitmapFileHeader.bfReserved1 = 0;

       bitmapFileHeader.bfReserved2 = 0;

       bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);

     

       //定义位图信息头

       bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);

       bitmapInfoHeader.biPlanes = 1;

       bitmapInfoHeader.biBitCount = 24;         //24位图

       bitmapInfoHeader.biCompression = BI_RGB;         //无压缩

       bitmapInfoHeader.biSizeImage = width*abs(height)*3;//w*h*(RGB字节数)

       bitmapInfoHeader.biXPelsPerMeter = 0;

       bitmapInfoHeader.biYPelsPerMeter = 0;

       bitmapInfoHeader.biClrUsed = 0;

       bitmapInfoHeader.biClrImportant = 0;

       bitmapInfoHeader.biWidth = width;

       bitmapInfoHeader.biHeight = height;

     

       for (imageIdx = 0;imageIdx<bitmapInfoHeader.biSizeImage;imageIdx+=3)

       {

                tempRGB = imageData[imageIdx];

                imageData[imageIdx] = imageData[imageIdx+2];

                imageData[imageIdx+2] = tempRGB;

       }

      

       fwrite(&bitmapFileHeader,1,sizeof(BITMAPFILEHEADER),filePtr);//写位图文件头

       fwrite(&bitmapInfoHeader,1,sizeof(BITMAPINFOHEADER),filePtr);//写位图信息头

       fwrite(imageData,1,bitmapInfoHeader.biSizeImage,filePtr);         //写图像数据

     

       fclose(filePtr);//关闭文件

       return 1;

    }

    简单应用:

    unsigned char * imageData;

    imageData = malloc(winWidth*winHeight*3);分配内存

    memset(imageData,0,winWidth*winHeight*3);清理imageData内存中的内容

    //从窗口读取数据

    glReadPixels(0,0,winWidth-1,winHeight-1,GL_RGB,GL_UNSIGNED_BYTE,imageData);

    WriteBitmapFile(“writeout.bmp”,winWidth,winHeight,(unsigned char *)imageData);

    free(imageData);

    4.        

    5.       Targa图像文件

    TGABMP的基础上又添加了一个alpha通道

    1.       TGA文件格式

    TGA文件格式分为两个部分:头+数据

    头结构如下:

    typedef struct tagTARGAFILEHEADER

    {

    unsigned char  imageIDLength;  //标识(ID)数据项中的字符数

                                                                  //0表示没有表示数据项

    unsigned char colorMapType;      //颜色位图类型 总为0

    unsigned char imageTypeCode;  //未压缩的RGB2

                                                                 //未压缩的灰度为3

    short int colorMapOrigin;      //颜色图(低-高)的原点,总为0

    short int colorMapLength;     //颜色图(低-高)的长度,总为0

    short int colorMapEntrySize;  //颜色图元素大小尺寸(低-高),总为0

    (这里应该是一个字节 不是short int

    参见:http://www.worldlingo.com/ma/dewiki/zh_cn/Targa_Image_File

     

    short int imageXorigin;      //图像(低-高)左下角的x坐标,总为0

    short int imageYorigin;      //图像(低-高)左下角的y坐标,总为0

    short int imageWidth;       //图像(低-高)的像素宽度

    short int imageHeight;      //图像(低-高)的像素高度

    unsigned char bitCount;   //位数 16 2432

    unsigned char imageDescriptor;   //24=0x0032=0x08

    }TARGAFILEHEADER;

    在头数据结构结束后紧接着就是Targa图像数据

    在头数据结构首先要关注的是imageTypeCode,此项数据表面了要处理的Targa文件类型,

    imageTypeCode:

    2------未压缩的RGB

    3------未压缩的黑白图

    10----游长编码RGB

    11----压缩黑白图像

    2.       Targa图像的载入

     

    typedef struct 

    {

       unsigned char imageTypeCode;

       short int     imageWidth;

       short int     imageHeight;

       unsigned char bitCount;

       unsigned char *imageData;

    }TGAFILE;

     

    int LoadTGAFile(char *filename,TGAFILE *tgaFile)

    {

       FILE  *filePtr;    //      文件指针

       unsigned char ucharBad; //无用的无符号字符数据

       short int   sintBad;   //无用的短整数数据

       long           imageSize;        //TGA文件的大小尺寸

       int                       colorMdoe;      //RGBA4RGB3

       long           imageIdx;         //计数器变量

       unsigned char colorSwap;//交换变量

     

       filePtr = fopen(filename,"rb");

       if(!filePtr)

                return 0;

     

       //读取前两个不需要的字节

       fread(&ucharBad,sizeof(unsigned char),1,filePtr);

       fread(&ucharBad,sizeof(unsigned char),1,filePtr);

     

       //读入图像类型码

       fread(&tgaFile->imageTypeCode,sizeof(unsigned char),1,filePtr);

     

       //只处理未压缩的图像

       if ((tgaFile->imageTypeCode!=2)&&(tgaFile->imageTypeCode!=3))

       {

                fclose(filePtr);

                return 0;

       }

       //读取13个不需要的数据字节     (应该是9个)

       fread(&sintBad,sizeof(short int),1,filePtr);

       fread(&sintBad,sizeof(short int),1,filePtr);

       fread(&ucharBad,sizeof(unsigned char),1,filePtr);

       fread(&sintBad,sizeof(short int),1,filePtr);

       fread(&sintBad,sizeof(short int),1,filePtr);

     

       //读取图像尺寸大小

       fread(&tgaFile->imageWidth,sizeof(short int),1,filePtr);

       fread(&tgaFile->imageHeight,sizeof(short int),1,filePtr);

       //读取图像位深度

       fread(&tgaFile->bitCount,sizeof(short int),1,filePtr);

       //读取1个不需要的数据字节

       fread(&ucharBad,sizeof(unsigned char),1,filePtr);

     

       colorMdoe = tgaFile->bitCount/8;

       imageSize = tgaFile->imageWidth*tgaFile->imageHeight*colorMdoe;

       //分配内存

       tgaFile->imageData = (unsigned char*)malloc(sizeof(unsigned char)*imageSize);

       //读入图像数据

       fread(&tgaFile->imageData,sizeof(unsigned char),imageSize,filePtr);

       //BGR转换为RGB

       for (imageIdx = 0,imageIdx<imageSize;imageIdx +=colorMdoe)

       {

                colorSwap = tgaFile->imageData[imageIdx];

                tgaFile->imageData[imageIdx] = tgaFile->imageData[imageIdx+2];

                tgaFile->imageData[imageIdx+2] = colorSwap;

       }

       //关闭文件

       fclose(filePtr);

       return 1;

    }

    简单应用:

    TGAFILE *myTga;

    myTga = (TGAFILE *)malloc(sizeof(TGAFILE));

    LoadTGAFile("test.tga",myTga);

    glPixelStorei(GL_UNPACK_ALIGNMENT,4);

    glRasterPos2i(200,200);

    glDrawPixels(myTga->imageWidth,myTga->imageHeight,GL_RGB,GL_UNSIGNED_BYTE,myTga->imageData);

    3.       Targa图像的输出

    需要指定tga文件类型、位深度、使用RGB还是RGBA颜色模式,头数据结构中不重要的数据项设置为0

    int WriteTGAFile(char * filename,short int width,short int height,unsigned char *imaeData)

    {

       unsigned char  byteSkip;  //      用于无用数据字节

       short int            shortSkip;         //      用于短整数型的无用数据

       unsigned char  imageType;      //  tga图像类型

       int                                colorMode;      //图像颜色模式

       unsigned char  colorSwap;       //用于BGR->RGB转换

       int                                imageIdx;         //BGR->RGB转换计数器

       unsigned char  bitDepth; //图像位深度

       long                    imageSize;        //图像数据大小尺寸

       FILE                    *filePtr;    //文件指针

     

       filePtr = fopen(filename,"wb");

       if (!filePtr)

       {

                fclose(filePtr);

                return 0;

       }

       imageType = 2; //未压缩的RGB

       bitDepth = 24; //24位深度

       colorMode = 3;         //RGB颜色模式

      

       byteSkip = 0;    //无用字节数据

       byteSkip = 0;    //无用短整数型数据

     

       //先写两个字节的空白数据

       fwrite(&byteSkip,sizeof(unsigned char),1,filePtr);

       fwrite(&byteSkip,sizeof(unsigned char),1,filePtr);

     

       //tga图像类型

       fwrite(&imageType,sizeof(unsigned char),1,filePtr);

     

       //9个字节的空白数据

       fwrite(&shortSkip,sizeof(short int),1,filePtr);

       fwrite(&shortSkip,sizeof(short int),1,filePtr);

       fwrite(&byteSkip,sizeof(unsigned char),1,filePtr);

       fwrite(&shortSkip,sizeof(short int),1,filePtr);

       fwrite(&shortSkip,sizeof(short int),1,filePtr);

       //写图像大小尺寸

       fwrite(&width,sizeof(short int),1,filePtr);

       fwrite(&height,sizeof(short int),1,filePtr);

       fwrite(&bitDepth,sizeof(unsigned char),1,filePtr);

       //写一个字节的空白数据

       fwrite(&byteSkip,sizeof(unsigned char),1,filePtr);

       //计算图像数据尺寸

       imageSize = width*height*colorMode;

       //将图像数据从RGB转换为BGR

       for(imageIdx = 0;imageIdx<imageSize;imageIdx+=colorMode)

       {

                colorSwap = imaeData[imageIdx];

                imaeData[imageIdx] = imaeData[imageIdx+2];

                imaeData[imageIdx+2] = colorSwap;

       }

       fwrite(imaeData,sizeof(unsigned char),imageSize,filePtr);

       fclose(filePtr);

       return 1;

    }

    简单应用:

    unsigned char *imageData;

    imageData = malloc(800*600*3);

    memset(imageData,0,800*600*3);

     

    //从窗口获得图像

    glReadPixels(0,0,799,599,GL_RGB,GL_UNSIGNED_BYTE,imageData);

    //将图像写如文件

    WriteTGAFile("writeout.tga",800,600,(unsigned char *)imageData);

    //释放图像数据内存

    free(imageData);

    6.        

  • 相关阅读:
    批量导入
    循环语句
    判断循环常见
    常见C运算符
    oc将字符串中单词按照出现次数(次数都不一样)降序排序,排序之后单词只出现一次,源字符串中单词用下划线连接,生成字符串也用下滑线连接
    把字符串中的字母大小写反转OC
    查找子串出现次数OC
    现有一个数组NSMutableArray, 数组有若干个NSString的元素,进行选择法排序
    终端的一些命令
    编程语言名字来历
  • 原文地址:https://www.cnblogs.com/ezhong/p/2171465.html
Copyright © 2011-2022 走看看