-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathetc2codec.cxx
148 lines (133 loc) · 3.05 KB
/
etc2codec.cxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include "etcpack.cxx"
#undef R
#undef G
#undef B
extern "C" {
#define LUA_LIB
#include <lua.h>
#include <lauxlib.h>
#include <stdint.h>
}
static inline void
big_endian_encode(unsigned int block, uint8_t r[4]) {
r[0] = (uint8_t)(block >> 24);
r[1] = (uint8_t)(block >> 16);
r[2] = (uint8_t)(block >> 8);
r[3] = (uint8_t)(block);
}
static inline unsigned int
big_endian_decode(const uint8_t r[4]) {
return (unsigned int)r[0] << 24 | r[1] << 16 | r[2] << 8 | r[3];
}
/*
string source rgba
string flag [21][fs][pn]
f fast default
s slow
p perceptual default
n nonperceptual
*/
static int
lcompress(lua_State *L) {
size_t sz;
const char * data = luaL_checklstring(L, 1, &sz);
if (sz != 16*4) {
return luaL_error(L, "Not 4x4 RGBA block");
}
int fast = 1;
int perceptual = 1;
if (lua_isstring(L, 2)) {
const char *flags = lua_tostring(L, 2);
int i;
for (i=0;flags[i];i++) {
switch(flags[i]) {
case 's':
fast = 0;
break;
case 'f':
fast = 1;
break;
case 'p':
perceptual = 1;
break;
case 'n':
perceptual = 0;
break;
default:
return luaL_error(L, "Unknown flags %s", flags);
}
}
}
uint8_t color[16*16*3];
uint8_t color_dec[16*16*3];
uint8_t alpha[16*16];
uint8_t result[16];
int i;
for (i=0;i<16*16;i++) {
color[i*3+0] = data[i*4+0];
color[i*3+1] = data[i*4+1];
color[i*3+2] = data[i*4+2];
alpha[i] = data[i*4+3];
}
unsigned int block1, block2;
if (fast) {
if (perceptual) {
compressBlockETC2FastPerceptual(color, color_dec, 4, 4, 0, 0, block1, block2);
} else {
compressBlockETC2Fast(color, alpha, color_dec, 4, 4, 0, 0, block1, block2);
}
} else {
if (perceptual) {
compressBlockETC2ExhaustivePerceptual(color, color_dec, 4, 4, 0, 0, block1, block2);
} else {
compressBlockETC2Exhaustive(color, color_dec, 4, 4, 0, 0, block1, block2);
}
}
if (fast) {
compressBlockAlphaFast(alpha, 0, 0, 4, 4, result);
} else {
compressBlockAlphaSlow(alpha, 0, 0, 4, 4, result);
}
big_endian_encode(block1, result+8);
big_endian_encode(block2, result+12);
lua_pushlstring(L, (const char *)result, 16);
return 1;
}
static int
luncompress(lua_State *L) {
size_t sz;
const char * data = luaL_checklstring(L, 1, &sz);
if (sz != 16) {
return luaL_error(L, "The size of ETC2 RGBA block should be 16 bytes.");
}
uint8_t alphaimg[16];
decompressBlockAlpha((uint8 *)(data),alphaimg,4,4,0,0);
uint8_t img[16*3];
unsigned int block1 = big_endian_decode((const uint8_t *)(data + 8));
unsigned int block2 = big_endian_decode((const uint8_t *)(data + 12));
decompressBlockETC2(block1, block2,img,4,4,0,0);
uint8_t result[16*4];
int i;
for (i=0;i<16;i++) {
result[i*4+0] = img[i*3+0];
result[i*4+1] = img[i*3+1];
result[i*4+2] = img[i*3+2];
result[i*4+3] = alphaimg[i];
}
lua_pushlstring(L,(const char *)result, 16*4);
return 1;
}
extern "C" {
LUAMOD_API int
luaopen_etc2codec(lua_State *L) {
luaL_checkversion(L);
setupAlphaTableAndValtab();
luaL_Reg l[] = {
{ "compress", lcompress },
{ "uncompress", luncompress },
{ NULL, NULL },
};
luaL_newlib(L, l);
return 1;
}
}