1.glReadPixels
glReadPixels(GLint x,GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid*pixels)
glReadPixels 是将GPU渲染完数据,从GPU回传到host端的唯一方式,由入参(x,y,w,h)制定一个从一帧图像中读取内存的矩形,type和format指定格式,pixels是输出像素的buffer
注意:glReadPixels实际上是从缓冲区中读取数据,如果使用了双缓冲区,则默认是从正在显示的缓冲(即前缓冲)中读取,而绘制工作是默认绘制到后缓冲区的。因此,如果需要读取已经绘制好的像素,往往需要先交换前后缓冲
int *pixel = (int*)malloc(sizeof(int)*1440*2560);
memset(pixel,0,sizeof(int)*1440*2560);
//int pixel[1440][2560];
glPixelStorei(GL_PACK_ALIGNMENT,1);
printf("---------1-------\n");
glReadPixels(0, 0, 1440, 50,GL_RGBA, GL_UNSIGNED_BYTE,pixel );
dump_picture("simple-egl",pixel,1440,50);
2.dump buffer到本地
void dump_picture(char *name,const void *ptr,int w,inth)
{
int fd= -1;
staticint dumpcnt = 1000;
charfilename[1024];
intp_size = 0;
intret_w = 0;
sprintf(filename, "/tmp/dumpfiles/cts-%s-%d_%dx%d-%d",name,getpid(), w, h, dumpcnt);
fd =open(filename, O_WRONLY|O_CREAT|O_APPEND, 0777);
printf("------%s:[%s] dumpidx=%d, fd=%d,w,h=(%d,%d)\n", name,__func__,dumpcnt, fd,w,h);
p_size= 4 * w * h;
while(ret_w = write(fd,ptr , p_size))
{
if (ret_w == -1)
{
printf("ret_w=-1,error\n");
break;
}
else if (ret_w == p_size)
{
break;
}
else if (ret_w > 0)
{
ptr += ret_w;
p_size -= ret_w;
}
}
close(fd);
dumpcnt++;
}
3.将原始数据转换成BMP图片
BMP文件是一种像素文件,它保存了一幅图象中所有的像素。这种文件格式可以保存单色位图、16色或256色索引模式像素图、24位真彩色图象,每种模式种单一像素的大小分别为1/8字节,1/2字节,1字节和3字节。目前最常见的是256色BMP和24位色BMP。这种文件格式还定义了像素保存的几种方法,包括不压缩、RLE压缩等。常见的BMP文件大多是不压缩的。Windows所使用的BMP文件,在开始处有一个文件头,大小为54字节。保存了包括文件格式标识、颜色数、图象大小、压缩方式等信息。
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int bmp_write(unsigned char *image, int xsize, intysize, char *filename)
{
unsignedchar header[54] = {0x42, 0x4d, 0, 0, 0, 0, 0, 0, 0, 0,
54, 0, 0, 0,40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 32, 0,
0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0
};
longfile_size = (long)xsize * (long)ysize * 4+ 54;
header[2] =(unsigned char)(file_size &0x000000ff);
header[3] = (file_size >> 8) &0x000000ff;
header[4] =(file_size >> 16) & 0x000000ff;
header[5] =(file_size >> 24) & 0x000000ff;
long width =xsize;
header[18] =width & 0x000000ff;
header[19] =(width >> 8) &0x000000ff;
header[20] =(width >> 16) &0x000000ff;
header[21] =(width >> 24) &0x000000ff;
long height= ysize;
header[22] =height &0x000000ff;
header[23] =(height >> 8) &0x000000ff;
header[24] =(height >> 16) &0x000000ff;
header[25] =(height >> 24) &0x000000ff;
charfname_bmp[128];
sprintf(fname_bmp, "%s.bmp", filename);
FILE *fp;
if (!(fp =fopen(fname_bmp, "wb")))
return -1;
fwrite(header, sizeof(unsigned char), 54, fp);
fwrite(image, sizeof(unsigned char), (size_t)(long)xsize * ysize * 4,fp);
fclose(fp);
return 0;
}
int main(int argc, char** argv)
{
printf("\nusage: source filename,width,height,picture name \n");
intbReverse = 1;
int width = atoi(argv[2]);
intheight = atoi(argv[3]);
printf("width:%d height:%d\n",width,height);
#if 1
FILE*fp;
if (!(fp =fopen(argv[1], "rb")))
return -1;
unsignedchar * buff = (unsigned char *)malloc(width*height*4);
memset(buff,0,width*height*4);
size_tcount = fread(buff,width*height*4,1,fp);
if(bReverse)
{
unsigned char * tmp = (unsigned char *)malloc(width*height*4);
memset(tmp,0,width*height*4);
int i=0;
for(;i<height;++i)
{
memcpy(tmp+(height-1-i)*width*4,buff+width*i*4,width*4);
}
bmp_write(tmp,width,height,argv[4]);
free(tmp);
}
else
bmp_write(buff,width,height,argv[4]);
fclose(fp);
free(buff);
#endif
}
用法:../rawToBmp32bppclient-11217_250x250-1010 250 250 cl1