Home | History | Annotate | Download | only in dds_to_header
      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