OSDN Git Service

Fix some warnings, fixes #3
[android-x86/external-s2tc.git] / s2tc_decompress.cpp
1 /*
2  * Copyright (C) 2011  Rudolf Polzer   All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * RUDOLF POLZER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20  */
21 #define S2TC_LICENSE_IDENTIFIER s2tc_decompress_license
22 #include "s2tc_license.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdint.h>
28 #include <getopt.h>
29 #include <algorithm>
30 #include "s2tc_common.h"
31
32 #ifdef ENABLE_RUNTIME_LINKING
33 #include <dlfcn.h>
34 #include <GL/gl.h>
35 extern "C"
36 {
37         typedef void (fetch_2d_texel_rgb_dxt1_t)(GLint srcRowStride, const GLubyte *pixdata,
38                              GLint i, GLint j, GLvoid *texel);
39         typedef void (fetch_2d_texel_rgba_dxt1_t)(GLint srcRowStride, const GLubyte *pixdata,
40                              GLint i, GLint j, GLvoid *texel);
41         typedef void (fetch_2d_texel_rgba_dxt3_t)(GLint srcRowStride, const GLubyte *pixdata,
42                              GLint i, GLint j, GLvoid *texel);
43         typedef void (fetch_2d_texel_rgba_dxt5_t)(GLint srcRowStride, const GLubyte *pixdata,
44                                      GLint i, GLint j, GLvoid *texel);
45 };
46 fetch_2d_texel_rgb_dxt1_t *fetch_2d_texel_rgb_dxt1 = NULL;
47 fetch_2d_texel_rgba_dxt1_t *fetch_2d_texel_rgba_dxt1 = NULL;
48 fetch_2d_texel_rgba_dxt3_t *fetch_2d_texel_rgba_dxt3 = NULL;
49 fetch_2d_texel_rgba_dxt5_t *fetch_2d_texel_rgba_dxt5 = NULL;
50 inline bool load_libraries(const char *n)
51 {
52         void *l = dlopen(n, RTLD_NOW);
53         if(!l)
54         {
55                 fprintf(stderr, "Cannot load library: %s\n", dlerror());
56                 return false;
57         }
58         fetch_2d_texel_rgb_dxt1 = (fetch_2d_texel_rgb_dxt1_t *) dlsym(l, "fetch_2d_texel_rgb_dxt1");
59         fetch_2d_texel_rgba_dxt1 = (fetch_2d_texel_rgba_dxt1_t *) dlsym(l, "fetch_2d_texel_rgba_dxt1");
60         fetch_2d_texel_rgba_dxt3 = (fetch_2d_texel_rgba_dxt3_t *) dlsym(l, "fetch_2d_texel_rgba_dxt3");
61         fetch_2d_texel_rgba_dxt5 = (fetch_2d_texel_rgba_dxt5_t *) dlsym(l, "fetch_2d_texel_rgba_dxt5");
62         if(!fetch_2d_texel_rgb_dxt1 || !fetch_2d_texel_rgba_dxt1 || !fetch_2d_texel_rgba_dxt3 || !fetch_2d_texel_rgba_dxt5)
63         {
64                 fprintf(stderr, "The selected libtxc_dxtn.so does not contain all required symbols.");
65                 dlclose(l);
66                 return false;
67         }
68         return true;
69 }
70 #else
71 extern "C"
72 {
73 #include "txc_dxtn.h"
74 };
75 #endif
76
77 uint32_t LittleLong(uint32_t w)
78 {
79         union
80         {
81                 unsigned char c[4];
82                 uint32_t u;
83         }
84         un;
85         un.c[0] = w;
86         un.c[1] = w >> 8;
87         un.c[2] = w >> 16;
88         un.c[3] = w >> 24;
89         return un.u;
90 }
91
92 int usage(const char *me)
93 {
94         fprintf(stderr, "usage:\n"
95                         "%s \n"
96                         "    [-i infile.tga]\n"
97                         "    [-o outfile.dds]\n"
98 #ifdef ENABLE_RUNTIME_LINKING
99                         "    [-l path_to_libtxc_dxtn.so]\n"
100 #endif
101                         ,
102                         me);
103         return 1;
104 }
105
106 int main(int argc, char **argv)
107 {
108         const char *infile = NULL, *outfile = NULL;
109
110 #ifdef ENABLE_RUNTIME_LINKING
111         const char *library = "libtxc_dxtn.so";
112 #endif
113
114         int opt;
115         while((opt = getopt(argc, argv, "i:o:"
116 #ifdef ENABLE_RUNTIME_LINKING
117                                         "l:"
118 #endif
119                                         )) != -1)
120         {
121                 switch(opt)
122                 {
123                         case 'i':
124                                 infile = optarg;
125                                 break;
126                         case 'o':
127                                 outfile = optarg;
128                                 break;
129 #ifdef ENABLE_RUNTIME_LINKING
130                         case 'l':
131                                 library = optarg;
132                                 break;
133 #endif
134                         default:
135                                 return usage(argv[0]);
136                                 break;
137                 }
138         }
139 #ifdef ENABLE_RUNTIME_LINKING
140         if(!load_libraries(library))
141                 return 1;
142 #endif
143
144         FILE *infh = infile ? fopen(infile, "rb") : stdin;
145         if(!infh)
146         {
147                 printf("opening input failed\n");
148                 return 2;
149         }
150
151         FILE *outfh = outfile ? fopen(outfile, "wb") : stdout;
152         if(!outfh)
153         {
154                 printf("opening output failed\n");
155                 return 2;
156         }
157
158         uint32_t h[32];
159         fread(h, sizeof(h), 1, infh);
160         int height = LittleLong(h[3]);
161         int width = LittleLong(h[4]);
162
163         void (*fetch)(GLint srcRowStride, const GLubyte *pixdata, GLint i, GLint j, GLvoid *texel) = NULL;
164         int fourcc = LittleLong(h[21]);
165         int blocksize;
166         switch(fourcc)
167         {
168                 case 0x31545844:
169                         fetch = fetch_2d_texel_rgba_dxt1;
170                         blocksize = 8;
171                         break;
172                 case 0x33545844:
173                         fetch = fetch_2d_texel_rgba_dxt3;
174                         blocksize = 16;
175                         break;
176                 case 0x35545844:
177                         fetch = fetch_2d_texel_rgba_dxt5;
178                         blocksize = 16;
179                         break;
180                 default:
181                         fprintf(stderr, "Only DXT1, DXT3, DXT5 are supported!\n");
182                         return 1;
183         }
184
185         unsigned char t[18];
186         memset(t, 0, 18);
187         t[2]  = 2;
188         t[12] = width % 256;
189         t[13] = width / 256;
190         t[14] = height % 256;
191         t[15] = height / 256;
192         t[16] = 32;
193         t[17] = 0x28;
194         fwrite(t, 18, 1, outfh);
195
196         int n = ((width + 3) / 4) * ((height + 3) / 4);
197         unsigned char *buf = (unsigned char *) malloc(n * blocksize);
198         fread(buf, blocksize, n, infh);
199
200         int x, y;
201         for(y = 0; y < height; ++y)
202                 for(x = 0; x < width; ++x)
203                 {
204                         char data[4];
205                         fetch(width, buf, x, y, &data);
206                         std::swap(data[0], data[2]);
207                         fwrite(data, 4, 1, outfh);
208                 }
209
210         if(infile)
211                 fclose(infh);
212         if(outfile)
213                 fclose(outfh);
214
215         return 0;
216 }