【转】 OpenGL使用libPng读取png图片
觉得自己越来越无耻了呢?原文:http://laoyin.blog.51cto.com/4885213/895554
我复制到windows下也可以正常跑出来。
1 #include<stdarg.h> 2 #include<png.h> 3 #include<glut.h> 4 #include<math.h> 5 #include<iostream> 6 7 8 #pragma comment(lib,"libpng16.lib")//读取png图片 9 GLuint CreateTextureFromPng(const char* filename) 10 { 11 unsigned char header[8]; //8 12 int k; //用于循环 13 GLuint textureID; //贴图名字 14 int width, height; //记录图片到宽和高 15 png_byte color_type; //图片到类型(可能会用在是否是开启来通道) 16 png_byte bit_depth; //字节深度 17 18 png_structp png_ptr; //图片 19 png_infop info_ptr; //图片的信息 20 int number_of_passes; //隔行扫描 21 png_bytep * row_pointers;//图片的数据内容 22 int row,col,pos; //用于改变png像素排列的问题。 23 GLubyte *rgba; 24 25 FILE *fp=fopen(filename,"rb");//以只读形式打开文件名为file_name的文件 26 if(!fp)//做出相应可能的错误处理 27 { 28 fclose(fp);//关闭打开的文件!给出默认贴图 29 return 0;//此处应该调用一个生成默认贴图返回ID的函数 30 } 31 //读取文件头判断是否所png图片.不是则做出相应处理 32 fread(header, 1, 8, fp); 33 if(png_sig_cmp(header,0,8)) 34 { 35 fclose(fp); 36 return 0; //每个错误处理都是一样的!这样报错之后锁定就要花点小时间来! 37 } 38 39 //根据libpng的libpng-manual.txt的说明使用文档 接下来必须初始化png_structp 和 png_infop 40 png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); //后三个是绑定错误以及警告的函数这里设置为空 41 if(!png_ptr)//做出相应到初始化失败的处理 42 { 43 fclose(fp); 44 return 0; 45 } 46 //根据初始化的png_ptr初始化png_infop 47 info_ptr=png_create_info_struct(png_ptr); 48 49 if(!info_ptr) 50 { 51 //初始化失败以后销毁png_structp 52 png_destroy_read_struct(&png_ptr,(png_infopp)NULL,(png_infopp)NULL); 53 fclose(fp); 54 return 0; 55 } 56 57 58 //老老实实按照libpng给到的说明稳定步骤来 错误处理! 59 if (setjmp(png_jmpbuf(png_ptr))) 60 61 { 62 //释放占用的内存!然后关闭文件返回一个贴图ID此处应该调用一个生成默认贴图返回ID的函数 63 64 png_destroy_read_struct(&png_ptr,(png_infopp)NULL,(png_infopp)NULL); 65 66 fclose(fp); 67 68 return 0; 69 70 } 71 //你需要确保是通过2进制打开的文件。通过i/o定制函数png_init_io 72 png_init_io(png_ptr,fp); 73 //似乎是说要告诉libpng文件从第几个开始missing 74 png_set_sig_bytes(png_ptr, 8); 75 //如果你只想简单的操作你现在可以实际读取图片信息了! 76 png_read_info(png_ptr, info_ptr); 77 //获得图片到信息 width height 颜色类型 字节深度 78 width = png_get_image_width(png_ptr, info_ptr); 79 height = png_get_image_height(png_ptr, info_ptr); 80 color_type = png_get_color_type(png_ptr, info_ptr); 81 //如果图片带有alpha通道就需要 82 // if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) 83 84 // png_set_swap_alpha(png_ptr); 85 bit_depth = png_get_bit_depth(png_ptr, info_ptr); 86 //隔行扫描图片 这个必须要调用才能进行 87 number_of_passes = png_set_interlace_handling(png_ptr); 88 //将读取到的信息更新到info_ptr 89 png_read_update_info(png_ptr, info_ptr); 90 91 //读文件 92 if (setjmp(png_jmpbuf(png_ptr))){ 93 fclose(fp); 94 return 0; 95 } 96 rgba=(GLubyte*)malloc(width * height * 4); 97 //使用动态数组 设置长度 98 row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); 99 100 for (k = 0; k < height; k++) 101 row_pointers[k] = NULL; 102 103 //通过扫描流里面的每一行将得到的数据赋值给动态数组 104 for (k=0; k<height; k++) 105 //row_pointers[k] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr)); 106 row_pointers[k] = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr, 107 info_ptr)); 108 //由于png他的像素是由 左-右-从顶到底 而贴图需要的像素都是从左-右-底到顶的所以在这里需要把像素内容进行一个从新排列 109 //读图片 110 png_read_image(png_ptr, row_pointers); 111 112 pos = (width * height * 4) - (4 * width); 113 for( row = 0; row < height; row++) 114 { 115 for( col = 0; col < (4 * width); col += 4) 116 { 117 rgba[pos++] = row_pointers[row][col]; // red 118 rgba[pos++] = row_pointers[row][col + 1]; // green 119 rgba[pos++] = row_pointers[row][col + 2]; // blue 120 rgba[pos++] = row_pointers[row][col + 3]; // alpha 121 } 122 pos=(pos - (width * 4)*2); 123 } 124 125 126 //开启纹理贴图特效 127 glEnable(GL_TEXTURE_2D); 128 129 //创建纹理 130 glGenTextures(1,&textureID); 131 //绑定纹理 132 glBindTexture(GL_TEXTURE_2D,textureID); //将纹理绑定到名字 133 134 //设置贴图和纹理的混合效果这里是默认只用纹理 135 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 136 //设置纹理所用到图片数据 137 glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,rgba); 138 139 //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); 140 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); 141 142 free(row_pointers); 143 fclose(fp); 144 return textureID; 145 } 146 147 void display() 148 { 149 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 150 glEnable(GL_TEXTURE_2D); 151 glBindTexture(GL_TEXTURE_2D,CreateTextureFromPng("test.png")); 152 glBegin(GL_QUADS); 153 glTexCoord2f(0.0f,0.0f);glVertex2f(-60.0f,-60.0f); 154 glTexCoord2f(1.0f, 0.0f); glVertex2f(60.0f, -60.0f); 155 glTexCoord2f(1.0f, 1.0f); glVertex2f( 60.0f, 60.0f); 156 glTexCoord2f(0.0f, 1.0f); glVertex2f( -60.0f, 60.0f); 157 glEnd(); 158 glDisable(GL_TEXTURE_2D); 159 glutSwapBuffers(); 160 } 161 162 void Reshape(GLsizei w,GLsizei h) 163 { 164 if(h<0) 165 { 166 h=1; 167 } 168 glViewport(0,0,w,h); 169 glMatrixMode(GL_PROJECTION); 170 glLoadIdentity(); 171 glOrtho(-100,100,-100,100,-100,100); 172 glMatrixMode(GL_MODELVIEW); 173 glLoadIdentity(); 174 } 175 176 int main(int ac,char** av) 177 { 178 glutInit(&ac,av); 179 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); 180 glutCreateWindow("pngtest"); 181 glClearColor(1.0,1.0,1.0,1.0); 182 glutDisplayFunc(display); 183 glutReshapeFunc(Reshape); 184 glutMainLoop(); 185 return 0; 186 }