我正在编写DX9渲染器,目前正在播放AVI电影文件。我已经能够使用AVIStreamGetFrame()
检索任何指定的帧,该帧返回打包的DIB,然后从那里我希望能够将位图数据复制到已经存在的IDirect3DTexture9 *
中。
我的问题是缺乏对位图文件格式的了解,并且不知道如何将BITMAPINFOHEADER
提供的像素数据转换为IDirect3DTexture9
可以解释的格式。
我首先创建这样的DX9纹理:
LPBITMAPINFO bmpInfo = m_pVideoData->GetVideoFormat();
D3DXCreateTexture(LtGEngine::GetInstance()->GetDevice(),
bmpInfo->bmiHeader.biWidth,
bmpInfo->bmiHeader.biHeight,
D3DX_DEFAULT,
0,
D3DFMT_A8R8G8B8, // <- DETERMINE HOW?
D3DPOOL_MANAGED, // <- OR D3DPOOL_SYSTEMMEM?
&m_pD3DTexture);
我在这里提出的问题已列为以上评论。当我得到BITMAPINFO时,例如读取bmpInfo.bmiHeader.biBitCount = 8(或16,等等),这是否意味着我需要相应地更改D3DFMT_ *?
稍后,当我获得要渲染的帧的
LPBITMAPINFOHEADER
时,我就不知道如何处理pBits
函数返回的IDirect3DTexture9::LockRect()
了。这是我到目前为止的内容:// Retrieve a frame from the video data as a BITMAPINFOHEADER
LPBITMAPINFOHEADER pBmpInfoHeader;
m_pVideoData->GetVideoFrame(0, 0, &pBmpInfoHeader);
D3DLOCKED_RECT rect;
if(FAILED(m_pD3DTexture->LockRect(0, &rect, NULL, 0)))
{
m_pD3DTexture->UnlockRect(0);
}
DWORD* pDest = (DWORD*)rect.pBits;
// Now what to copy from pBmpInfoHeader?
有没有为我做过的API调用,我从未见过?还是有谁知道比这更简单的方法?感谢您的阅读/帮助。
最佳答案
得到它的工作!
几个注意事项。我的AVI文件(在这种情况下为单帧/位图)为16位格式,因此必须使用D3DFMT_X1R5G5B5创建目标纹理。另外,位图是倒置存储的,因此我不得不反转指针并向后读取每一行。
这是代码:
// Retrieve a frame from the video data as a BITMAPINFOHEADER
LPBITMAPINFOHEADER pBmpInfoHeader;
m_pVideoData->GetVideoFrame(0, 0, &pBmpInfoHeader);
// Get dimentions
long nWidth = pBmpInfoHeader->biWidth;
long nHeight = pBmpInfoHeader->biHeight;
// Bitmap width correction (might not be needed...)
if (nWidth % 4 != 0)
nWidth = nWidth + (4 - nWidth%4);
// Get Pixel data (should be after the header in memory)
WORD bitCount = pBmpInfoHeader->biBitCount;
DWORD size = nWidth * nHeight * bitCount/8;
BYTE *pPixelSrc = (BYTE *)pBmpInfoHeader + sizeof(pBmpInfoHeader);
// Lock the texture so we can write this frame's texel data
D3DLOCKED_RECT lock;
if(FAILED(m_pD3DTexture->LockRect(0, &lock, NULL, 0)))
{
m_pD3DTexture->UnlockRect(0);
return;
}
int iNumBytesPerRowSrc = pBmpInfoHeader->biWidth * (pBmpInfoHeader->biBitCount/8);
int iNumBytesPerRowDst = lock.Pitch;
int iNumBytesToCopyPerRow = min(iNumBytesPerRowSrc, iNumBytesPerRowDst);
// Bitmap data is stored upside down
// Start at the end and work backwards
pPixelSrc += (iNumBytesPerRowSrc * nHeight);
// Store a pointer to the texture pixel data and write new data
BYTE* ucTexDst = (BYTE *)lock.pBits;
for(int y = 0; y < nHeight; ++y)
{
pPixelSrc -= iNumBytesPerRowSrc;
memcpy(ucTexDst, pPixelSrc, iNumBytesToCopyPerRow);
ucTexDst += iNumBytesPerRowDst;
}
// Unlock texture so gfx card can resume its business
m_pD3DTexture->UnlockRect(0);