繁体   English   中英

从内存缓冲区保存QImage

[英]Saving a QImage from a memory buffer

这基本上是我在做什么:

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

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

这种解释仅是针对上下文,因为我遇到的问题比较简单。

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

这是我这部分的代码:

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进行frameBytes > RGB转换。

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;
    }


}

修正错误

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

unsigned char *mycopy = new unsigned char[1920*1080*3];
memcpy(mycopy, frameBytes, sizeof(1920*1080*3));

那里的sizeof意味着您只复制一个int大小的块,而不是6MB。 看起来是由于使用静态数组导致的意外保留? 替换为

const size_t bufsize = 1920*1080*3;
auto *mycopy = new unsigned char[bufsize];
memcpy(mycopy, frameBytes, bufsize);

更简单的方法

另外,您可以复制映像,而不是自己进行内存分配(并在QImage销毁后负责delete[]对其进行分配):

const unsigned char *bytes = frameBytes;
QImage img = QImage(bytes, 1920, 1080, QImage::Format_RGB888).copy();

这种工作方式是,我们使用frameBytes作为其源创建一个临时QImage (我们将其作为指向const指针传递,以使其坚持为只读)。 然后,我们将整个过程都copy()到新的QImage ,丢弃临时图像。 copy()功能与您上面的代码类似,但是现在不必进行计算了,从而避免了随之而来的潜在错误。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM