Merge pull request #4735 from cg110/fix_web_server_mem_leak
[vuplus_xbmc] / tools / TexturePacker / MakeDDS.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <sys/types.h>
22 #include <squish.h>
23 #include <string>
24 #include <SDL/SDL.h>
25 #include <SDL/SDL_image.h>
26 #include "cmdlineargs.h"
27 #ifdef TARGET_WINDOWS
28 #define strncasecmp strnicmp
29 #endif
30 #include "DDSImage.h"
31 #include "XBTF.h"
32
33 #undef main
34
35 const char *GetFormatString(unsigned int format)
36 {
37   switch (format)
38   {
39   case squish::kDxt1:
40     return "DXT1 ";
41   case squish::kDxt5:
42     return "YCoCg";
43   default:
44     return "?????";
45   }
46 }
47
48 void CompressImage(const squish::u8 *brga, int width, int height, squish::u8 *compressed, unsigned int flags, double &colorMSE, double &alphaMSE)
49 {
50   squish::CompressImage(brga, width, height, compressed, flags | squish::kSourceBGRA);
51   squish::ComputeMSE(brga, width, height, compressed, flags | squish::kSourceBGRA, colorMSE, alphaMSE);
52 }
53
54 void CompressToDDS(SDL_Surface* image, unsigned int format, CDDSImage &out)
55 {
56   // Convert to ARGB
57   SDL_PixelFormat argbFormat;
58   memset(&argbFormat, 0, sizeof(SDL_PixelFormat));
59   argbFormat.BitsPerPixel = 32;
60   argbFormat.BytesPerPixel = 4;
61
62 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
63   argbFormat.Amask = 0xff000000;
64   argbFormat.Ashift = 24;
65   argbFormat.Rmask = 0x00ff0000;
66   argbFormat.Rshift = 16;
67   argbFormat.Gmask = 0x0000ff00;
68   argbFormat.Gshift = 8;
69   argbFormat.Bmask = 0x000000ff;
70   argbFormat.Bshift = 0;
71 #else
72   argbFormat.Amask = 0x000000ff;
73   argbFormat.Ashift = 0;
74   argbFormat.Rmask = 0x0000ff00;
75   argbFormat.Rshift = 8;
76   argbFormat.Gmask = 0x00ff0000;
77   argbFormat.Gshift = 16;
78   argbFormat.Bmask = 0xff000000;
79   argbFormat.Bshift = 24;
80 #endif
81
82   SDL_Surface *argbImage = SDL_ConvertSurface(image, &argbFormat, 0);
83
84   double colorMSE, alphaMSE;
85   if (format == XB_FMT_DXT1)
86     CompressImage((squish::u8 *)argbImage->pixels, image->w, image->h, out.GetData(), squish::kDxt1, colorMSE, alphaMSE);
87   else if (format == XB_FMT_DXT5)
88     CompressImage((squish::u8 *)argbImage->pixels, image->w, image->h, out.GetData(), squish::kDxt5, colorMSE, alphaMSE);
89
90   // print some info about the resulting image
91   printf("Size: %dx%d %s in %u bytes. Quality: %5.2f\n", image->w, image->h, GetFormatString(format), out.GetSize(), colorMSE);
92
93   SDL_FreeSurface(argbImage);
94 }
95
96 void Usage()
97 {
98   puts("Usage: MakeDDS [-oN] input [output]");
99   puts(" -o1 for DXT1");
100   puts(" -o5 for DXT5");
101 }
102
103 void createDDS(const std::string& inputFile, const std::string& outputFile, unsigned int format)
104 {
105   // Load the image
106   SDL_Surface* image = IMG_Load(inputFile.c_str());
107   if (!image)
108   {
109     printf("...unable to load image %s\n", inputFile.c_str());
110     return;
111   }
112
113   CDDSImage dds(image->w, image->h, format);
114   CompressToDDS(image, format, dds);
115
116   // write to a DDS file
117   dds.WriteFile(outputFile);
118
119   SDL_FreeSurface(image);
120 }
121
122 int main(int argc, char* argv[])
123 {
124   bool valid = false;
125   CmdLineArgs args(argc, (const char**)argv);
126
127   if (args.size() == 1)
128   {
129     Usage();
130     return 1;
131   }
132
133   std::string inputFile;
134   std::string outputFile;
135
136   unsigned int format = squish::kDxt1;
137   for (unsigned int i = 1; i < args.size(); ++i)
138   {
139     if (!stricmp(args[i], "--help") || !stricmp(args[i], "-?") || !stricmp(args[i], "?"))
140     {
141       Usage();
142       return 1;
143     }
144     else if (!strncasecmp(args[i], "-o1", 3))
145       format = XB_FMT_DXT1;
146     else if (!strncasecmp(args[i], "-o5", 3))
147       format = XB_FMT_DXT5;
148     else if (!inputFile.size())
149     {
150       inputFile = args[i];
151       valid = true;
152     }
153     else if (!outputFile.size())
154     {
155       outputFile = args[i];
156       valid = true;
157     }
158     else
159     {
160       printf("Unrecognized command line flag: %s\n", args[i]);
161     }
162   }
163
164   if (outputFile.empty())
165   { // construct output file from input - rename to .dds
166     size_t pos = inputFile.find_last_of('.');
167     if (pos != std::string::npos)
168     {
169       outputFile = inputFile.substr(0, pos);
170       outputFile += ".dds";
171     }
172   }
173
174   if (!valid)
175   {
176     Usage();
177     return 1;
178   }
179
180   createDDS(inputFile, outputFile, format);
181 }