关于DDS的DXT1和 DXT3的解码
关于DDS的DXT1和 DXT3的解码, 有两个问题。
第一个问题:它们解码速度怎么样,能实时解码?
第二个问题:谁有相应的解码程序,给发一份?
初次接触DDS格式,请大家多帮忙,谢谢了。
[解决办法]
没做过。
google找找资料。英文习惯就好啊,英文资料多点。
[解决办法]
我给你实际源码吧,该源码是从Microsoft DirectX SDK (March 2009)的DirectX Texture Tool示例程序中提取出来的,详细源码,请参考该示例。
// DDSBase.h//// This header defines constants and structures that are useful when parsing // DDS files. DDS files were originally designed to use several structures// and constants that are native to DirectDraw and are defined in ddraw.h,// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar // (compatible) constants and structures so that one can use DDS files // without needing to include ddraw.h.#ifndef _DDSBASE_H_#define _DDSBASE_H_struct DDS_PIXELFORMAT{ DWORD dwSize; DWORD dwFlags; DWORD dwFourCC; DWORD dwRGBBitCount; DWORD dwRBitMask; DWORD dwGBitMask; DWORD dwBBitMask; DWORD dwABitMask;};#define DDS_FOURCC 0x00000004 // DDPF_FOURCC#define DDS_RGB 0x00000040 // DDPF_RGB#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELSconst DDS_PIXELFORMAT DDSPF_DXT1 = { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 };const DDS_PIXELFORMAT DDSPF_DXT2 = { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 };const DDS_PIXELFORMAT DDSPF_DXT3 = { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 };const DDS_PIXELFORMAT DDSPF_DXT4 = { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 };const DDS_PIXELFORMAT DDSPF_DXT5 = { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 };const DDS_PIXELFORMAT DDSPF_A8R8G8B8 = { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };const DDS_PIXELFORMAT DDSPF_A1R5G5B5 = { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 };const DDS_PIXELFORMAT DDSPF_A4R4G4B4 = { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 };const DDS_PIXELFORMAT DDSPF_R8G8B8 = { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 };const DDS_PIXELFORMAT DDSPF_R5G6B5 = { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 };#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT #define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ )#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUMEstruct DDS_HEADER{ DWORD dwSize; DWORD dwHeaderFlags; DWORD dwHeight; DWORD dwWidth; DWORD dwPitchOrLinearSize; DWORD dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwHeaderFlags DWORD dwMipMapCount; DWORD dwReserved1[11]; DDS_PIXELFORMAT ddspf; DWORD dwSurfaceFlags; DWORD dwCubemapFlags; DWORD dwReserved2[3];};#endif//-------------------------------------//§ File: DDSConvert.h//§ Desc: CDDSConvert dds格式转换//§ //§ Date: 2011/6/6//§ Copyright(c) xychzh//-------------------------------------#ifndef _DDSCONVERT_H_#define _DDSCONVERT_H_#include "DDSBase.h"class CDDSConvert{public: CDDSConvert(IDirect3DDevice9* pD3DDevice); ~CDDSConvert();public: void ConvertDDS(const char* szSrcFile, const char* szDstFile, D3DFORMAT dstFormat); void ConvertDDS(IDirect3DTexture9* pSrcTexture, IDirect3DTexture9** ppDstTexture, D3DFORMAT dstFormat); BOOL OpenFile(LPCTSTR lpszPathName); HRESULT Compress(IDirect3DTexture9* pSrc, IDirect3DTexture9** ppDst, D3DFORMAT fmtTo); HRESULT ChangeFormat(LPDIRECT3DBASETEXTURE9 ptexCur, D3DFORMAT fmtTo, LPDIRECT3DBASETEXTURE9* pptexNew); HRESULT BltAllLevels(D3DCUBEMAP_FACES FaceType, LPDIRECT3DBASETEXTURE9 ptexSrc, LPDIRECT3DBASETEXTURE9 ptexDest); bool IsVolumeMap() { return m_dwDepth > 0; }// BOOL IsCubeMap(VOID) { return (m_dwCubeMapFlags > 0); }private: IDirect3DDevice9* m_pD3DDevice; // D3D设备对象private: LPDIRECT3DBASETEXTURE9 m_ptexOrig; LPDIRECT3DBASETEXTURE9 m_ptexNew; DWORD m_dwWidth; DWORD m_dwHeight; DWORD m_dwDepth; int m_numMips; D3DFORMAT m_CurFormat;};#endif
[解决办法]
// ------------------------------------//§ File: DDSConvert.cpp//§ Desc: CDDSConvert dds格式转换//§ //§ Date: 2011/6/6//§ Copyright(c) xychzh// ------------------------------------#include "StdAfx.h"#include "DDSConvert.h"#ifndef ReleasePpo#define ReleasePpo(ppo) \ if (*(ppo) != NULL) \ { \ (*(ppo))->Release(); \ *(ppo) = NULL; \ } \ else (VOID)0#endifCDDSConvert::CDDSConvert(IDirect3DDevice9* pD3DDevice){ m_pD3DDevice = pD3DDevice; m_ptexOrig = NULL; m_ptexNew = NULL;}CDDSConvert::~CDDSConvert(){}void CDDSConvert::ConvertDDS(const char* szSrcFile, const char* szDstFile, D3DFORMAT dstFormat){ OpenFile(szSrcFile); IDirect3DTexture9* pSrcTexture = (IDirect3DTexture9*)m_ptexOrig; IDirect3DTexture9* pDstTexture = NULL; Compress(pSrcTexture, &pDstTexture, dstFormat); if( FAILED( D3DXSaveTextureToFile( szDstFile, D3DXIFF_DDS, pDstTexture, NULL ) ) ) { return; } ReleasePpo(&m_ptexOrig); if (pDstTexture != NULL) { pDstTexture->Release(); pDstTexture = NULL; }}void CDDSConvert::ConvertDDS(IDirect3DTexture9* pSrcTexture, IDirect3DTexture9** ppDstTexture, D3DFORMAT dstFormat){ D3DSURFACE_DESC surfaceDesc; pSrcTexture->GetLevelDesc(0, &surfaceDesc); m_CurFormat = surfaceDesc.Format; m_dwWidth = surfaceDesc.Width; m_dwHeight = surfaceDesc.Height; m_dwDepth = 0; m_numMips = 1; Compress(pSrcTexture, ppDstTexture, dstFormat);}BOOL CDDSConvert::OpenFile(LPCTSTR lpszPathName){ LPDIRECT3DDEVICE9 pd3ddev = m_pD3DDevice; D3DXIMAGE_INFO imageinfo; D3DXIMAGE_INFO imageinfo2; if( FAILED( D3DXGetImageInfoFromFile( lpszPathName, &imageinfo ) ) ) { return FALSE; } switch( imageinfo.ResourceType ) { case D3DRTYPE_TEXTURE: if( FAILED( D3DXCreateTextureFromFileEx( pd3ddev, lpszPathName, imageinfo.Width, imageinfo.Height, imageinfo.MipLevels, 0, imageinfo.Format, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, 0, &imageinfo2, NULL, (LPDIRECT3DTEXTURE9*)&m_ptexOrig ) ) ) { return FALSE; } m_dwWidth = imageinfo2.Width; m_dwHeight = imageinfo2.Height; m_dwDepth = 0; m_numMips = imageinfo2.MipLevels; D3DSURFACE_DESC surfaceDesc; ((LPDIRECT3DTEXTURE9)m_ptexOrig)->GetLevelDesc(0, &surfaceDesc); m_CurFormat = surfaceDesc.Format; if( imageinfo.ImageFileFormat == D3DXIFF_BMP ) { // Look for "foo_a.bmp" for alpha channel// CString strPath = lpszPathName;// int i = strPath.ReverseFind('.');// HRESULT hr;// strPath = strPath.Left(i) + "_a.bmp";// CFileStatus status;// if (CFile::GetStatus(strPath, status))// {// // Make sure there's an alpha channel to load alpha image into// if (FAILED(EnsureAlpha(&m_ptexOrig)))// return FALSE;// // LPDIRECT3DSURFACE9 psurf;// // hr = ((LPDIRECT3DTEXTURE9)m_ptexOrig)->GetSurfaceLevel(0, &psurf);// if (FAILED(hr))// return FALSE;// // hr = LoadAlphaIntoSurface(strPath, psurf);// ReleasePpo(&psurf);// if (FAILED(hr))// return FALSE;// } } break; case D3DRTYPE_VOLUMETEXTURE: if( FAILED( D3DXCreateVolumeTextureFromFileEx( pd3ddev, lpszPathName, imageinfo.Width, imageinfo.Height, imageinfo.Depth, imageinfo.MipLevels, 0, imageinfo.Format, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, 0, &imageinfo2, NULL, (LPDIRECT3DVOLUMETEXTURE9*)&m_ptexOrig ) ) ) { return FALSE; } m_dwWidth = imageinfo2.Width; m_dwHeight = imageinfo2.Height; m_dwDepth = imageinfo2.Depth; m_numMips = imageinfo2.MipLevels; break; case D3DRTYPE_CUBETEXTURE: if( FAILED( D3DXCreateCubeTextureFromFileEx( pd3ddev, lpszPathName, imageinfo.Width, imageinfo.MipLevels, 0, imageinfo.Format, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, 0, &imageinfo2, NULL, (LPDIRECT3DCUBETEXTURE9*)&m_ptexOrig ) ) ) { return FALSE; } m_dwWidth = imageinfo2.Width; m_dwHeight = imageinfo2.Height; m_dwDepth = 0; m_numMips = imageinfo2.MipLevels; // m_dwCubeMapFlags = DDS_CUBEMAP_ALLFACES; break; default: return FALSE; } return TRUE;}HRESULT CDDSConvert::Compress(IDirect3DTexture9* pSrc, IDirect3DTexture9** ppDst, D3DFORMAT fmtTo){ HRESULT hr; LPDIRECT3DBASETEXTURE9 ptexNew = NULL; if (FAILED(hr = ChangeFormat(pSrc, fmtTo, (LPDIRECT3DBASETEXTURE9*)ppDst))) return hr; return S_OK;}HRESULT CDDSConvert::ChangeFormat(LPDIRECT3DBASETEXTURE9 ptexCur, D3DFORMAT fmtTo, LPDIRECT3DBASETEXTURE9* pptexNew){ HRESULT hr; LPDIRECT3DDEVICE9 pd3ddev = m_pD3DDevice; LPDIRECT3DTEXTURE9 pmiptex; LPDIRECT3DCUBETEXTURE9 pcubetex; LPDIRECT3DVOLUMETEXTURE9 pvoltex; D3DFORMAT fmtFrom; LPDIRECT3DTEXTURE9 pmiptexNew; LPDIRECT3DCUBETEXTURE9 pcubetexNew; LPDIRECT3DVOLUMETEXTURE9 pvoltexNew; if (IsVolumeMap()) { pvoltex = (LPDIRECT3DVOLUMETEXTURE9)ptexCur; D3DVOLUME_DESC vd; pvoltex->GetLevelDesc(0, &vd); fmtFrom = vd.Format; }// else if (m_dwCubeMapFlags > 0)// {// pcubetex = (LPDIRECT3DCUBETEXTURE9)ptexCur;// D3DSURFACE_DESC sd;// pcubetex->GetLevelDesc(0, &sd);// fmtFrom = sd.Format;// } else { pmiptex = (LPDIRECT3DTEXTURE9)ptexCur; D3DSURFACE_DESC sd; pmiptex->GetLevelDesc(0, &sd); fmtFrom = sd.Format; } if (fmtFrom == D3DFMT_DXT2 || fmtFrom == D3DFMT_DXT4) { if (fmtTo == D3DFMT_DXT1) { // AfxMessageBox(ID_ERROR_PREMULTTODXT1); } else if (fmtTo != D3DFMT_DXT2 && fmtTo != D3DFMT_DXT4) { // AfxMessageBox(ID_ERROR_PREMULTALPHA); return S_OK; } } if (IsVolumeMap()) { hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, m_dwDepth, m_numMips, 0, fmtTo, D3DPOOL_SYSTEMMEM, &pvoltexNew, NULL); if (FAILED(hr)) return hr; *pptexNew = pvoltexNew; if (FAILED(BltAllLevels(D3DCUBEMAP_FACE_FORCE_DWORD, ptexCur, *pptexNew))) return hr; }// else if (m_dwCubeMapFlags > 0)// {// hr = pd3ddev->CreateCubeTexture(m_dwWidth, m_numMips, // 0, fmtTo, D3DPOOL_MANAGED, &pcubetexNew, NULL);// if (FAILED(hr))// return hr;// *pptexNew = pcubetexNew;// if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_NEGATIVE_X, ptexCur, *pptexNew)))// return hr;// if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_POSITIVE_X, ptexCur, *pptexNew)))// return hr;// if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_NEGATIVE_Y, ptexCur, *pptexNew)))// return hr;// if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_POSITIVE_Y, ptexCur, *pptexNew)))// return hr;// if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_NEGATIVE_Z, ptexCur, *pptexNew)))// return hr;// if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_POSITIVE_Z, ptexCur, *pptexNew)))// return hr;// } else { if ((fmtTo == D3DFMT_DXT1 || fmtTo == D3DFMT_DXT2 || fmtTo == D3DFMT_DXT3 || fmtTo == D3DFMT_DXT4 || fmtTo == D3DFMT_DXT5) && (m_dwWidth % 4 != 0 || m_dwHeight % 4 != 0)) { // AfxMessageBox(ID_ERROR_NEEDMULTOF4); return E_FAIL; } hr = pd3ddev->CreateTexture(m_dwWidth, m_dwHeight, m_numMips, 0, fmtTo, D3DPOOL_MANAGED, &pmiptexNew, NULL); if (FAILED(hr)) return hr; *pptexNew = pmiptexNew; if (FAILED(BltAllLevels(D3DCUBEMAP_FACE_FORCE_DWORD, ptexCur, *pptexNew))) return hr; } return S_OK;}HRESULT CDDSConvert::BltAllLevels(D3DCUBEMAP_FACES FaceType, LPDIRECT3DBASETEXTURE9 ptexSrc, LPDIRECT3DBASETEXTURE9 ptexDest){ HRESULT hr; LPDIRECT3DTEXTURE9 pmiptexSrc; LPDIRECT3DTEXTURE9 pmiptexDest; LPDIRECT3DCUBETEXTURE9 pcubetexSrc; LPDIRECT3DCUBETEXTURE9 pcubetexDest; LPDIRECT3DVOLUMETEXTURE9 pvoltexSrc; LPDIRECT3DVOLUMETEXTURE9 pvoltexDest; DWORD iLevel; if (IsVolumeMap()) { pvoltexSrc = (LPDIRECT3DVOLUMETEXTURE9)ptexSrc; pvoltexDest = (LPDIRECT3DVOLUMETEXTURE9)ptexDest; }// else if (IsCubeMap())// {// pcubetexSrc = (LPDIRECT3DCUBETEXTURE9)ptexSrc;// pcubetexDest = (LPDIRECT3DCUBETEXTURE9)ptexDest;// } else { pmiptexSrc = (LPDIRECT3DTEXTURE9)ptexSrc; pmiptexDest = (LPDIRECT3DTEXTURE9)ptexDest; } for (iLevel = 0; iLevel < m_numMips; iLevel++) { if (IsVolumeMap()) { LPDIRECT3DVOLUME9 pvolSrc = NULL; LPDIRECT3DVOLUME9 pvolDest = NULL; hr = pvoltexSrc->GetVolumeLevel(iLevel, &pvolSrc); hr = pvoltexDest->GetVolumeLevel(iLevel, &pvolDest); hr = D3DXLoadVolumeFromVolume(pvolDest, NULL, NULL, pvolSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&pvolSrc); ReleasePpo(&pvolDest); }// else if (IsCubeMap())// {// LPDIRECT3DSURFACE9 psurfSrc = NULL;// LPDIRECT3DSURFACE9 psurfDest = NULL;// hr = pcubetexSrc->GetCubeMapSurface(FaceType, iLevel, &psurfSrc);// hr = pcubetexDest->GetCubeMapSurface(FaceType, iLevel, &psurfDest);// hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, // psurfSrc, NULL, NULL, D3DX_DEFAULT, 0);// ReleasePpo(&psurfSrc);// ReleasePpo(&psurfDest);// } else { LPDIRECT3DSURFACE9 psurfSrc = NULL; LPDIRECT3DSURFACE9 psurfDest = NULL; hr = pmiptexSrc->GetSurfaceLevel(iLevel, &psurfSrc); hr = pmiptexDest->GetSurfaceLevel(iLevel, &psurfDest); hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&psurfSrc); ReleasePpo(&psurfDest); } } return S_OK;}
[解决办法]
微软的开发者官网上有讲解的