zoukankan      html  css  js  c++  java
  • PNG图片数据解析

    PNG是一种非常流行的图片格式,它不仅支持透明效果,而且图片数据经过了压缩处理,所以广泛用于web等应用。

    PNG的文件格式:

      PNG文件中的数据,总是以一个固定的8个字节开头:

        (图片来自http://blog.csdn.net/bisword/article/details/2777121

      除此之外,PNG的其他数据都是以数据块的方式组织,它们被分为标准数据块和辅助数据块,其中的辅助数据块是可选的。关键数据块包含我们必须的图片信息,我们之后要重点解析的也是关键数据块。

      

      (图片来自http://blog.csdn.net/bisword/article/details/2777121

    每种数据块的结构:

      

        (图片来自http://blog.csdn.net/bisword/article/details/2777121

      Length:该数据块的中Chunk Data的长度;

      Chunk Type Code:数据类型,就是指上面提到的IHDR,IEND等;

      Chunk Data:数据区域,如果是IDAT,就表示存储的还未解压的图片数据;

      CRC:循环冗余效验码;

    具体实现:(实现中没有处理png数据中变形的情况,部分头中的宏定义来自libpng,实例不具备实用性,仅作参考)

    头文件:

      1 #ifndef __PNG__
      2 #define __PNG__
      3 
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <math.h>
      7 #include "zlib/zlib.h"
      8 
      9 /**
     10  * 类型标志
     11  */
     12 #define PNG_FLAG_HEX "89504E470D0A1A0A"
     13 
     14 /**
     15  * 数据块类型
     16  */
     17 #define DATA_CHUNK_TYPE_IHDR "IHDR"
     18 #define DATA_CHUNK_TYPE_IDAT "IDAT"
     19 #define DATA_CHUNK_TYPE_IEND "IEND"
     20 #define DATA_CHUNK_TYPE_tEXt "tEXt"
     21 #define DATA_CHUNK_TYPE_iTXt "iTXt"
     22 
     23 /**
     24  * 过滤方式
     25  */
     26 #define DATA_FILTER_TYPE_DEFAULT 0
     27 #define DATA_FILTER_TYPE_ADD_ROW 1
     28 #define DATA_FILTER_TYPE_ADD_UP  2
     29 #define DATA_FILTER_TYPE_AVERGE  3
     30 #define DATA_FILTER_TYPE_PAETH   4
     31 
     32 /* color type masks */
     33 #define PNG_COLOR_MASK_PALETTE    1
     34 #define PNG_COLOR_MASK_COLOR      2
     35 #define PNG_COLOR_MASK_ALPHA      4
     36 
     37 /* color types.  Note that not all combinations are legal */
     38 #define PNG_COLOR_TYPE_GRAY           0
     39 #define PNG_COLOR_TYPE_PALETTE    (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
     40 #define PNG_COLOR_TYPE_RGB        (PNG_COLOR_MASK_COLOR)
     41 #define PNG_COLOR_TYPE_RGB_ALPHA  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
     42 #define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
     43 
     44 #define RGB_USE_ALPHA(vr, vg, vb, va) 
     45     (unsigned)(((unsigned)((unsigned char)(vr) * ((unsigned char)(va) + 1)) >> 8) | 
     46     ((unsigned)((unsigned char)(vg) * ((unsigned char)(va) + 1) >> 8) << 8) | 
     47     ((unsigned)((unsigned char)(vb) * ((unsigned char)(va) + 1) >> 8) << 16) | 
     48     ((unsigned)(unsigned char)(va) << 24))
     49 
     50 /**
     51  * 一次解压图片数据的限制
     52  */
     53 #define DECOMPRESSION_MAX_BYTES 8192
     54 
     55 /**
     56  * 数据块信息
     57  */
     58 typedef struct _DataChunkHeader 
     59 {
     60     // 数据长度
     61     unsigned char length[4];
     62     // 数据类型
     63     unsigned char type[4];
     64 } DataChunkHeader;
     65 
     66 /**
     67  * IHDR数据
     68  */
     69 typedef struct _IDHRData
     70 {
     71     unsigned char width[4];
     72     unsigned char height[4];
     73     unsigned char bitDepth[1];
     74     unsigned char colorType[1];
     75     unsigned char compressionMethod[1];
     76     unsigned char filterMethod[1];
     77     unsigned char interlaceMethod[1];
     78 } IDHRData;
     79 
     80 /**
     81  * PNG图片类
     82  */
     83 class PNG
     84 {
     85 public:
     86     PNG();
     87     PNG(const char* filePath);
     88 
     89     ~PNG();
     90 
     91     int getWindth();
     92     int getHeight();
     93 
     94     /**
     95      * 获取图片宽度
     96      */
     97     unsigned char* getImageData();
     98 
     99 private:
    100     int m_width;
    101     int m_height;
    102 
    103     unsigned char m_bitDepth;
    104     unsigned char m_colorType;
    105     unsigned char m_compressionMethod;
    106     unsigned char m_filterMethod;
    107     unsigned char m_interlaceMethod;
    108     unsigned char m_chanels;
    109 
    110     unsigned char* m_imageData;
    111 
    112     /**
    113      * 从文件加载图片数据
    114      */
    115     bool loadImageDataFromFile(const char* filePath);
    116 
    117     /**
    118      * 解析数值
    119      */
    120     int parseNumber(const unsigned char* data, int len);
    121 
    122     /**
    123      * 解压数据
    124      */
    125     int decompressData(z_stream* zStream, unsigned char* data, int dataLen, int leftLen, FILE *pFile);
    126 
    127     /**
    128      * 生成图片数据
    129      */
    130     void generateImageData(unsigned char* data, unsigned long dataLen);
    131 
    132     /**
    133      * 默认的过滤方式
    134      */
    135     void defaultFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes);
    136 
    137     /**
    138      * 当前行相加的过滤方式
    139      */
    140     void addCurrentRowFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes);
    141 
    142     /**
    143      * 前一行相加的过滤方式
    144      */
    145     void addUpRowFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes);
    146 
    147     /**
    148      * 平均的过滤方式
    149      */
    150     void avergeFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes);
    151 
    152     /**
    153      * paeth的过滤方式
    154      */
    155     void paethFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes);
    156 
    157     /**
    158      * 解析IHDR数据
    159      */
    160     void parseIHDRData(DataChunkHeader& dataChunkHeader, FILE* pFile);
    161 
    162     /**
    163      * 解析IDAT数据
    164      */
    165     void parseIDATData(DataChunkHeader& dataChunkHeader, FILE* pFile);
    166 
    167     /**
    168      * 解析IEND数据
    169      */
    170     void parseIENDData(DataChunkHeader& dataChunkHeader, FILE *pFile);
    171 
    172     /**
    173      * 解析其他数据
    174      */
    175     void parseCommonData(DataChunkHeader& dataChunkHeader, FILE *pFile);
    176 };
    177 
    178 #endif

    cpp文件:

      1 #include "png.h"
      2 #include "utils/cUtil.h"
      3 #include <stdlib.h>
      4 
      5 #include <windows.h>
      6 
      7 /**
      8  * 默认构造函数
      9  */
     10 PNG::PNG()
     11 {
     12     this->m_width = 0;
     13     this->m_height = 0;
     14 
     15     this->m_imageData = 0;
     16 }
     17 
     18 /**
     19  * 构造函数
     20  * @param filePath 图片路径
     21  */
     22 PNG::PNG(const char *filePath)
     23 {
     24     this->m_width = 0;
     25     this->m_height = 0;
     26 
     27     this->loadImageDataFromFile(filePath);
     28 }
     29 
     30 /**
     31  * 析构函数
     32  */
     33 PNG::~PNG()
     34 {
     35 
     36 }
     37 
     38 /**
     39  * 从文件加载图片数据
     40  */
     41 bool PNG::loadImageDataFromFile(const char* filePath)
     42 {
     43     FILE* pFile = fopen(filePath, "rb");
     44     if (!pFile)
     45         return false;
     46 
     47     // 解析PNG标志
     48     char flag[8];
     49     char hexFlag[17];
     50     fread(flag, 1, 8, pFile);
     51     toHexStr(flag, 8, hexFlag);
     52     if (strcmp(hexFlag, PNG_FLAG_HEX) != 0)
     53         return false;
     54 
     55     // 解析图片数据
     56     DataChunkHeader dataChunkHeader;
     57     char dataChunkHeaderType[5];
     58     do {
     59         fread(&dataChunkHeader, 1, sizeof(DataChunkHeader), pFile);
     60 
     61         memcpy(dataChunkHeaderType, dataChunkHeader.type, 4);
     62         dataChunkHeaderType[4] = '';
     63 
     64         // IHDR
     65         if ( strcmp(dataChunkHeaderType, DATA_CHUNK_TYPE_IHDR) == 0 ) {
     66             this->parseIHDRData(dataChunkHeader, pFile);
     67         }
     68         // IDAT
     69         else if ( strcmp(dataChunkHeaderType, DATA_CHUNK_TYPE_IDAT) == 0 ) {
     70             this->parseIDATData(dataChunkHeader, pFile);
     71         }
     72         // IEND
     73         else if ( strcmp(dataChunkHeaderType, DATA_CHUNK_TYPE_IEND) == 0 ) {
     74             this->parseIENDData(dataChunkHeader, pFile);
     75         }
     76         // 其他数据
     77         else {
     78             this->parseCommonData(dataChunkHeader, pFile);
     79         }
     80     } while( strcmp(dataChunkHeaderType, DATA_CHUNK_TYPE_IEND) != 0 );
     81 
     82     int i = 1;
     83 
     84     return true;
     85 }
     86 
     87 /**
     88  * 解析数值
     89  */
     90 int PNG::parseNumber(const unsigned char* data, int len)
     91 {
     92     char localNum[4];
     93 
     94     bool isLittleEndian = checkEndian();
     95     for (int i = 0; i<4; i++) {
     96         char ch;
     97 
     98         if (isLittleEndian) {
     99             if (i <= len-1)
    100                 ch = data[len - 1 - i];
    101             else
    102                 ch = '';
    103         }
    104         else {
    105             if (i <= len-1)
    106                 ch = data[i];
    107             else
    108                 ch = '';
    109         }
    110         localNum[i] = ch;
    111     }
    112 
    113     int num;
    114     memcpy(&num, localNum, 4);
    115     return num;
    116 }
    117 
    118 /**
    119  * 解析IHDR数据
    120  */
    121 void PNG::parseIHDRData(DataChunkHeader& dataChunkHeader, FILE* pFile)
    122 {
    123     int dataLen = this->parseNumber(dataChunkHeader.length, 4);
    124 
    125     IDHRData idhrData;
    126     char crc[4];
    127 
    128     fread(&idhrData, 1, sizeof(IDHRData), pFile);
    129     fread(crc, 1, 4, pFile);
    130 
    131     this->m_width              = this->parseNumber(idhrData.width, 4);
    132     this->m_height              = this->parseNumber(idhrData.height, 4);
    133     this->m_bitDepth          = this->parseNumber(idhrData.bitDepth, 1);
    134     this->m_colorType          = this->parseNumber(idhrData.colorType, 1);
    135     this->m_compressionMethod = this->parseNumber(idhrData.compressionMethod, 1);
    136     this->m_filterMethod      = this->parseNumber(idhrData.filterMethod, 1);
    137     this->m_interlaceMethod   = this->parseNumber(idhrData.interlaceMethod, 1);
    138     this->m_chanels              = 0;
    139 
    140     switch (this->m_colorType) {
    141         case PNG_COLOR_TYPE_GRAY:
    142         case PNG_COLOR_TYPE_PALETTE:
    143             this->m_chanels = 1;
    144         break;
    145         case PNG_COLOR_TYPE_RGB:
    146             this->m_chanels = 3;
    147         break;
    148         case PNG_COLOR_TYPE_GRAY_ALPHA:
    149             this->m_chanels = 2;
    150         break;
    151         case PNG_COLOR_TYPE_RGB_ALPHA:
    152             this->m_chanels = 4;
    153         break;
    154         default:
    155             this->m_chanels = 0;
    156         break;
    157    }
    158 }
    159 
    160 /**
    161  * 解压数据
    162  */
    163 int PNG::decompressData(z_stream* zStream, unsigned char* data, int dataLen, int leftLen, FILE *pFile)
    164 {
    165     int result = 0;
    166 
    167     int leftBytesCount = leftLen;
    168     int avail_out = -1;
    169     do {
    170         if (zStream->avail_in == 0) {
    171             if (avail_out == 0) 
    172                 break;
    173             else {
    174                 if (leftBytesCount == 0) {
    175                     DataChunkHeader dataChunkHeader;
    176                     fread(&dataChunkHeader, 1, sizeof(DataChunkHeader), pFile);
    177 
    178                     int newDataLen = this->parseNumber(dataChunkHeader.length, 4);
    179                     unsigned char* newData = new unsigned char[dataLen + newDataLen];
    180                     char crc[4];
    181 
    182                     fread(newData + dataLen, 1, newDataLen, pFile);
    183                     fread(crc, 1, 4, pFile);
    184                     memcpy(newData, data, dataLen);
    185 
    186                     delete data;
    187                     data = newData;
    188 
    189                     zStream->next_in = newData + dataLen;
    190                     zStream->avail_in = newDataLen;
    191 
    192                     dataLen = dataLen + newDataLen;
    193                     
    194                     return this->decompressData(zStream, data, dataLen, 0, pFile);
    195                 }
    196             }
    197 
    198             // 导出数据是否超过限制
    199             if (leftBytesCount > DECOMPRESSION_MAX_BYTES)
    200                 zStream->avail_in = DECOMPRESSION_MAX_BYTES;
    201             else
    202                 zStream->avail_in = leftBytesCount;
    203 
    204             leftBytesCount -= zStream->avail_in;
    205         }
    206         
    207         if (avail_out > 0)
    208             zStream->avail_out = avail_out;
    209         else
    210             zStream->avail_out = m_width * 4 + 1;
    211 
    212         result = inflate(zStream, Z_NO_FLUSH);
    213         if (result != Z_OK)
    214             break;
    215 
    216         avail_out = zStream->avail_out;
    217     } while (zStream->avail_in >= 0);
    218 
    219     return result;
    220 }
    221 
    222 /**
    223  * 生成图片数据
    224  */
    225 void PNG::generateImageData(unsigned char* data, unsigned long dataLen)
    226 {
    227     // 行字节数
    228     int rowBytes = this->m_chanels * this->m_width;
    229 
    230     // 初始化图片数据
    231     this->m_imageData = new unsigned char[rowBytes * this->m_height];
    232 
    233     unsigned char* pImageData = this->m_imageData;
    234     unsigned char* pRowData = data;
    235 
    236     for (int rowIndex = 0; rowIndex < this->m_height; rowIndex++) {
    237         // 过滤类型
    238         unsigned char filterType = pRowData[0]; 
    239 
    240         pRowData += 1;
    241 
    242         switch (filterType) {
    243             // 不需要过滤处理
    244             case DATA_FILTER_TYPE_DEFAULT:
    245                 this->defaultFilterType(pImageData, pRowData, rowBytes);
    246             break;
    247             // 当前行相加
    248             case DATA_FILTER_TYPE_ADD_ROW:
    249                 this->addCurrentRowFilterType(pImageData, pRowData, rowBytes);
    250             break;
    251             // 和前一行相加
    252             case DATA_FILTER_TYPE_ADD_UP:
    253                 this->addUpRowFilterType(pImageData, pRowData, rowBytes);
    254             break;
    255             // 求平均
    256             case DATA_FILTER_TYPE_AVERGE:
    257                 this->avergeFilterType(pImageData, pRowData, rowBytes);
    258             break;
    259             // Paeth
    260             case DATA_FILTER_TYPE_PAETH:
    261                 this->paethFilterType(pImageData, pRowData, rowBytes);
    262             break;
    263             // 类型错误
    264             default:
    265             break;
    266         }
    267 
    268         pImageData += rowBytes;
    269         pRowData += rowBytes;
    270 
    271         char text[100];
    272         sprintf(text, "filter type:%d, rowIndex:%d 
    ", filterType, rowIndex);
    273         OutputDebugString(text);
    274     }
    275 
    276     int channel = rowBytes / this->m_width;
    277     if (channel == 4) {
    278         unsigned int *tmp = (unsigned int *)this->m_imageData;
    279 
    280         for (unsigned short i = 0; i < this->m_height; i++) {
    281             for (unsigned int j = 0; j < rowBytes; j+=4) {
    282                 unsigned int offset = i * rowBytes + j;
    283 
    284                 *tmp++ = RGB_USE_ALPHA(
    285                     this->m_imageData[offset], 
    286                     this->m_imageData[offset+1], 
    287                     this->m_imageData[offset+2],
    288                     this->m_imageData[offset+3] 
    289                 );
    290             }
    291         }
    292     }
    293 }
    294 
    295 /**
    296  * 默认的过滤方式
    297  */
    298 void PNG::defaultFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes)
    299 {
    300     for (int i = 0; i < rowBytes; i++) {
    301         *pImageData++ = *pRowData++;
    302     }
    303 }
    304 
    305 /**
    306  * 当前行相加的过滤方式
    307  */
    308 void PNG::addCurrentRowFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes)
    309 {
    310     for (int i = 0; i < rowBytes; i++) {
    311         if (i == 0) {
    312             memcpy(pImageData, pRowData, 4);
    313             i += 3;
    314             pImageData += 4;
    315             pRowData += 4;
    316         }
    317         else {
    318             *pImageData++ = (unsigned char)(((int)*(pRowData++) + (int)*(pImageData-4)) & 0xFF);
    319         }
    320     }
    321 }
    322 
    323 /**
    324  * 前一行相加的过滤方式
    325  */
    326 void PNG::addUpRowFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes)
    327 {
    328     for (int i = 0; i < rowBytes; i++) {
    329         *pImageData++ = (unsigned char)(((int)*(pRowData++) + (int)*(pImageData-rowBytes)) & 0xFF);
    330     }
    331 }
    332 
    333 /**
    334  * 平均的过滤方式
    335  */
    336 void PNG::avergeFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes)
    337 {
    338     for (int i = 0; i < rowBytes; i++) {
    339         int averge = 0;
    340 
    341         if (i <= 3) {
    342             averge = ((int)*(pImageData-rowBytes)) / 2;
    343 
    344             *pImageData++ = (unsigned char)((averge + (int)*(pRowData++)) & 0xFF);
    345         }
    346         else {
    347             averge = (((int)*(pImageData-4)) + ((int)*(pImageData-rowBytes))) / 2;
    348 
    349             *pImageData++ = (unsigned char)((averge + (int)*(pRowData++)) & 0xFF);
    350         }
    351     }
    352 }
    353 
    354 /**
    355  * paeth的过滤方式
    356  */
    357 int Paeth(int a, int b, int c)
    358 {
    359     int p  = a + b - c;
    360     int pa = abs(p - a);
    361     int pb = abs(p - b);
    362     int pc = abs(p - c);
    363     
    364     int Paeth;
    365     if(pa <= pb && pa <= pc)
    366         Paeth = a;
    367     else if (pb <= pc) 
    368         Paeth = b;
    369     else 
    370         Paeth = c;
    371     return Paeth ;
    372 }
    373 void PNG::paethFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes)
    374 {
    375     for (int i = 0; i < rowBytes; i++) {
    376         if (i <= 3) {
    377             *pImageData++ = (unsigned char)(((int)*(pRowData++) + (int)*(pImageData-rowBytes)) & 0xFF);
    378         }
    379         else {
    380             unsigned char left = *(pImageData - 4);
    381             unsigned char up = *(pImageData - rowBytes);
    382             unsigned char leftUp = *(pImageData - rowBytes - 4);
    383 
    384             int value = Paeth((int)left, (int)up, (int)leftUp);
    385             
    386             *pImageData++ = (unsigned char)(((int)*(pRowData++) + value) & 0xFF);
    387         }
    388     }
    389 }
    390 
    391 /**
    392  * 解析IDAT数据
    393  */
    394 void PNG::parseIDATData(DataChunkHeader& dataChunkHeader, FILE* pFile)
    395 {
    396     // 解压后的图片数据
    397     unsigned char* imageData = new unsigned char[m_width * m_height * 4];
    398 
    399     int dataLen = this->parseNumber(dataChunkHeader.length, 4);
    400     // 解压前的图片数据
    401     unsigned char* data = new unsigned char[dataLen];
    402     char crc[4];
    403     // 提取数据
    404     fread(data, 1, dataLen, pFile);
    405     fread(crc, 1, 4, pFile);
    406 
    407     // 存放临时的解压数据
    408     unsigned long decompressDataLen = m_width * m_height * 4 + m_height;
    409     unsigned char* decompressData = new unsigned char[decompressDataLen];
    410 
    411     z_stream* zStream = new z_stream();
    412     zStream->next_in = data;
    413     zStream->next_out = decompressData;
    414 
    415     inflateInit(zStream);
    416 
    417     // 解压数据
    418     this->decompressData(zStream, data, dataLen, dataLen, pFile);
    419     // 生成图片数据
    420     this->generateImageData(decompressData, decompressDataLen);
    421 
    422     /*
    423     int result = 0;
    424     // 开始解压数据
    425     int leftBytesCount = dataLen;
    426     int avail_out = -1;
    427     do {
    428         if (zStream->avail_in == 0) {
    429             if (avail_out == 0)
    430                 break;
    431             else {
    432                 if (leftBytesCount == 0) {
    433 
    434                 }
    435             }
    436 
    437             // 导出数据是否超过限制
    438             if (leftBytesCount > DECOMPRESSION_MAX_BYTES)
    439                 zStream->avail_in = DECOMPRESSION_MAX_BYTES;
    440             else
    441                 zStream->avail_in = leftBytesCount;
    442 
    443             leftBytesCount = dataLen - zStream->avail_in;
    444         }
    445         
    446         if (avail_out > 0)
    447             zStream->avail_out = avail_out;
    448         else
    449             zStream->avail_out = m_width * 4 + 1;
    450 
    451         result = inflate(zStream, Z_NO_FLUSH);
    452         if (result != Z_OK)
    453             break;
    454 
    455         avail_out = zStream->avail_out;
    456     } while (zStream->avail_in >= 0);
    457     // 数据解压是否成功
    458     if (result == Z_STREAM_END) {
    459         int i = 1;
    460     }
    461     */
    462 }
    463 
    464 /**
    465  * 解析IEND数据
    466  */
    467 void PNG::parseIENDData(DataChunkHeader& dataChunkHeader, FILE *pFile)
    468 {
    469     char crc[4];
    470     fread(crc, 1, 4, pFile);
    471 }
    472 
    473 /**
    474  * 解析其他数据
    475  */
    476 void PNG::parseCommonData(DataChunkHeader& dataChunkHeader, FILE *pFile)
    477 {
    478     int dataLen = this->parseNumber(dataChunkHeader.length, 4);
    479     fseek(pFile, dataLen + 4, SEEK_CUR);
    480 }
    481 
    482 /**
    483  * 获取图片宽度
    484  */
    485 unsigned char* PNG::getImageData()
    486 {
    487     return this->m_imageData;
    488 }
    489 
    490 /**
    491  * 获取图片宽度
    492  */
    493 int PNG::getWindth()
    494 {
    495     return this->m_width;
    496 }
    497 
    498 /**
    499  * 获取图片高度
    500  */
    501 int PNG::getHeight()
    502 {
    503     return this->m_height;
    504 }

    如果需要绘制图片,可以使用opengl库

    参考代码:

     1 glViewport(0, 0, winWidth, winHeight);    
     2 
     3 glMatrixMode(GL_PROJECTION);            
     4 glLoadIdentity();                        
     5 glOrtho(0.0f, winWidth - 1.0, 0.0, winHeight - 1.0, -10.0, 10.0);
     6 
     7 glMatrixMode(GL_MODELVIEW);    
     8 glLoadIdentity();        
     9 
    10 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    11 
    12 glEnable(GL_TEXTURE_2D);
    13 
    14 int width = png->getWindth();
    15 int height = png->getHeight();
    16 unsigned char* data = png->getImageData();
    17 
    18 GLuint name1;
    19 glGenTextures(1, &name1);
    20 glBindTexture(GL_TEXTURE_2D, name1);
    21 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    22 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    23 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,      GL_REPEAT);
    24 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,      GL_REPEAT);
    25 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,GL_RGBA, GL_UNSIGNED_BYTE, data); 
    26 glBegin(GL_POLYGON);
    27     glTexCoord2f(1, 1);
    28     glVertex3d(800, 800, 2);
    29     glTexCoord2f(0, 1);
    30     glVertex3d(0, 800, 2);
    31     glTexCoord2f(0, 0);
    32     glVertex3d(0, 0, 2);
    33     glTexCoord2f(1, 0);
    34     glVertex3d(800, 0, 2);
    35 glEnd();
  • 相关阅读:
    2019春第三次课程设计实验报告
    2019春第二次课程设计实验报告
    2019春第一次课程设计实验报告
    第十二周总结
    第十一周总结
    第五周课程总结&试验报告(三)
    第四周课程总结&实验报告(二)
    第三周课程总结&实验报告一
    第二周学习总结
    19春总结
  • 原文地址:https://www.cnblogs.com/iRidescent-ZONE/p/4193248.html
Copyright © 2011-2022 走看看