OpenGL调试时输出显存帧到图片的一些方法

1. 从帧缓存读取像素
bool GLUtils::saveRender(const std::string& tag,int w, int h,const char* func_name, int line){
    std::vector<uint32_t> outputValues(w* h, 0);
    glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, &outputValues[0]);
    return savePicture(tag,w, h,outputValues.data(),std::string(func_name),line);
}
2.从EGLImageKHR 转到纹理
bool GLUtils::saveEGLImage(EGLImageKHR eglImage,const std::string& tag,int w, int h,const char* func_name, int line){
    GLuint tmpTex=GLUtils::createTexture(w, h,(uint32_t)0x00000000);
    glBindTexture(GL_TEXTURE_2D, tmpTex);
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage);
    glBindTexture(GL_TEXTURE_2D, 0);
    auto re =GLUtils::saveTexture(tmpTex,tag, w,  h, func_name,  line);
    glDeleteTextures(1, &tmpTex);
    return re;
}
3.内存的像素保存到文件或图片
//保存为png
bool GLUtils::savePicture(const std::string& tag,int m_width, int m_height,void *m_pixelData,std::string func_name, int line,bool isSaveAsPng){

        char pngPath[200];
        int64_t eventTime = std::chrono::steady_clock::now().time_since_epoch().count();
    //    eventTime=1;
        char save_path[] = DEBUG_PIC_SAVE_PATH;
        if (::access(save_path, F_OK) == -1){
            mkdir(save_path, S_IRWXU);		
        }
        LOGD("access file: exist \"%d\", read \"%d\", write \"%d\"", ::access(save_path, F_OK), ::access(save_path, R_OK), ::access(save_path, W_OK));
        std::string suffix = ".png";
        if(!isSaveAsPng){
            suffix = ".raw";
        }
        sprintf(pngPath, "%s%lld-%s-%s-%d%s",save_path, eventTime,func_name.c_str(), tag.c_str(), line,suffix.c_str());
        if(isSaveAsPng){
            return save(std::string(pngPath), m_width, m_height,m_pixelData, "png");
        }else{
            return saveRGBARaw(std::string(pngPath), m_width, m_height,m_pixelData);
        }
    }
//直接保存图片裸数据,性能较快
    bool GLUtils::saveRGBARaw(const std::string& fileName,int width, int height,void *m_pixelData)
    {
        uint32_t buffer_size = width * height * sizeof(int32_t);
        int dumpFd = open(fileName.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
        if(dumpFd >= 0) {
            write(dumpFd, m_pixelData, buffer_size);
            close(dumpFd);
            return false;
        }
        return true;
    }

    bool GLUtils::save(const std::string& fileName,int m_width, int m_height,void *m_pixelData, const std::string& fileFormat)
    {
        bool ret = false;
        if (m_height > 0 && m_width > 0)
        {
            if (fileFormat == "png")
            {
                ret = stbi_write_png(fileName.c_str(), m_width, m_height, c_bytesPixel[PF_RGBA8], m_pixelData, m_width*c_bytesPixel[PF_RGBA8]);
            }
            if (fileFormat == "jpg")
            {
                ret = stbi_write_jpg(fileName.c_str(), m_width, m_height, c_bytesPixel[PF_RGBA8], m_pixelData,95);
            }
        }
        return ret;
    }
4.从纹理读取
bool GLUtils::saveTexture(GLuint tex,const std::string& tag,int w, int h,const char* func_name, int line){
    uint32_t *buf= GLUtils::readPixels(tex,w,h);
    auto re= savePicture(tag,w, h,buf,std::string(func_name),line);
    free(buf);
    return re;
}
uint32_t * GLUtils::readPixels(GLuint tex,int width,int height){
    uint32_t* outbuf=createTmpPictureEmpty(width, height);;
    GLuint fbo;
    glGenFramebuffers(1,&fbo);
    glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
    glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, tex, 0);
    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,outbuf);
    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
    glBindTexture(GL_TEXTURE_2D,0);
    return outbuf;
}
5. GraphicBuffer或ANativeWindowBuffer保存到文件

