8,305
社区成员
发帖
与我相关
我的任务
分享
// ------------------------------------------------------------------------
//§ 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
#endif
CDDSConvert::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;
}
// 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_ALPHAPIXELS
const 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_VOLUME
struct 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