首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从内存缓冲区中保存QImage

从内存缓冲区中保存QImage
EN

Stack Overflow用户
提问于 2016-08-04 10:34:43
回答 1查看 1.7K关注 0票数 0

以下是我所做的基本工作:

我有一个视频流(YUV格式)。每个帧被提取到一个缓冲器(frameBytes)中。稍后,此缓冲区用于执行YUV>RGB转换,然后在IplImage中传输。然后将IplImage转换为cv::Mat,并在OpenGL上下文中显示。一切都很好。

我想要做的是绕过IplImagecv::Mat部分,直接使用OpenGL中的frameBytes缓冲区,并在着色器中进行转换。

这个解释只是为了上下文,因为我遇到的问题更简单。

为了查看是否能够更早地使用缓冲区,我尝试使用memcpy复制它,然后将其保存在QImage中然后保存在文件中。

这里是我这部分的代码:

代码语言:javascript
运行
复制
unsigned char *mycopy = new unsigned char[1920*1080*3];
memcpy(mycopy, frameBytes, sizeof(1920*1080*3));
QImage *img = new QImage(mycopy, 1920, 1080, QImage::Format_RGB888);
img->save("image.jpg",0,-1);

frameBytes包含来自视频流的YUV数据。我知道这是YUV,我正在尝试用RGB888格式创建一个QImage,但是由于QImage不支持这种格式,我没有在那里进行转换,我认为它仍然可以保存一个图像,但是使用错误的颜色,所以我不关心现在(也许这个假设是错误的?)

问题是,保存的图像是黑色的。

为了获得更多信息,这里有一个示例,其中我使用frameBytes进行YUV->RGB转换。

代码语言:javascript
运行
复制
void DeckLinkCaptureDelegate::convertFrameToOpenCV(void* frameBytes, IplImage * m_RGB){
    if(!m_RGB)  m_RGB = cvCreateImage(cvSize(1920, 1080), IPL_DEPTH_8U, 3);


    unsigned char* pData = (unsigned char *) frameBytes;


    for(int i = 0, j=0; i < 1920 * 1080 * 3; i+=6, j+=4)
    {

        unsigned char u = pData[j];
        unsigned char y = pData[j+1];
        unsigned char v = pData[j+2];

        //fprintf(stderr, "%d\n", v);
        m_RGB->imageData[i+2] = 1.0*y + 8 + 1.402*(v-128);               // r
        m_RGB->imageData[i+1] = 1.0*y - 0.34413*(u-128) - 0.71414*(v-128);   // g
        m_RGB->imageData[i] = 1.0*y + 1.772*(u-128) + 0;                            // b

        y = pData[j+3];
        m_RGB->imageData[i+5] = 1.0*y + 8 + 1.402*(v-128);               // r
        m_RGB->imageData[i+4] = 1.0*y - 0.34413*(u-128) - 0.71414*(v-128);   // g
        m_RGB->imageData[i+3] = 1.0*y + 1.772*(u-128) + 0;
    }


}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-08-04 17:31:27

修复错误

没有将所有数据复制到新缓冲区:

代码语言:javascript
运行
复制
unsigned char *mycopy = new unsigned char[1920*1080*3];
memcpy(mycopy, frameBytes, sizeof(1920*1080*3));

其中的sizeof意味着您只是在复制一个int-sized块,而不是6MB。它看起来像是一个使用静态数组的意外持久器?代之以

代码语言:javascript
运行
复制
const size_t bufsize = 1920*1080*3;
auto *mycopy = new unsigned char[bufsize];
memcpy(mycopy, frameBytes, bufsize);

更简单的方法

或者,与其自己进行内存分配(并在销毁delete[]之后负责QImage ),不如复制映像:

代码语言:javascript
运行
复制
const unsigned char *bytes = frameBytes;
QImage img = QImage(bytes, 1920, 1080, QImage::Format_RGB888).copy();

其工作方式是使用QImage作为其源创建一个临时的frameBytes (我们将它作为指向const的指针传递,以坚持它是只读的)。然后,我们将整个copy()转换为一个新的QImage,丢弃临时的内容。copy()执行类似于上面的代码的操作,但是我们现在不必进行计算,从而消除了一些可能出现错误的情况。

还请注意,我更喜欢按值传递QImage。虽然这可能看起来效率低下,但大多数(可复制的) Qt类型都设计为引用计数的随写复制结构,并且可以安全地以这种方式使用,从而消除了另一类错误(内存管理)。Qt的集合类型也是如此,非常有用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38764966

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档