簡體   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