[[maybe_unused]] static void dumpGraphicRawData2file(const native_handle_t* bufferHandle, 
                                uint32_t width, uint32_t height, 
                                uint32_t stride, int32_t format)
{
    // ALOGE("%s [%d]", __FUNCTION__, __LINE__);

    static int sDumpCount = 0;

    if(bufferHandle != nullptr) {

    //     AHardwareBuffer_lock(aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1, nullptr,
    //                         (void **) &ptrReader);
    // //	memset(ptrReader, 123456 ,screenW*screenH * sizeof(uint32_t));
    //     unsigned int* mysurface=(unsigned int*)ptrReader;

    //     uint32_t buffer_size = stride * height * android::bytesPerPixel(format);
        
    //     char dumpPath[100] = "";
    //     snprintf(dumpPath, sizeof(dumpPath), "/data/dump/buffer_%u_frame_%u_%u_%u.bin", sDumpCount++, width, height, android::bytesPerPixel(format));
    //     int dumpFd = open(dumpPath, O_WRONLY|O_CREAT|O_TRUNC, 0644);
    //     if(dumpFd >= 0 && ptrReader != NULL) {
    //         write(dumpFd, ptrReader, buffer_size);// д���ݵ��ļ�
    //         // ALOGD("liuxurun dump writing buffer");
    //         close(dumpFd);
    //     }
    //     munmap((void*)ptrReader, buffer_size);
    //     int32_t fence = -1;
    //     AHardwareBuffer_unlock(aHardwareBuffer, &fence);


        int shareFd = bufferHandle->data[0];
        unsigned char *srcAddr = NULL;
        uint32_t buffer_size = stride * height * android::bytesPerPixel(format);
        srcAddr = (unsigned char *)mmap(NULL, buffer_size, PROT_READ, MAP_SHARED, shareFd, 0);// ��ȡ���ݵ�ַ

        char dumpPath[100] = "";
        snprintf(dumpPath, sizeof(dumpPath), "/data/dump/buffer_%u_frame_%u_%u_%u.bin", sDumpCount++, width, height, android::bytesPerPixel(format));
        int dumpFd = open(dumpPath, O_WRONLY|O_CREAT|O_TRUNC, 0644);
        if(dumpFd >= 0 && srcAddr != NULL) {
            write(dumpFd, srcAddr, buffer_size);// д���ݵ��ļ�
            // ALOGD("liuxurun dump writing buffer");
            close(dumpFd);
        }
        munmap((void*)srcAddr, buffer_size);
    }
}
    
auto graphicBuffer = android::GraphicBuffer::from((ANativeWindowBuffer *)output.data);
uint32_t width = graphicBuffer->getWidth();
uint32_t height = graphicBuffer->getHeight();
uint32_t stride = graphicBuffer->getStride();
int32_t format = graphicBuffer->getPixelFormat();
dumpGraphicRawData2file(graphicBuffer->getNativeBuffer()->handle, width, height, stride, format);
            
python批量将RGBA8888裸数据保存到png
"""
# pip install opencv-python
pip install Pillow
"""

import os,re
import shutil
from PIL import Image

# import cv2 as cv

import numpy as np

src=[
    'D:\Out\libxrengine_gtest\dump',
     ]

target_dir=os.path.join('D:\Out\libxrengine_gtest\generated')
files_hz='.png'
patternz = re.compile(r'\.bin$')	#


def mkdir(dir):
    if not os.path.exists(dir):
        os.makedirs(dir,exist_ok=True)

def getDirname(pathN):
    return os.path.dirname(pathN)

def getName(pathN):
    return pathN[len(getDirname(pathN))+1:]

ffmpeg_exe = 'D:/software/ffmpeg-6.0-essentials_build/bin/ffmpeg.exe'

def convert(from_file,to_file):
    cmd=ffmpeg_exe+' -s 640x480 -pix_fmt yuv444p10le -i ' + from_file + ' -f image2 -pix_fmt rgba32 ' + to_file
    print(cmd)
    os.system(cmd)

def comvert2(from_file,to_file): #RGBA保存
    with open(from_file, 'rb') as raw:  
        rawData = raw.read()
        width = 640
        height = 480
        image = Image.new('RGBA', (width, height))
        buf = np.frombuffer(rawData, dtype=np.uint8 )
        buf.shape = ( height ,width,4)
        img = Image.fromarray(buf)
        img.save(to_file)

def doForFile(srcFile,dstFile):
    matchz = patternz.search(srcFile)
    if matchz:
        comvert2(srcFile,dstFile+files_hz)
        # print(srcFile,dstFile+files_hz)
    # else:  
    #     shutil.copyfile(srcFile,dstFile)

def traverse(src_path,target_path,base_src_path):
    for parent,dirs,files in os.walk(src_path):
        for filename in files:
            srcFile=os.path.join(parent , filename)
            dstFile=target_path+srcFile[len(base_src_path):]
            dstPath=getDirname(dstFile)
            mkdir(dstPath)
            doForFile(srcFile,dstFile)
        for dir_in in dirs:
            traverse(dir_in,target_path,base_src_path)

def traverseDir(src_path,target_path):
    new_target_path = os.path.join(target_path,getName(src_path))
    print(new_target_path)
    traverse(src_path,new_target_path,src_path)

def start():
    for src_p in src:
        traverseDir(os.path.join(src_p),target_dir)

start()
print('finish')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值