1. 程式人生 > >OpenGL使用libPng讀取png圖片

OpenGL使用libPng讀取png圖片

return comment 文件名 獲得 open tro missing rgba com

#include<stdarg.h>
#include<png.h>
#include<glut.h>
#include<math.h>
#include<iostream>

#pragma comment(lib,"libpng16.lib")//讀取png圖片
GLuint CreateTextureFromPng(const char* filename)
{
 unsigned char header[8];     //8
 int k;   //用於循環
 GLuint textureID; //貼圖名字
 int width, height; //記錄圖片到寬和高
 png_byte color_type; //圖片到類型(可能會用在是否是開啟來通道)
 png_byte bit_depth; //字節深度

 png_structp png_ptr; //圖片
 png_infop info_ptr; //圖片的信息
 int number_of_passes; //隔行掃描
 png_bytep * row_pointers;//圖片的數據內容
 int row,col,pos;  //用於改變png像素排列的問題。
 GLubyte *rgba;

 FILE *fp=fopen(filename,"rb");//以只讀形式打開文件名為file_name的文件
 if(!fp)//做出相應可能的錯誤處理
 {
  fclose(fp);//關閉打開的文件!給出默認貼圖
  return 0;//此處應該調用一個生成默認貼圖返回ID的函數
 }
        //讀取文件頭判斷是否所png圖片.不是則做出相應處理
        fread(header, 1, 8, fp);
 if(png_sig_cmp(header,0,8))
 {
  fclose(fp);
  return 0; //每個錯誤處理都是一樣的!這樣報錯之後鎖定就要花點小時間來!
 }
   
 //根據libpng的libpng-manual.txt的說明使用文檔 接下來必須初始化png_structp 和 png_infop
 png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); //後三個是綁定錯誤以及警告的函數這裏設置為空
 if(!png_ptr)//做出相應到初始化失敗的處理
 { 
  fclose(fp);
  return 0;
 }
 //根據初始化的png_ptr初始化png_infop
 info_ptr=png_create_info_struct(png_ptr);

 if(!info_ptr)
 {
  //初始化失敗以後銷毀png_structp
  png_destroy_read_struct(&png_ptr,(png_infopp)NULL,(png_infopp)NULL);
  fclose(fp);
  return 0;
 }

 
 //老老實實按照libpng給到的說明穩定步驟來  錯誤處理!
        if (setjmp(png_jmpbuf(png_ptr)))

     {
  //釋放占用的內存!然後關閉文件返回一個貼圖ID此處應該調用一個生成默認貼圖返回ID的函數

         png_destroy_read_struct(&png_ptr,(png_infopp)NULL,(png_infopp)NULL);

         fclose(fp);

         return 0;

     }
 //你需要確保是通過2進制打開的文件。通過i/o定制函數png_init_io
 png_init_io(png_ptr,fp);
 //似乎是說要告訴libpng文件從第幾個開始missing
        png_set_sig_bytes(png_ptr, 8);
 //如果你只想簡單的操作你現在可以實際讀取圖片信息了!
        png_read_info(png_ptr, info_ptr);
 //獲得圖片到信息 width height 顏色類型  字節深度
        width = png_get_image_width(png_ptr, info_ptr);
        height = png_get_image_height(png_ptr, info_ptr);
        color_type = png_get_color_type(png_ptr, info_ptr);
 //如果圖片帶有alpha通道就需要
// if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)

        // png_set_swap_alpha(png_ptr);
        bit_depth = png_get_bit_depth(png_ptr, info_ptr);
 //隔行掃描圖片  這個必須要調用才能進行
        number_of_passes = png_set_interlace_handling(png_ptr);
 //將讀取到的信息更新到info_ptr
        png_read_update_info(png_ptr, info_ptr);

 //讀文件
        if (setjmp(png_jmpbuf(png_ptr))){
  fclose(fp);
                return 0;
 }
        rgba=(GLubyte*)malloc(width * height * 4);
 //使用動態數組  設置長度
        row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
 
 for (k = 0; k < height; k++)
        row_pointers[k] = NULL;
  
 //通過掃描流裏面的每一行將得到的數據賦值給動態數組       
 for (k=0; k<height; k++)
                //row_pointers[k] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));
   row_pointers[k] = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr,
         info_ptr));
 //由於png他的像素是由 左-右-從頂到底 而貼圖需要的像素都是從左-右-底到頂的所以在這裏需要把像素內容進行一個從新排列
 //讀圖片
        png_read_image(png_ptr, row_pointers);

            pos = (width * height * 4) - (4 * width);
     for( row = 0; row < height; row++)
     {
        for( col = 0; col < (4 * width); col += 4)
        {
     rgba[pos++] = row_pointers[row][col];        // red
     rgba[pos++] = row_pointers[row][col + 1];    // green
     rgba[pos++] = row_pointers[row][col + 2];    // blue
     rgba[pos++] = row_pointers[row][col + 3];    // alpha
        }
        pos=(pos - (width * 4)*2);
     }

 //開啟紋理貼圖特效
        glEnable(GL_TEXTURE_2D);
 
 //創建紋理 
        glGenTextures(1,&textureID);
 //綁定紋理
        glBindTexture(GL_TEXTURE_2D,textureID); //將紋理綁定到名字
 
 //設置貼圖和紋理的混合效果這裏是默認只用紋理
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
 //設置紋理所用到圖片數據
        glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,rgba);
 
        //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
 
 free(row_pointers); 
 fclose(fp);
        return textureID;
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D,CreateTextureFromPng("test.png"));
	glBegin(GL_QUADS);
	glTexCoord2f(0.0f,0.0f);glVertex2f(-60.0f,-60.0f);
	 glTexCoord2f(1.0f, 0.0f); glVertex2f(60.0f, -60.0f);
	glTexCoord2f(1.0f, 1.0f); glVertex2f( 60.0f, 60.0f);
	glTexCoord2f(0.0f, 1.0f); glVertex2f( -60.0f, 60.0f); 
	glEnd();
	glDisable(GL_TEXTURE_2D);
	glutSwapBuffers();
}

void Reshape(GLsizei w,GLsizei h)
{
	if(h<0)
	{
		h=1;
	}
	glViewport(0,0,w,h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-100,100,-100,100,-100,100);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

int main(int ac,char** av)
{
	glutInit(&ac,av);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutCreateWindow("pngtest");
	glClearColor(1.0,1.0,1.0,1.0);
	glutDisplayFunc(display);
	glutReshapeFunc(Reshape);
	glutMainLoop();
	return 0;
}

OpenGL使用libPng讀取png圖片