Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/basis_universal/encoder/basisu_pvrtc1_4.cpp
9903 views
1
// basisu_pvrtc1_4.cpp
2
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License");
5
// you may not use this file except in compliance with the License.
6
// You may obtain a copy of the License at
7
//
8
// http://www.apache.org/licenses/LICENSE-2.0
9
//
10
// Unless required by applicable law or agreed to in writing, software
11
// distributed under the License is distributed on an "AS IS" BASIS,
12
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
// See the License for the specific language governing permissions and
14
// limitations under the License.
15
#include "basisu_pvrtc1_4.h"
16
17
namespace basisu
18
{
19
#if 0
20
static const uint8_t g_pvrtc_5[32] = { 0,8,16,24,33,41,49,57,66,74,82,90,99,107,115,123,132,140,148,156,165,173,181,189,198,206,214,222,231,239,247,255 };
21
static const uint8_t g_pvrtc_4[16] = { 0,16,33,49,66,82,99,115,140,156,173,189,206,222,239,255 };
22
static const uint8_t g_pvrtc_3[8] = { 0,33,74,107,148,181,222,255 };
23
static const uint8_t g_pvrtc_alpha[9] = { 0,34,68,102,136,170,204,238,255 };
24
#endif
25
26
static const uint8_t g_pvrtc_5_nearest[256] = { 0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,31,31,31,31 };
27
static const uint8_t g_pvrtc_4_nearest[256] = { 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15 };
28
#if 0
29
static const uint8_t g_pvrtc_3_nearest[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 };
30
static const uint8_t g_pvrtc_alpha_nearest[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8 };
31
#endif
32
33
#if 0
34
static const uint8_t g_pvrtc_5_floor[256] =
35
{
36
0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,
37
3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,
38
7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,
39
11,11,11,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,15,15,15,15,15,
40
15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,
41
19,19,19,19,19,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,
42
23,23,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,27,27,
43
27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,31
44
};
45
46
static const uint8_t g_pvrtc_5_ceil[256] =
47
{
48
0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,
49
4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,8,8,8,8,8,8,
50
8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,12,12,12,12,12,
51
12,12,12,12,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,16,16,16,16,
52
16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,
53
20,20,20,20,20,20,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,
54
24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,28,
55
28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,31,31,31,31,31,31,31,31
56
};
57
58
static const uint8_t g_pvrtc_4_floor[256] =
59
{
60
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
61
1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
62
3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
63
5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,
64
7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,
65
9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,
66
11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,
67
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15
68
};
69
70
static const uint8_t g_pvrtc_4_ceil[256] =
71
{
72
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
73
2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
74
4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,
75
6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,
76
8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,
77
10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,
78
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,
79
14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15
80
};
81
82
static const uint8_t g_pvrtc_3_floor[256] =
83
{
84
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
85
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
86
1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
87
2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
88
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,
89
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,
90
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,
91
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7
92
};
93
94
static const uint8_t g_pvrtc_3_ceil[256] =
95
{
96
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
97
1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
98
2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
99
3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
100
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,
101
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,
102
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,
103
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
104
};
105
106
static const uint8_t g_pvrtc_alpha_floor[256] =
107
{
108
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
109
0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
110
1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
111
2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
112
3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
113
4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
114
5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
115
6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8
116
};
117
118
static const uint8_t g_pvrtc_alpha_ceil[256] =
119
{
120
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
121
1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
122
2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
123
3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
124
4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
125
5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
126
6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
127
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
128
};
129
#endif
130
131
uint32_t pvrtc4_swizzle_uv(uint32_t width, uint32_t height, uint32_t x, uint32_t y)
132
{
133
assert((x < width) && (y < height) && basisu::is_pow2(height) && basisu::is_pow2(width));
134
135
uint32_t min_d = width, max_v = y;
136
if (height < width)
137
{
138
min_d = height;
139
max_v = x;
140
}
141
142
// Interleave the XY LSB's
143
uint32_t shift_ofs = 0, swizzled = 0;
144
for (uint32_t s_bit = 1, d_bit = 1; s_bit < min_d; s_bit <<= 1, d_bit <<= 2, ++shift_ofs)
145
{
146
if (y & s_bit) swizzled |= d_bit;
147
if (x & s_bit) swizzled |= (2 * d_bit);
148
}
149
150
max_v >>= shift_ofs;
151
152
// OR in the rest of the bits from the largest dimension
153
swizzled |= (max_v << (2 * shift_ofs));
154
155
return swizzled;
156
}
157
158
color_rgba pvrtc4_block::get_endpoint(uint32_t endpoint_index, bool unpack) const
159
{
160
assert(endpoint_index < 2);
161
const uint32_t packed = m_endpoints >> (endpoint_index * 16);
162
163
uint32_t r, g, b, a;
164
if (packed & 0x8000)
165
{
166
// opaque 554 or 555
167
if (!endpoint_index)
168
{
169
r = (packed >> 10) & 31;
170
g = (packed >> 5) & 31;
171
b = (packed >> 1) & 15;
172
173
if (unpack)
174
{
175
b = (b << 1) | (b >> 3);
176
}
177
}
178
else
179
{
180
r = (packed >> 10) & 31;
181
g = (packed >> 5) & 31;
182
b = packed & 31;
183
}
184
185
a = unpack ? 255 : 7;
186
}
187
else
188
{
189
// translucent 4433 or 4443
190
if (!endpoint_index)
191
{
192
a = (packed >> 12) & 7;
193
r = (packed >> 8) & 15;
194
g = (packed >> 4) & 15;
195
b = (packed >> 1) & 7;
196
197
if (unpack)
198
{
199
a = (a << 1);
200
a = (a << 4) | a;
201
202
r = (r << 1) | (r >> 3);
203
g = (g << 1) | (g >> 3);
204
b = (b << 2) | (b >> 1);
205
}
206
}
207
else
208
{
209
a = (packed >> 12) & 7;
210
r = (packed >> 8) & 15;
211
g = (packed >> 4) & 15;
212
b = packed & 15;
213
214
if (unpack)
215
{
216
a = (a << 1);
217
a = (a << 4) | a;
218
219
r = (r << 1) | (r >> 3);
220
g = (g << 1) | (g >> 3);
221
b = (b << 1) | (b >> 3);
222
}
223
}
224
}
225
226
if (unpack)
227
{
228
r = (r << 3) | (r >> 2);
229
g = (g << 3) | (g >> 2);
230
b = (b << 3) | (b >> 2);
231
}
232
233
assert((r < 256) && (g < 256) && (b < 256) && (a < 256));
234
235
return color_rgba(r, g, b, a);
236
}
237
238
color_rgba pvrtc4_block::get_endpoint_5554(uint32_t endpoint_index) const
239
{
240
assert(endpoint_index < 2);
241
const uint32_t packed = m_endpoints >> (endpoint_index * 16);
242
243
uint32_t r, g, b, a;
244
if (packed & 0x8000)
245
{
246
// opaque 554 or 555
247
if (!endpoint_index)
248
{
249
r = (packed >> 10) & 31;
250
g = (packed >> 5) & 31;
251
b = (packed >> 1) & 15;
252
253
b = (b << 1) | (b >> 3);
254
}
255
else
256
{
257
r = (packed >> 10) & 31;
258
g = (packed >> 5) & 31;
259
b = packed & 31;
260
}
261
262
a = 15;
263
}
264
else
265
{
266
// translucent 4433 or 4443
267
if (!endpoint_index)
268
{
269
a = (packed >> 12) & 7;
270
r = (packed >> 8) & 15;
271
g = (packed >> 4) & 15;
272
b = (packed >> 1) & 7;
273
274
a = a << 1;
275
276
r = (r << 1) | (r >> 3);
277
g = (g << 1) | (g >> 3);
278
b = (b << 2) | (b >> 1);
279
}
280
else
281
{
282
a = (packed >> 12) & 7;
283
r = (packed >> 8) & 15;
284
g = (packed >> 4) & 15;
285
b = packed & 15;
286
287
a = a << 1;
288
289
r = (r << 1) | (r >> 3);
290
g = (g << 1) | (g >> 3);
291
b = (b << 1) | (b >> 3);
292
}
293
}
294
295
assert((r < 32) && (g < 32) && (b < 32) && (a < 16));
296
297
return color_rgba(r, g, b, a);
298
}
299
300
bool pvrtc4_image::get_interpolated_colors(uint32_t x, uint32_t y, color_rgba* pColors) const
301
{
302
assert((x < m_width) && (y < m_height));
303
304
int block_x0 = (static_cast<int>(x) - 2) >> 2;
305
int block_x1 = block_x0 + 1;
306
int block_y0 = (static_cast<int>(y) - 2) >> 2;
307
int block_y1 = block_y0 + 1;
308
309
block_x0 = posmod(block_x0, m_block_width);
310
block_x1 = posmod(block_x1, m_block_width);
311
block_y0 = posmod(block_y0, m_block_height);
312
block_y1 = posmod(block_y1, m_block_height);
313
314
pColors[0] = interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0));
315
pColors[3] = interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1));
316
317
if (get_block_uses_transparent_modulation(x >> 2, y >> 2))
318
{
319
for (uint32_t c = 0; c < 4; c++)
320
{
321
uint32_t m = (pColors[0][c] + pColors[3][c]) / 2;
322
pColors[1][c] = static_cast<uint8_t>(m);
323
pColors[2][c] = static_cast<uint8_t>(m);
324
}
325
pColors[2][3] = 0;
326
return true;
327
}
328
329
for (uint32_t c = 0; c < 4; c++)
330
{
331
pColors[1][c] = static_cast<uint8_t>((pColors[0][c] * 5 + pColors[3][c] * 3) / 8);
332
pColors[2][c] = static_cast<uint8_t>((pColors[0][c] * 3 + pColors[3][c] * 5) / 8);
333
}
334
335
return false;
336
}
337
338
color_rgba pvrtc4_image::get_pixel(uint32_t x, uint32_t y, uint32_t m) const
339
{
340
assert((x < m_width) && (y < m_height));
341
342
int block_x0 = (static_cast<int>(x) - 2) >> 2;
343
int block_x1 = block_x0 + 1;
344
int block_y0 = (static_cast<int>(y) - 2) >> 2;
345
int block_y1 = block_y0 + 1;
346
347
block_x0 = posmod(block_x0, m_block_width);
348
block_x1 = posmod(block_x1, m_block_width);
349
block_y0 = posmod(block_y0, m_block_height);
350
block_y1 = posmod(block_y1, m_block_height);
351
352
if (get_block_uses_transparent_modulation(x >> 2, y >> 2))
353
{
354
if (m == 0)
355
return interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0));
356
else if (m == 3)
357
return interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1));
358
359
color_rgba l(interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0)));
360
color_rgba h(interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1)));
361
362
return color_rgba((l[0] + h[0]) / 2, (l[1] + h[1]) / 2, (l[2] + h[2]) / 2, (m == 2) ? 0 : (l[3] + h[3]) / 2);
363
}
364
else
365
{
366
if (m == 0)
367
return interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0));
368
else if (m == 3)
369
return interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1));
370
371
color_rgba l(interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0)));
372
color_rgba h(interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1)));
373
374
if (m == 2)
375
return color_rgba((l[0] * 3 + h[0] * 5) / 8, (l[1] * 3 + h[1] * 5) / 8, (l[2] * 3 + h[2] * 5) / 8, (l[3] * 3 + h[3] * 5) / 8);
376
else
377
return color_rgba((l[0] * 5 + h[0] * 3) / 8, (l[1] * 5 + h[1] * 3) / 8, (l[2] * 5 + h[2] * 3) / 8, (l[3] * 5 + h[3] * 3) / 8);
378
}
379
}
380
381
uint64_t pvrtc4_image::local_endpoint_optimization_opaque(uint32_t bx, uint32_t by, const image& orig_img, bool perceptual)
382
{
383
uint64_t initial_error = evaluate_1x1_endpoint_error(bx, by, orig_img, perceptual, false);
384
if (!initial_error)
385
return initial_error;
386
387
vec3F c_avg_orig(0);
388
389
for (int y = 0; y < 7; y++)
390
{
391
const uint32_t py = wrap_y(by * 4 + y - 1);
392
for (uint32_t x = 0; x < 7; x++)
393
{
394
const uint32_t px = wrap_x(bx * 4 + x - 1);
395
396
const color_rgba& c = orig_img(px, py);
397
398
c_avg_orig[0] += c[0];
399
c_avg_orig[1] += c[1];
400
c_avg_orig[2] += c[2];
401
}
402
}
403
404
c_avg_orig *= 1.0f / 49.0f;
405
406
vec3F quant_colors[2];
407
quant_colors[0].set(c_avg_orig);
408
quant_colors[0] -= vec3F(.0125f);
409
410
quant_colors[1].set(c_avg_orig);
411
quant_colors[1] += vec3F(.0125f);
412
413
float total_weight[2];
414
415
bool success = true;
416
417
for (uint32_t pass = 0; pass < 4; pass++)
418
{
419
vec3F new_colors[2] = { vec3F(0), vec3F(0) };
420
memset(total_weight, 0, sizeof(total_weight));
421
422
static const float s_weights[7][7] =
423
{
424
{ 1.000000f, 1.637089f, 2.080362f, 2.242640f, 2.080362f, 1.637089f, 1.000000f },
425
{ 1.637089f, 2.414213f, 3.006572f, 3.242640f, 3.006572f, 2.414213f, 1.637089f },
426
{ 2.080362f, 3.006572f, 3.828426f, 4.242640f, 3.828426f, 3.006572f, 2.080362f },
427
{ 2.242640f, 3.242640f, 4.242640f, 5.000000f, 4.242640f, 3.242640f, 2.242640f },
428
{ 2.080362f, 3.006572f, 3.828426f, 4.242640f, 3.828426f, 3.006572f, 2.080362f },
429
{ 1.637089f, 2.414213f, 3.006572f, 3.242640f, 3.006572f, 2.414213f, 1.637089f },
430
{ 1.000000f, 1.637089f, 2.080362f, 2.242640f, 2.080362f, 1.637089f, 1.000000f }
431
};
432
433
for (int y = 0; y < 7; y++)
434
{
435
const uint32_t py = wrap_y(by * 4 + y - 1);
436
for (uint32_t x = 0; x < 7; x++)
437
{
438
const uint32_t px = wrap_x(bx * 4 + x - 1);
439
440
const color_rgba& orig_c = orig_img(px, py);
441
442
vec3F color(orig_c[0], orig_c[1], orig_c[2]);
443
444
uint32_t c = quant_colors[0].squared_distance(color) > quant_colors[1].squared_distance(color);
445
446
const float weight = s_weights[y][x];
447
new_colors[c] += color * weight;
448
449
total_weight[c] += weight;
450
}
451
}
452
453
if (!total_weight[0] || !total_weight[1])
454
success = false;
455
456
quant_colors[0] = new_colors[0] / (float)total_weight[0];
457
quant_colors[1] = new_colors[1] / (float)total_weight[1];
458
}
459
460
if (!success)
461
{
462
quant_colors[0] = c_avg_orig;
463
quant_colors[1] = c_avg_orig;
464
}
465
466
vec4F colors[2] = { quant_colors[0], quant_colors[1] };
467
468
colors[0] += vec3F(.5f);
469
colors[1] += vec3F(.5f);
470
color_rgba color_0((int)colors[0][0], (int)colors[0][1], (int)colors[0][2], 0);
471
color_rgba color_1((int)colors[1][0], (int)colors[1][1], (int)colors[1][2], 0);
472
473
pvrtc4_block cur_blocks[3][3];
474
475
for (int y = -1; y <= 1; y++)
476
{
477
for (int x = -1; x <= 1; x++)
478
{
479
const uint32_t block_x = wrap_block_x(bx + x);
480
const uint32_t block_y = wrap_block_y(by + y);
481
cur_blocks[x + 1][y + 1] = m_blocks(block_x, block_y);
482
}
483
}
484
485
color_rgba l1(0), h1(0);
486
487
l1[0] = g_pvrtc_5_nearest[color_0[0]];
488
h1[0] = g_pvrtc_5_nearest[color_1[0]];
489
490
l1[1] = g_pvrtc_5_nearest[color_0[1]];
491
h1[1] = g_pvrtc_5_nearest[color_1[1]];
492
493
l1[2] = g_pvrtc_4_nearest[color_0[2]];
494
h1[2] = g_pvrtc_5_nearest[color_0[2]];
495
496
l1[3] = 0;
497
h1[3] = 0;
498
499
m_blocks(bx, by).set_endpoint_raw(0, l1, true);
500
m_blocks(bx, by).set_endpoint_raw(1, h1, true);
501
502
uint64_t e03_err_0 = remap_pixels_influenced_by_endpoint(bx, by, orig_img, perceptual, false);
503
504
pvrtc4_block blocks0[3][3];
505
for (int y = -1; y <= 1; y++)
506
{
507
for (int x = -1; x <= 1; x++)
508
{
509
const uint32_t block_x = wrap_block_x(bx + x);
510
const uint32_t block_y = wrap_block_y(by + y);
511
blocks0[x + 1][y + 1] = m_blocks(block_x, block_y);
512
}
513
}
514
515
l1[0] = g_pvrtc_5_nearest[color_1[0]];
516
h1[0] = g_pvrtc_5_nearest[color_0[0]];
517
518
l1[1] = g_pvrtc_5_nearest[color_1[1]];
519
h1[1] = g_pvrtc_5_nearest[color_0[1]];
520
521
l1[2] = g_pvrtc_4_nearest[color_1[2]];
522
h1[2] = g_pvrtc_5_nearest[color_0[2]];
523
524
l1[3] = 0;
525
h1[3] = 0;
526
527
m_blocks(bx, by).set_endpoint_raw(0, l1, true);
528
m_blocks(bx, by).set_endpoint_raw(1, h1, true);
529
530
uint64_t e03_err_1 = remap_pixels_influenced_by_endpoint(bx, by, orig_img, perceptual, false);
531
532
if (initial_error < basisu::minimum(e03_err_0, e03_err_1))
533
{
534
for (int y = -1; y <= 1; y++)
535
{
536
for (int x = -1; x <= 1; x++)
537
{
538
const uint32_t block_x = wrap_block_x(bx + x);
539
const uint32_t block_y = wrap_block_y(by + y);
540
m_blocks(block_x, block_y) = cur_blocks[x + 1][y + 1];
541
}
542
}
543
return initial_error;
544
}
545
else if (e03_err_0 < e03_err_1)
546
{
547
for (int y = -1; y <= 1; y++)
548
{
549
for (int x = -1; x <= 1; x++)
550
{
551
const uint32_t block_x = wrap_block_x(bx + x);
552
const uint32_t block_y = wrap_block_y(by + y);
553
m_blocks(block_x, block_y) = blocks0[x + 1][y + 1];
554
}
555
}
556
assert(e03_err_0 == evaluate_1x1_endpoint_error(bx, by, orig_img, perceptual, false));
557
return e03_err_0;
558
}
559
560
assert(e03_err_1 == evaluate_1x1_endpoint_error(bx, by, orig_img, perceptual, false));
561
return e03_err_1;
562
}
563
564
} // basisu
565
566