天天看點

Qt QImage加載記憶體資料後繪制

如果我在記憶體中生成了一個包含RGBA各分量的顔色二維數組ColorArray,要怎樣通過QImage把這些資料顯示出來呢?

①QImage需要加載這些資料

//1、 通過QImage的構造函數 
QImage(const uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = Q_NULLPTR,
             void *cleanupInfo = Q_NULLPTR);
//其中data是指向顔色資料(32bit)的指針,width表示一行有多少個像素,height表示一列有多少個像素,format表示圖像格式(QImage
//提供了多種格式)。QImage在析構時并不會删除data。如果提供了cleanupFunction和cleanupInfo,那麼當QImage的圖像資料不再被使用時,
//會調用cleanupFunction清除cleanupInfo所指向的記憶體。

//通過靜态函數 QImage::fromData  還沒嘗試過
           

②記憶體中ColorArray的格式需要和QImage的資料格式一緻。

存在QImage中的每一個像素都是以整型integer來表示的。這個integer的size以及每個byte的意義,與QImage的格式有關 。QImage支援的顔色資料格式有很多種,比如QImage::Format_RGB16、QImage::Format_RGBA8888、QImage::Format_ARGB32等等。

兩種格式的不同

格式類型 不同點 
QImage::Format_ARGB32 32bit的ARGB,按32bit整型去通路,始終是0xAARRGGBB。如果按位元組來讀取(也就是存儲方式相關),在不同的系統上,讀取的順序不同。如果在大端big_endian架構上,按位元組會被讀取為0xAA、0xRR、0xGG、0xBB;在小端little_endian架構上,按位元組會被讀取為0xBB、0xGG、0xRR、0xAA。  可以記作,Byte存儲方式順序不定,4-Byte讀取的數值固定。
QImage::Format_RGBA8888 每一個32bit中,RGBA各分量的順序是有序的。如果按位元組來讀取,那麼會依次讀取位元組0xRR、0xGG、0xBB、0xAA。那麼,在大端big_endian上,這個32bits會被表示為0xRRGGBBAA,在小端little_endian上,會被表示為0xAABBGGRR。    可以記作,Byte存儲方式順序固定,4-Byte讀取的數值不定。

從上面的表格中可以看出,對于一塊ColorArray,如果用不同的QImage::Fromat,可能會産生不同的圖像。

我們的問題是,如果用這塊buffer,直接套用QImage(ColorArray,width,height, format)的構造函數,如何生成一個QImage::Format_RGBA8888的QImage?

在大端big_endian結構上,QImage::Format_RGBA8888對應的byte順序是 0xRR、0xGG、0xBB、0xAA,是以我們在buffer中指派時,應依給每個Byte位元組幅值RR、GG、BB、AA。或者使用如下結構體直接給32bits指派。

typedef struct
{
    U8 red;
    U8 green;
    U8 blue;
    U8 alpha;
} Color;

/*
注意,使用這種結構計算出RGBA的各分量後,形成了一塊顯示記憶體區域ColorArray.
對于這塊ColorArray, QImage是直接以int*指針來通路的。通常情況下,這沒有問題。
但是,如果還要對基于這塊ColorArray的QImage進行一次縮放(QImage::scales(...)),則容易出現問題。
因為,進行一次縮放,涉及對ColorArray的周遊,會用int*的指針進行通路,但是,由于ColorArray是用
Color對象構造的,ColorArray并不一定存放在與int對齊的位址上,是以,用int*指針通路會導緻“段錯誤”。

那麼,如何避免這種情況呢?有這麼2個思路:
1.将ColorArray拷貝到一個int類型的數組上ColorArrayInt,QImage用ColorArrayInt構造
2.typedef union{Color color; int colorInt}ColorUnion;通過構造聯合體,確定Color是與int類型對齊的。


無論對于大端還是小端系統,無論是棧上還是堆上,Color::red的位址都小于Color::alpha;相應的,int32 temp[4]中,
temp[0]的位址小于temp[4]的位址。
但是,在大端系統中,int32類型變量的第一個byte對應高8位資料,int32類型變量的地4個位元組,對應低8未資料;
在小端系統中,int32類型變量的第一個byte,對應低8位資料,int32類型變量的地4個位元組,對應高8未資料。  
大端和小端的概念,僅在于變量類型内部如何安排byte,但是變量和變量之間,還是按照通常的順序排布。
*/
           

附件:

QImage::Format清單(待更新....)

如有不足,歡迎拍磚。如需轉載,請注明來源。

Qt

繼續閱讀