OpenGL使用libPng读取png图片

#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;
}
时间: 2024-12-09 09:55:41

OpenGL使用libPng读取png图片的相关文章

libpng处理png图片(二)

一,实现效果:图片剪切, 图片拼接 -------切割后----->                        切割后的小图片 拼图的效果与此类似. 二,实现思想 利用上一篇所展示的libpng读写图片的函数,读出图片的数据域,然后对数据域进行"剪切"或者拼接获得新图片的数据域,最后通过libpng的库函数写入图片即可. 三,剪切图片的核心代码(代码内含注释) 思路:读出一张大图片的数据域buff, 按照数据与图片中像素对应的原则, 依次获取切割后每个小图片的数据域png_b

关于Opengl中将24位BMP图片加入?一个alpha通道并实现透明的问题

#include <windows.h>#include <GL/glut.h>#include <GL/glaux.h>#include <stdio.h> #pragma comment( lib, "opengl32.lib" )// 链接时使用OpenGL32.lib#pragma comment( lib, "glu32.lib" )// 链接时使用GLu32.lib  #pragma comment( li

OpenGL 绘制效果保存成图片

分享一下我老师大神的人工智能教程吧.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net opengl中有一个非常有用的函数:glReadPixels(),可以读取各种缓冲区(深度.颜色,etc)的数值.要将opengl的绘制场景保存成图片,也需要使用这个函数. 一个简单的例子见如下的c程序.按键盘上的“C”键,可以将读取的图像缓冲区数据存储成tmpcolor.txt. #include "windows.h"

【原创】Android 4.4前后版本读取图库图片方式的变化

Android 4.4前后版本读取图库图片方式的变化 本文讲述Android 4.4(KitKat)前后访问图库以及访问后通过图片路径读取图片的变化 Android 4.4(KitKat)以前: 访问图库(方法一): 1 /** 2 * Access the gallery to pick up an image. 3 */ 4 private void startPickPhotoActivity() { 5 Intent intent = new Intent(Intent. ACTION_

读取本地图片写到jsp页面

//读取本地图片写到jsp页面 File file = new File("D:/parking/A区12号.jpg"); ServletOutputStream out = null; InputStream in = null; try { in = new FileInputStream(file); response().setContentType("multipart/form-data"); int tempbyte; out = response()

C#从SQL server数据库中读取l图片和存入图片

原文:C#从SQL server数据库中读取l图片和存入图片 本实例主要介绍如何将图片存入数据库.将图片存入数据库,首先要在数据库中建立一张表,将存储图片的字段类型设为Image类型,用FileStream类.BinaryReader把图片读成字节的形式,赋给一个字节数组,然后用ADO.SqlCommand对象的ExecuteNonQuery()方法来把数据保存到数据库中.主要代码如下: private void button1_Click(object sender, EventArgs e)

android 读取,写入图片到sd卡源码

<pre name="code" class="html"><!--<span style="font-family: Arial, Helvetica, sans-serif;">在AndroidMainfest.xml文件中添加</span><span style="font-family: Arial, Helvetica, sans-serif;">-->&l

DB2保存图片并读取动态显示图片

博文背景: 客户要求结构化图片信息,而不是文件文档话的管理,故要求将图片信息存储于DB2里,出于技术的角度,真不喜欢将文件存储于数据库, 但客户是上帝,木有办法,故有了如下的测试. 测试环境:DB2 V9.7  JDK7  spring3.x tomcat8 本机测试结果:在第一次访问的时候动态获取的速度是直接获取的1/20的样子,如果缓存的话就无法对比了. 时间检测使用了chrome和firfox的F12工具. 写测试代码的过程中参考了网上很多文章,发现大部分都是copy来copy去,估计都没

数据库读取二进制图片显示到PictureBox中

1.已知路径,加载本地图片到Image中 Image img = Image.FromFile("路径"); 2.数据库中读取二进制图片 string strSql = "Select Top 1 ImageContent From TT_ImageFileSave)"; Byte[] byteImage = new Byte[0]; byteImage = (Byte[])(DbHelperSQL.GetSingle(strSql)); MemoryStream