BGRA在内存上的排列按B、G、R、A依次排列,32表示每个通道占1个字节8bits,一个像素占4个字节32bits
RBGA在内存上的排列按R、B、G、A依次排列
YUV420在内存上的排列为,先是全部Y,然后是全部U,最后是全部V
只需遍历一遍,把每4个字节的第一位和第三位互换即可
void ConvertBGRAtoRGBA(BYTE* data, int width, int height)
{
for (int i = 0; i < width * height * 4; i += 4) {
BYTE temp = data[i];
data[i] = data[i + 2];
data[i + 2] = temp;
}
}
按照上图YUV420的存储格式,蓝色部分4个Y、1个U、1个V可以转换出4个像素的RBGA格式。
void I420ToRGBA(const uint8_t* src_y, const uint8_t* src_u, const uint8_t* src_v, uint8_t* dst_rgba, int width, int height)
{
// 计算公式
//R = Y + 1.13983 * V
//G = Y - 0.39465 * U - 0.58060 * V
//B = Y + 2.03211 * U
const int src_y_stride = width;
const int src_u_stride = (width + 1) / 2;
const int src_v_stride = (width + 1) / 2;
const int dst_rgba_stride = width * 4;
for (int y = 0; y < height; ++y) {
const uint8_t* src_y_row = src_y + y * src_y_stride;
const uint8_t* src_u_row = src_u + (y / 2) * src_u_stride;
const uint8_t* src_v_row = src_v + (y / 2) * src_v_stride;
uint8_t* dst_rgba_row = dst_rgba + y * dst_rgba_stride;
for (int x = 0; x < width; ++x) {
const int src_y_val = src_y_row[x];
const int src_u_val = src_u_row[x / 2];
const int src_v_val = src_v_row[x / 2];
const int c_val = src_y_val - 16;
const int d_val = src_u_val - 128;
const int e_val = src_v_val - 128;
const int r_val = (298 * c_val + 409 * e_val + 128) >> 8;
const int g_val = (298 * c_val - 100 * d_val - 208 * e_val + 128) >> 8;
const int b_val = (298 * c_val + 516 * d_val + 128) >> 8;
dst_rgba_row[x * 4 + 0] = static_cast<uint8_t>(max(0, min(255, r_val)));
dst_rgba_row[x * 4 + 1] = static_cast<uint8_t>(max(0, min(255, g_val)));
dst_rgba_row[x * 4 + 2] = static_cast<uint8_t>(max(0, min(255, b_val)));
dst_rgba_row[x * 4 + 3] = 255;
}
}
}
这里用Windows GDI的方式把图片直接绘制在窗口上 CBitmap用的是BGRA格式的数据,显示I420的话,把格式转换一下再组装为CBitmap即可。
void CPicViewerDlg::DrawBitmap(CWnd *pWnd, int x, int y, int w, int h, unsigned char *pData)
{
CBitmap bitmap;
CDC MemDc;
bitmap.CreateBitmap(w, h, 1, 32, pData);
CDC *pWndDc = pWnd->GetDC();
MemDc.CreateCompatibleDC(pWndDc);
CBitmap *pOldBitmap = MemDc.SelectObject(&bitmap);
pWndDc->BitBlt(x, y, w, h, &MemDc, 0, 0, SRCCOPY);
MemDc.SelectObject(pOldBitmap);
pWnd->ReleaseDC(pWndDc);
pWndDc = NULL;
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。