1 // 2 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 #include <ddraw.h> 8 #include <d3d9types.h> 9 #include <stdio.h> 10 #include <fstream> 11 #include <vector> 12 #include <iostream> 13 #include <string> 14 #include <algorithm> 15 #include <array> 16 17 int main(int argc, char **argv) 18 { 19 std::string programName(argv[0]); 20 if (argc < 4) 21 { 22 std::cout << "usage:\n"; 23 std::cout << programName << "INPUT_FILE OUTPUT_C_ARRAY_NAME OUTPUT_FILE\n"; 24 return -1; 25 } 26 27 std::string inputFile(argv[1]); 28 std::string outputName(argv[2]); 29 std::string outputFile(argv[3]); 30 std::ifstream readFile(inputFile, std::ios::binary | std::ios::in); 31 32 readFile.seekg(0, std::ios::end); 33 std::streamoff fileSize = readFile.tellg(); 34 readFile.seekg(0, std::ios::beg); 35 36 const std::size_t minSize = sizeof(DDSURFACEDESC2) + sizeof(DWORD); 37 if (fileSize < minSize) 38 { 39 std::cout << inputFile << " is only " << fileSize << " bytes, must be at greater than " << minSize 40 << " bytes to be a correct DDS image file.\n"; 41 return -2; 42 } 43 44 DWORD magicWord; 45 readFile.read(reinterpret_cast<char*>(&magicWord), sizeof(DWORD)); 46 if (magicWord != MAKEFOURCC('D','D','S',' ')) 47 { 48 std::cout << "Magic word must be " << MAKEFOURCC('D','D','S',' ') << ".\n"; 49 return -3; 50 } 51 52 DDSURFACEDESC2 header; 53 readFile.read(reinterpret_cast<char*>(&header), sizeof(DDSURFACEDESC2)); 54 55 std::string formatName; 56 std::size_t blockSize = 0; 57 std::size_t blockWidth = 0; 58 std::size_t blockHeight = 0; 59 60 if (header.ddpfPixelFormat.dwFlags & DDPF_RGB) 61 { 62 blockSize = header.ddpfPixelFormat.dwRGBBitCount / 8; 63 blockWidth = 1; 64 blockHeight = 1; 65 66 if (blockSize == 4) 67 { 68 if (header.ddpfPixelFormat.dwRBitMask == 0x000000FF && 69 header.ddpfPixelFormat.dwGBitMask == 0x0000FF00 && 70 header.ddpfPixelFormat.dwBBitMask == 0x00FF0000 && 71 header.ddpfPixelFormat.dwRGBAlphaBitMask == 0xFF000000) 72 { 73 formatName = "RGBA8"; 74 } 75 else if (header.ddpfPixelFormat.dwRBitMask == 0x000000FF && 76 header.ddpfPixelFormat.dwGBitMask == 0x0000FF00 && 77 header.ddpfPixelFormat.dwBBitMask == 0x00FF0000 && 78 header.ddpfPixelFormat.dwRGBAlphaBitMask == 0x00000000) 79 { 80 formatName = "RGBX8"; 81 } 82 else if (header.ddpfPixelFormat.dwRBitMask == 0x000003FF && 83 header.ddpfPixelFormat.dwGBitMask == 0x000FFC00 && 84 header.ddpfPixelFormat.dwBBitMask == 0x3FF00000 && 85 header.ddpfPixelFormat.dwRGBAlphaBitMask == 0xC0000000) 86 { 87 formatName = "RGB10A2"; 88 } 89 else if (header.ddpfPixelFormat.dwRBitMask == 0x0000FFFF && 90 header.ddpfPixelFormat.dwGBitMask == 0xFFFF0000 && 91 header.ddpfPixelFormat.dwBBitMask == 0x00000000 && 92 header.ddpfPixelFormat.dwRGBAlphaBitMask == 0x00000000) 93 { 94 formatName = "RG16"; 95 } 96 else if (header.ddpfPixelFormat.dwRBitMask == 0xFFFFFFFF && 97 header.ddpfPixelFormat.dwGBitMask == 0x00000000 && 98 header.ddpfPixelFormat.dwBBitMask == 0x00000000 && 99 header.ddpfPixelFormat.dwRGBAlphaBitMask == 0x00000000) 100 { 101 formatName = "R32"; 102 } 103 else 104 { 105 formatName = "UKNOWN"; 106 } 107 } 108 } 109 else if (header.ddpfPixelFormat.dwFlags & DDPF_FOURCC) 110 { 111 switch (header.ddpfPixelFormat.dwFourCC) 112 { 113 case MAKEFOURCC('D','X','T','1'): 114 formatName = "DXT1"; 115 blockSize = 8; 116 blockWidth = 4; 117 blockHeight = 4; 118 break; 119 120 case MAKEFOURCC('D','X','T','3'): 121 formatName = "DXT3"; 122 blockSize = 16; 123 blockWidth = 4; 124 blockHeight = 4; 125 break; 126 127 case MAKEFOURCC('D','X','T','5'): 128 formatName = "DXT5"; 129 blockSize = 16; 130 blockWidth = 4; 131 blockHeight = 4; 132 break; 133 134 case D3DFMT_R32F: 135 formatName = "R32F"; 136 blockSize = 4; 137 blockWidth = 1; 138 blockHeight = 1; 139 140 case D3DFMT_G32R32F: 141 formatName = "RG32F"; 142 blockSize = 8; 143 blockWidth = 1; 144 blockHeight = 1; 145 146 case D3DFMT_A32B32G32R32F: 147 formatName = "RGBA32F"; 148 blockSize = 16; 149 blockWidth = 1; 150 blockHeight = 1; 151 152 case D3DFMT_R16F: 153 formatName = "R16F"; 154 blockSize = 2; 155 blockWidth = 1; 156 blockHeight = 1; 157 158 case D3DFMT_G16R16F: 159 formatName = "RG16F"; 160 blockSize = 4; 161 blockWidth = 1; 162 blockHeight = 1; 163 164 case D3DFMT_A16B16G16R16F: 165 formatName = "RGBA16F"; 166 blockSize = 8; 167 blockWidth = 1; 168 blockHeight = 1; 169 170 default: 171 std::cout << "Unsupported FourCC format.\n"; 172 return -5; 173 } 174 } 175 else 176 { 177 std::cout << "Unsupported DDS format.\n"; 178 return -6; 179 } 180 181 std::size_t height = header.dwHeight; 182 std::size_t width = header.dwWidth; 183 std::size_t levels = std::max<size_t>(1, header.dwMipMapCount); 184 185 std::ofstream oss(outputFile); 186 oss << "// Automatically generated header from " << inputFile << ", a " << width << "x" << height; 187 if (levels > 1) 188 { 189 oss << " (" << levels << " mip levels)"; 190 } 191 oss << "\n// " << formatName << " texture using " << programName << ".\n"; 192 193 oss << "static const size_t " << outputName << "_width = " << width << ";\n"; 194 oss << "static const size_t " << outputName << "_height = " << height << ";\n"; 195 oss << "static const size_t " << outputName << "_levels = " << levels << ";\n"; 196 oss << "\n"; 197 198 for (std::size_t i = 0; i < levels; ++i) 199 { 200 std::size_t widthAtLevel = std::max<size_t>(width >> i, 1); 201 std::size_t heightAtLevel = std::max<size_t>(height >> i, 1); 202 std::size_t sizeAtLevel = static_cast<std::size_t>(std::ceil(widthAtLevel / static_cast<float>(blockWidth)) * 203 std::ceil(heightAtLevel / static_cast<float>(blockHeight))) * 204 blockSize; 205 206 std::vector<unsigned char> data(sizeAtLevel); 207 readFile.read(reinterpret_cast<char*>(data.data()), sizeAtLevel); 208 209 oss << "static const size_t " << outputName << "_" << i << "_width = " << widthAtLevel << ";\n"; 210 oss << "static const size_t " << outputName << "_" << i << "_height = " << heightAtLevel << ";\n"; 211 oss << "static const size_t " << outputName << "_" << i << "_size = " << sizeAtLevel << ";\n"; 212 oss << "static const unsigned char " << outputName << "_" << i << "_data[" << sizeAtLevel << "] =\n"; 213 oss << "{"; 214 for (std::size_t j = 0; j < sizeAtLevel; j++) 215 { 216 if (j % 16 == 0) 217 { 218 oss << "\n "; 219 } 220 221 char buffer[32]; 222 sprintf_s(buffer, "0x%02X,", data[j]); 223 oss << std::string(buffer); 224 } 225 oss << "\n"; 226 oss << "};\n"; 227 228 if (i + 1 < levels) 229 { 230 oss << "\n"; 231 } 232 } 233 234 oss.close(); 235 readFile.close(); 236 237 return 0; 238 } 239