[英]Saving a QImage from a memory buffer
这基本上是我在做什么:
我有一个视频流(YUV格式)。 每个帧都提取到缓冲区( frameBytes
)中。 以后,此缓冲区用于执行YUV-> RGB转换,然后在IplImage
中进行IplImage
。 然后将IplImage
传输到cv::Mat
并显示在OpenGL上下文中。 一切正常。
我想做的是绕过IplImage
和cv::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.