BOOL
CMxDDraw::RGB24_to_RGB32(BYTE * pRGB24, DWORD dwRGB24Len, PBYTE & pRGB32, DWORD & dwRGB32Len)
{
ASSERT(pRGB24);
ASSERT(!pRGB32);
dwRGB32Len = ((m_nPosWidth * CLR_32BIT + 7) / 8) * m_nPosHeigh;
pRGB32 = new BYTE [dwRGB32Len];
if (pRGB32)
{
//Step through the 32bit buffer, copying the 3 Channels from
//the 24bit buffer. However, at the end of each channel, we
//have to write an extra byte for the 32bit image's alpha
//channel
ZeroMemory(pRGB32, dwRGB32Len);
for (DWORD i = 0, j = 0; i < dwRGB32Len; i += 4, j += 3)
{
memcpy(&pRGB32[i], &pRGB24[j], 3);
}
return TRUE;
}
return FALSE;
}
void
CMxDDraw::DrawYUV420(BYTE * pYUVData, DWORD stride,BOOL is_interlaced)
{
DDSURFACEDESC ddsd;
LPBYTE lpY = pYUVData;
LPBYTE lpU = pYUVData + 1;
LPBYTE lpV = pYUVData + 2;
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsd.dwWidth = m_nPosWidth;
ddsd.dwHeight = m_nPosHeigh;
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC | DDPF_YUV;
ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('U','Y','V','Y');
ddsd.ddpfPixelFormat.dwYUVBitCount = 16;
if (!CreateOffScrrenSurface(&ddsd))
{
return;
}
if(m_lpDDSOffScr->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL) != DD_OK)
{
return;
}
LPBYTE lpSurf = (LPBYTE)ddsd.lpSurface;
//Fill Off-screen surface
if(lpSurf)
{
DWORD i = 0;
DWORD j = 0;
for(i = 0; i < ddsd.dwHeight && is_interlaced; i += 2)
{
lpSurf += i * ddsd.lPitch;
for (j = 0; j < ddsd.dwWidth; j += 2)
{
*lpSurf++ = *lpU++; //U
*lpSurf++ = *lpY++; //Y
*lpSurf++ = *lpV++; //V
*lpSurf++ = *lpY++; //Y
}
if (stride > ddsd.dwWidth)
{
lpU += (stride - ddsd.dwWidth) / 2;
lpV += (stride - ddsd.dwWidth) / 2;
lpY += (stride - ddsd.dwWidth);
}
if (i % 4 == 0)
{
lpU -= stride / 2;
lpV -= stride / 2;
}
}
for(i = 1; i < ddsd.dwHeight && is_interlaced; i += 2)
{
lpSurf += i * ddsd.lPitch;
for (j = 0; j < ddsd.dwWidth; j += 2)
{
*lpSurf++ = *lpU++; //U
*lpSurf++ = *lpY++; //Y
*lpSurf++ = *lpV++; //V
*lpSurf++ = *lpY++; //Y
}
if (stride > ddsd.dwWidth)
{
lpU += (stride - ddsd.dwWidth) / 2;
lpV += (stride - ddsd.dwWidth) / 2;
lpY += (stride - ddsd.dwWidth);
}
if ((i - 1) % 4 == 0)
{
lpU -= stride / 2;
lpV -= stride / 2;
}
}
for(i = 0; i < ddsd.dwHeight && !is_interlaced; i += 2)
{
lpSurf += i * ddsd.lPitch;
for (j = 0; j < ddsd.dwWidth; j += 2)
{
*lpSurf++ = *lpU++; //U
*lpSurf++ = *lpY++; //Y
*lpSurf++ = *lpV++; //V
*lpSurf++ = *lpY++; //Y
}
if (stride > ddsd.dwWidth)
{
lpU += (stride - ddsd.dwWidth) / 2;
lpV += (stride - ddsd.dwWidth) / 2;
lpY += (stride - ddsd.dwWidth);
}
if (i % 2 == 0)
{
lpU -= ddsd.lPitch / 2;
lpV -= ddsd.lPitch / 2;
}
}
}
m_lpDDSOffScr->Unlock(NULL);
RecalculateDstRect();
m_lpDDClipper->SetHWnd(0, m_hVideoHWND);
m_lpDDSPrimary->Blt(&m_rcDst, m_lpDDSOffScr, &m_rcSrc, DDBLT_WAIT, NULL);
}
第二个函数实现了从YUV到RGB32的转化。
CMxDDraw::RGB24_to_RGB32(BYTE * pRGB24, DWORD dwRGB24Len, PBYTE & pRGB32, DWORD & dwRGB32Len)
{
ASSERT(pRGB24);
ASSERT(!pRGB32);
dwRGB32Len = ((m_nPosWidth * CLR_32BIT + 7) / 8) * m_nPosHeigh;
pRGB32 = new BYTE [dwRGB32Len];
if (pRGB32)
{
//Step through the 32bit buffer, copying the 3 Channels from
//the 24bit buffer. However, at the end of each channel, we
//have to write an extra byte for the 32bit image's alpha
//channel
ZeroMemory(pRGB32, dwRGB32Len);
for (DWORD i = 0, j = 0; i < dwRGB32Len; i += 4, j += 3)
{
memcpy(&pRGB32[i], &pRGB24[j], 3);
}
return TRUE;
}
return FALSE;
}
void
CMxDDraw::DrawYUV420(BYTE * pYUVData, DWORD stride,BOOL is_interlaced)
{
DDSURFACEDESC ddsd;
LPBYTE lpY = pYUVData;
LPBYTE lpU = pYUVData + 1;
LPBYTE lpV = pYUVData + 2;
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsd.dwWidth = m_nPosWidth;
ddsd.dwHeight = m_nPosHeigh;
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC | DDPF_YUV;
ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('U','Y','V','Y');
ddsd.ddpfPixelFormat.dwYUVBitCount = 16;
if (!CreateOffScrrenSurface(&ddsd))
{
return;
}
if(m_lpDDSOffScr->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL) != DD_OK)
{
return;
}
LPBYTE lpSurf = (LPBYTE)ddsd.lpSurface;
//Fill Off-screen surface
if(lpSurf)
{
DWORD i = 0;
DWORD j = 0;
for(i = 0; i < ddsd.dwHeight && is_interlaced; i += 2)
{
lpSurf += i * ddsd.lPitch;
for (j = 0; j < ddsd.dwWidth; j += 2)
{
*lpSurf++ = *lpU++; //U
*lpSurf++ = *lpY++; //Y
*lpSurf++ = *lpV++; //V
*lpSurf++ = *lpY++; //Y
}
if (stride > ddsd.dwWidth)
{
lpU += (stride - ddsd.dwWidth) / 2;
lpV += (stride - ddsd.dwWidth) / 2;
lpY += (stride - ddsd.dwWidth);
}
if (i % 4 == 0)
{
lpU -= stride / 2;
lpV -= stride / 2;
}
}
for(i = 1; i < ddsd.dwHeight && is_interlaced; i += 2)
{
lpSurf += i * ddsd.lPitch;
for (j = 0; j < ddsd.dwWidth; j += 2)
{
*lpSurf++ = *lpU++; //U
*lpSurf++ = *lpY++; //Y
*lpSurf++ = *lpV++; //V
*lpSurf++ = *lpY++; //Y
}
if (stride > ddsd.dwWidth)
{
lpU += (stride - ddsd.dwWidth) / 2;
lpV += (stride - ddsd.dwWidth) / 2;
lpY += (stride - ddsd.dwWidth);
}
if ((i - 1) % 4 == 0)
{
lpU -= stride / 2;
lpV -= stride / 2;
}
}
for(i = 0; i < ddsd.dwHeight && !is_interlaced; i += 2)
{
lpSurf += i * ddsd.lPitch;
for (j = 0; j < ddsd.dwWidth; j += 2)
{
*lpSurf++ = *lpU++; //U
*lpSurf++ = *lpY++; //Y
*lpSurf++ = *lpV++; //V
*lpSurf++ = *lpY++; //Y
}
if (stride > ddsd.dwWidth)
{
lpU += (stride - ddsd.dwWidth) / 2;
lpV += (stride - ddsd.dwWidth) / 2;
lpY += (stride - ddsd.dwWidth);
}
if (i % 2 == 0)
{
lpU -= ddsd.lPitch / 2;
lpV -= ddsd.lPitch / 2;
}
}
}
m_lpDDSOffScr->Unlock(NULL);
RecalculateDstRect();
m_lpDDClipper->SetHWnd(0, m_hVideoHWND);
m_lpDDSPrimary->Blt(&m_rcDst, m_lpDDSOffScr, &m_rcSrc, DDBLT_WAIT, NULL);
}
第二个函数实现了从YUV到RGB32的转化。