xoreos  0.0.5
s3tc.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include "src/common/util.h"
26 #include "src/common/readstream.h"
27 
29 
30 namespace Graphics {
31 
32 static inline uint32 convert565To8888(uint16 color) {
33  return ((color & 0x1F) << 11) | ((color & 0x7E0) << 13) | ((color & 0xF800) << 16) | 0xFF;
34 }
35 
36 static inline uint32 interpolate32(double weight, uint32 color_0, uint32 color_1) {
37  byte r[3], g[3], b[3], a[3];
38  r[0] = color_0 >> 24;
39  r[1] = color_1 >> 24;
40  r[2] = (byte)((1.0f - weight) * (double)r[0] + weight * (double)r[1]);
41  g[0] = (color_0 >> 16) & 0xFF;
42  g[1] = (color_1 >> 16) & 0xFF;
43  g[2] = (byte)((1.0f - weight) * (double)g[0] + weight * (double)g[1]);
44  b[0] = (color_0 >> 8) & 0xFF;
45  b[1] = (color_1 >> 8) & 0xFF;
46  b[2] = (byte)((1.0f - weight) * (double)b[0] + weight * (double)b[1]);
47  a[0] = color_0 & 0xFF;
48  a[1] = color_1 & 0xFF;
49  a[2] = (byte)((1.0f - weight) * (double)a[0] + weight * (double)a[1]);
50  return r[2] << 24 | g[2] << 16 | b[2] << 8 | a[2];
51 }
52 
53 struct DXT1Texel {
57 };
58 
59 #define READ_DXT1_TEXEL(x) \
60  x.color_0 = src.readUint16LE(); \
61  x.color_1 = src.readUint16LE(); \
62  x.pixels = src.readUint32BE()
63 
64 void decompressDXT1(byte *dest, Common::SeekableReadStream &src, uint32 width, uint32 height, uint32 pitch) {
65  for (int32 ty = height; ty > 0; ty -= 4) {
66  for (uint32 tx = 0; tx < width; tx += 4) {
67  DXT1Texel tex;
68  READ_DXT1_TEXEL(tex);
69  uint32 blended[4];
70 
71  blended[0] = convert565To8888(tex.color_0);
72  blended[1] = convert565To8888(tex.color_1);
73 
74  if (tex.color_0 > tex.color_1) {
75  blended[2] = interpolate32(0.333333f, blended[0], blended[1]);
76  blended[3] = interpolate32(0.666666f, blended[0], blended[1]);
77  } else {
78  blended[2] = interpolate32(0.5f, blended[0], blended[1]);
79  blended[3] = 0;
80  }
81 
82  uint32 cpx = tex.pixels;
83  uint32 blockWidth = MIN<uint32>(width, 4);
84  uint32 blockHeight = MIN<uint32>(height, 4);
85 
86  for (byte y = 0; y < blockHeight; ++y) {
87  for (byte x = 0; x < blockWidth; ++x) {
88  const uint32 destX = tx + x;
89  const uint32 destY = height - 1 - (ty - blockHeight + y);
90 
91  const uint32 pixel = blended[cpx & 3];
92 
93  cpx >>= 2;
94 
95  if ((destX < width) && (destY < height))
96  WRITE_BE_UINT32(dest + destY * pitch + destX * 4, pixel);
97  }
98  }
99  }
100  }
101 }
102 
103 struct DXT23Texel : public DXT1Texel {
105 };
106 
107 #define READ_DXT3_TEXEL(x) \
108  x.alpha[0] = src.readUint16LE(); \
109  x.alpha[1] = src.readUint16LE(); \
110  x.alpha[2] = src.readUint16LE(); \
111  x.alpha[3] = src.readUint16LE(); \
112  READ_DXT1_TEXEL(x)
113 
114 void decompressDXT3(byte *dest, Common::SeekableReadStream &src, uint32 width, uint32 height, uint32 pitch) {
115  for (int32 ty = height; ty > 0; ty -= 4) {
116  for (uint32 tx = 0; tx < width; tx += 4) {
117  DXT23Texel tex;
118  uint32 blended[4];
119  READ_DXT3_TEXEL(tex);
120 
121  blended[0] = convert565To8888(tex.color_0) & 0xFFFFFF00;
122  blended[1] = convert565To8888(tex.color_1) & 0xFFFFFF00;
123  blended[2] = interpolate32(0.333333f, blended[0], blended[1]);
124  blended[3] = interpolate32(0.666666f, blended[0], blended[1]);
125 
126  uint32 cpx = tex.pixels;
127  uint32 blockWidth = MIN<uint32>(width, 4);
128  uint32 blockHeight = MIN<uint32>(height, 4);
129 
130  for (byte y = 0; y < blockHeight; ++y) {
131  for (byte x = 0; x < blockWidth; ++x) {
132  const uint32 destX = tx + x;
133  const uint32 destY = height - 1 - (ty - blockHeight + y);
134 
135  const uint32 alpha = (tex.alpha[y] >> (x * 4)) & 0xF;
136  const uint32 pixel = blended[cpx & 3] | alpha << 4;
137 
138  cpx >>= 2;
139 
140  if ((destX < width) && (destY < height))
141  WRITE_BE_UINT32(dest + destY * pitch + destX * 4, pixel);
142  }
143  }
144  }
145  }
146 }
147 
148 struct DXT45Texel : public DXT1Texel {
152 };
153 
155  uint64 output = src.readUint32LE();
156  return output | ((uint64)src.readUint16LE() << 32);
157 }
158 
159 #define READ_DXT5_TEXEL(x) \
160  x.alpha_0 = src.readByte(); \
161  x.alpha_1 = src.readByte(); \
162  x.alphabl = readUint48LE(src); \
163  READ_DXT1_TEXEL(x)
164 
165 void decompressDXT5(byte *dest, Common::SeekableReadStream &src, uint32 width, uint32 height, uint32 pitch) {
166  for (int32 ty = height; ty > 0; ty -= 4) {
167  for (uint32 tx = 0; tx < width; tx += 4) {
168  uint32 blended[4];
169  byte alphab[8];
170  DXT45Texel tex;
171  READ_DXT5_TEXEL(tex);
172 
173  alphab[0] = tex.alpha_0;
174  alphab[1] = tex.alpha_1;
175 
176  if (tex.alpha_0 > tex.alpha_1) {
177  alphab[2] = (byte)((6.0f * (double)alphab[0] + 1.0f * (double)alphab[1] + 3.0f) / 7.0f);
178  alphab[3] = (byte)((5.0f * (double)alphab[0] + 2.0f * (double)alphab[1] + 3.0f) / 7.0f);
179  alphab[4] = (byte)((4.0f * (double)alphab[0] + 3.0f * (double)alphab[1] + 3.0f) / 7.0f);
180  alphab[5] = (byte)((3.0f * (double)alphab[0] + 4.0f * (double)alphab[1] + 3.0f) / 7.0f);
181  alphab[6] = (byte)((2.0f * (double)alphab[0] + 5.0f * (double)alphab[1] + 3.0f) / 7.0f);
182  alphab[7] = (byte)((1.0f * (double)alphab[0] + 6.0f * (double)alphab[1] + 3.0f) / 7.0f);
183  } else {
184  alphab[2] = (byte)((4.0f * (double)alphab[0] + 1.0f * (double)alphab[1] + 2.0f) / 5.0f);
185  alphab[3] = (byte)((3.0f * (double)alphab[0] + 2.0f * (double)alphab[1] + 2.0f) / 5.0f);
186  alphab[4] = (byte)((2.0f * (double)alphab[0] + 3.0f * (double)alphab[1] + 2.0f) / 5.0f);
187  alphab[5] = (byte)((1.0f * (double)alphab[0] + 4.0f * (double)alphab[1] + 2.0f) / 5.0f);
188  alphab[6] = 0;
189  alphab[7] = 255;
190  }
191 
192  blended[0] = convert565To8888(tex.color_0) & 0xFFFFFF00;
193  blended[1] = convert565To8888(tex.color_1) & 0xFFFFFF00;
194  blended[2] = interpolate32(0.333333f, blended[0], blended[1]);
195  blended[3] = interpolate32(0.666666f, blended[0], blended[1]);
196 
197  uint32 cpx = tex.pixels;
198  uint32 blockWidth = MIN<uint32>(width, 4);
199  uint32 blockHeight = MIN<uint32>(height, 4);
200 
201  for (byte y = 0; y < blockHeight; ++y) {
202  for (byte x = 0; x < blockWidth; ++x) {
203  const uint32 destX = tx + x;
204  const uint32 destY = height - 1 - (ty - blockHeight + y);
205 
206  const uint32 alpha = alphab[(tex.alphabl >> (3 * (4 * (3 - y) + x))) & 7];
207  const uint32 pixel = blended[cpx & 3] | alpha;
208 
209  cpx >>= 2;
210 
211  if ((destX < width) && (destY < height))
212  WRITE_BE_UINT32(dest + destY * pitch + destX * 4, pixel);
213  }
214  }
215  }
216  }
217 }
218 
219 } // End of namespace Graphics
uint16 readUint16LE()
Read an unsigned 16-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:122
static uint32 interpolate32(double weight, uint32 color_0, uint32 color_1)
Definition: s3tc.cpp:36
uint32 readUint32LE()
Read an unsigned 32-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:133
#define READ_DXT3_TEXEL(x)
Definition: s3tc.cpp:107
uint64_t uint64
Definition: types.h:206
uint16 color_1
Definition: s3tc.cpp:55
uint16 alpha[4]
Definition: s3tc.cpp:104
uint16 color_0
Definition: s3tc.cpp:54
void decompressDXT3(byte *dest, Common::SeekableReadStream &src, uint32 width, uint32 height, uint32 pitch)
Definition: s3tc.cpp:114
uint16_t uint16
Definition: types.h:202
Utility templates and functions.
void decompressDXT1(byte *dest, Common::SeekableReadStream &src, uint32 width, uint32 height, uint32 pitch)
Definition: s3tc.cpp:64
void decompressDXT5(byte *dest, Common::SeekableReadStream &src, uint32 width, uint32 height, uint32 pitch)
Definition: s3tc.cpp:165
static uint32 convert565To8888(uint16 color)
Definition: s3tc.cpp:32
Basic reading stream interfaces.
static uint64 readUint48LE(Common::SeekableReadStream &src)
Definition: s3tc.cpp:154
Manual S3TC DXTn decompression methods.
uint32_t uint32
Definition: types.h:204
Interface for a seekable & readable data stream.
Definition: readstream.h:265
#define READ_DXT1_TEXEL(x)
Definition: s3tc.cpp:59
uint8 byte
Definition: types.h:209
#define READ_DXT5_TEXEL(x)
Definition: s3tc.cpp:159
int32_t int32
Definition: types.h:203