int main(int argc, char* argv[]) { // imFormatRegisterJP2(); // imFormatRegisterAVI(); // imFormatRegisterWMV(); if (argc < 2) { printf("Invalid number of arguments.\n"); return 0; } PrintImageInfo(argv[1]); return 1; }
void ConvertFile(const char* Dir, const char* Filename, double MaxMSE) { HRESULT hr; LPDIRECT3DSURFACE8 pSrcSurf = NULL; char OutFilename[52]; if (Dir) _snprintf(OutFilename, 52, "%s\\%s", Dir, Filename); else _snprintf(OutFilename, 52, "%s", Filename); OutFilename[51] = 0; printf("%s: ", OutFilename); TRACE1("%s:\n", OutFilename); int n = strlen(OutFilename); if (n < 40) printf("%*c", 40-n, ' '); if (pSrcSurf) pSrcSurf->Release(); pSrcSurf = NULL; // Load up the file D3DXIMAGE_INFO info; hr = D3DXGetImageInfoFromFile(Filename, &info); CheckHR(hr); PrintImageInfo(info); UINT Width = PadPow2(info.Width); UINT Height = PadPow2(info.Height); float Waste = 100.f * (float)(Width * Height - info.Width * info.Height) / (float)(Width * Height); UncompressedSize += Width * Height * 4; TotalSrcPixels += info.Width * info.Height; TotalDstPixels += Width * Height; // Special case for 256-colour files - just directly drop into a P8 xpr if (info.Format == D3DFMT_P8) { hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pSrcSurf); CheckHR(hr); hr = D3DXLoadSurfaceFromFile(pSrcSurf, NULL, NULL, Filename, NULL, D3DX_FILTER_NONE, 0, NULL); CheckHR(hr); FixTransparency(pSrcSurf); if (Width * Height > 4096) { // DXT1 for P8s if lossless and more than 4k image LPDIRECT3DSURFACE8 pTempSurf; hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pTempSurf); CheckHR(hr); hr = D3DXLoadSurfaceFromSurface(pTempSurf, NULL, NULL, pSrcSurf, NULL, NULL, D3DX_FILTER_NONE, 0); CheckHR(hr); double CMSE, AMSE; TRACE0(" Checking DXT1: "); if (!GetFormatMSE(info, pTempSurf, D3DFMT_DXT1, CMSE, AMSE)) { pTempSurf->Release(); return; } TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE); if (CMSE <= 1e-6 && AMSE <= 1e-6) { printf("DXT1 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: DXT1\n"); WriteXPR(OutFilename, info, pTempSurf, XB_D3DFMT_DXT1, NULL); pTempSurf->Release(); return; } pTempSurf->Release(); } printf("P8 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: P8\n"); LPDIRECT3DSURFACE8 pTempSurf; DWORD pal[256]; ConvertP8(pSrcSurf, pTempSurf, pal, info); WriteXPR(OutFilename, info, pTempSurf, XB_D3DFMT_P8, pal); pTempSurf->Release(); return; } // test linear format versus non-linear format // Linear format requires 64 pixel aligned width, whereas // Non-linear format requires power of 2 width and height bool useLinearFormat(false); UINT linearWidth = (info.Width + 0x3f) & ~0x3f; if (AllowLinear && linearWidth * info.Height < Width * Height) useLinearFormat = true; hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pSrcSurf); CheckHR(hr); hr = D3DXLoadSurfaceFromFile(pSrcSurf, NULL, NULL, Filename, NULL, D3DX_FILTER_NONE, 0, NULL); CheckHR(hr); // create the linear version as well LPDIRECT3DSURFACE8 pLinearSrcSurf = NULL; if (useLinearFormat) { hr = pD3DDevice->CreateImageSurface(linearWidth, info.Height, D3DFMT_A8R8G8B8, &pLinearSrcSurf); CheckHR(hr); hr = D3DXLoadSurfaceFromFile(pLinearSrcSurf, NULL, NULL, Filename, NULL, D3DX_FILTER_NONE, 0, NULL); CheckHR(hr); } // special case for small files - all textures are alloced on page granularity so just output uncompressed // dxt is crap on small files anyway if (Width * Height <= 1024) { if (useLinearFormat) { // correct sizing amounts UncompressedSize -= Width * Height * 4; UncompressedSize += linearWidth * info.Height * 4; TotalDstPixels -= Width * Height; TotalDstPixels += linearWidth * info.Height; Waste = 100.f * (float)(linearWidth * info.Height - info.Width * info.Height) / (float)(linearWidth * info.Height); printf("LIN_A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", linearWidth, info.Height, Waste); TRACE0(" Selected Format: LIN_A8R8G8B8\n"); WriteXPR(OutFilename, info, pLinearSrcSurf, XB_D3DFMT_LIN_A8R8G8B8, NULL); } else { printf("A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: A8R8G8B8\n"); WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_A8R8G8B8, NULL); } return; } FixTransparency(pSrcSurf); // Find the best format within specified tolerance double CMSE, AMSE[2]; // DXT1 is the preferred format as it's smallest TRACE0(" Checking DXT1: "); if (!GetFormatMSE(info, pSrcSurf, D3DFMT_DXT1, CMSE, AMSE[0])) return; TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE[0]); if (CMSE <= MaxMSE && AMSE[0] <= MaxMSE) { printf("DXT1 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: DXT1\n"); WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_DXT1, NULL); return; } // Use P8 is possible as it's lossless LPDIRECT3DSURFACE8 pTempSurf; DWORD pal[256]; if (ConvertP8(pSrcSurf, pTempSurf, pal, info)) { printf("P8 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: P8\n"); WriteXPR(OutFilename, info, pTempSurf, XB_D3DFMT_P8, pal); pTempSurf->Release(); return; } // DXT3/5 are the same size so use whichever is better if good enough // CMSE will be equal for both TRACE0(" Checking DXT3: "); if (!GetFormatMSE(info, pSrcSurf, D3DFMT_DXT3, CMSE, AMSE[0])) return; TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE[0]); TRACE0(" Checking DXT5: "); if (!GetFormatMSE(info, pSrcSurf, D3DFMT_DXT5, CMSE, AMSE[1])) return; TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE[1]); if (AMSE[0] <= AMSE[1]) { if (CMSE <= MaxMSE && AMSE[0] <= MaxMSE) { printf("DXT3 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: DXT3\n"); WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_DXT3, NULL); return; } } else { if (CMSE <= MaxMSE && AMSE[1] <= MaxMSE) { printf("DXT5 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: DXT5\n"); WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_DXT5, NULL); return; } } // No good compressed format so use uncompressed // A1R5G5B5 is worth a try I guess... TRACE0(" Checking A1R5G5B5: "); if (!GetFormatMSE(info, pSrcSurf, D3DFMT_A1R5G5B5, CMSE, AMSE[0])) return; TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE[0]); if (CMSE <= MaxMSE && AMSE[0] <= MaxMSE) { printf("A1R5G5B5 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: A1R5G5B5\n"); LPDIRECT3DSURFACE8 pTempSurf; hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A1R5G5B5, &pTempSurf); CheckHR(hr); hr = D3DXLoadSurfaceFromSurface(pTempSurf, NULL, NULL, pSrcSurf, NULL, NULL, D3DX_FILTER_NONE, 0); CheckHR(hr); WriteXPR(OutFilename, info, pTempSurf, XB_D3DFMT_A1R5G5B5, NULL); pTempSurf->Release(); return; } // Use A8R8G8B8 if (useLinearFormat) { // correct sizing information UncompressedSize -= Width * Height * 4; UncompressedSize += linearWidth * info.Height * 4; TotalDstPixels -= Width * Height; TotalDstPixels += linearWidth * info.Height; Waste = 100.f * (float)(linearWidth * info.Height - info.Width * info.Height) / (float)(linearWidth * info.Height); printf("LIN_A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", linearWidth, info.Height, Waste); TRACE0(" Selected Format: LIN_A8R8G8B8\n"); WriteXPR(OutFilename, info, pLinearSrcSurf, XB_D3DFMT_LIN_A8R8G8B8, NULL); } else { printf("A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: A8R8G8B8\n"); WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_A8R8G8B8, NULL); } if (pSrcSurf) pSrcSurf->Release(); }