Parent Directory
|
Revision Log
Release 2.0.2 tag
1 /* 2 DDS GIMP plugin 3 4 Copyright (C) 2004 Shawn Kirst <skirst@fuse.net>, 5 with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> where specified. 6 7 This program is free software; you can redistribute it and/or 8 modify it under the terms of the GNU General Public 9 License as published by the Free Software Foundation; either 10 version 2 of the License, or (at your option) any later version. 11 12 This program 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 GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; see the file COPYING. If not, write to 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. 21 */ 22 23 /* 24 * Parts of this code have been generously released in the public domain 25 * by 'Ryg'. The original code can be found (at the time of writing) 26 * here: https://mollyrocket.com/forums/viewtopic.php?t=392 27 */ 28 29 #include <stdlib.h> 30 #include <string.h> 31 #include <math.h> 32 #include <glib.h> 33 34 #include "dds.h" 35 #include "endian.h" 36 #include "mipmap.h" 37 38 #include "dxt_tables.h" 39 40 #ifndef MIN 41 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 42 #endif 43 #ifndef MAX 44 #define MAX(a, b) ((a) > (b) ? (a) : (b)) 45 #endif 46 47 /* extract 4x4 BGRA block */ 48 static void extract_block(const unsigned char *src, int w, 49 unsigned char *block) 50 { 51 int i; 52 for(i = 0; i < 4; ++i) 53 { 54 memcpy(&block[i * 4 * 4], src, 4 * 4); 55 src += w * 4; 56 } 57 } 58 59 static inline int mul8bit(int a, int b) 60 { 61 int t = a * b + 128; 62 return((t + (t >> 8)) >> 8); 63 } 64 65 /* pack BGR8 to RGB565 */ 66 static inline unsigned short pack_rgb565(const unsigned char *c) 67 { 68 return(((c[2] >> 3) << 11) | ((c[1] >> 2) << 5) | (c[0] >> 3)); 69 } 70 71 /* unpack RGB565 to BGR */ 72 static void unpack_rgb565(unsigned char *dst, unsigned short v) 73 { 74 int r = (v >> 11) & 0x1f; 75 int g = (v >> 5) & 0x3f; 76 int b = (v ) & 0x1f; 77 78 dst[0] = (b << 3) | (b >> 2); 79 dst[1] = (g << 2) | (g >> 4); 80 dst[2] = (r << 3) | (r >> 2); 81 } 82 83 static void lerp_rgb(unsigned char *dst, unsigned char *a, unsigned char *b, int f) 84 { 85 dst[0] = a[0] + mul8bit(b[0] - a[0], f); 86 dst[1] = a[1] + mul8bit(b[1] - a[1], f); 87 dst[2] = a[2] + mul8bit(b[2] - a[2], f); 88 } 89 90 static int color_distance(const unsigned char *c0, 91 const unsigned char *c1) 92 { 93 return(((c0[0] - c1[0]) * (c0[0] - c1[0])) + 94 ((c0[1] - c1[1]) * (c0[1] - c1[1])) + 95 ((c0[2] - c1[2]) * (c0[2] - c1[2]))); 96 } 97 98 static int luminance(const unsigned char *c) 99 { 100 return((c[2] * 54 + c[1] * 182 + c[0] * 20) >> 8); 101 } 102 103 static void dither_block(unsigned char *dst, const unsigned char *block) 104 { 105 int err[8], *ep1 = err, *ep2 = err + 4, *tmp; 106 int c, y; 107 unsigned char *bp, *dp; 108 const unsigned char *quant; 109 110 for(c = 0; c < 3; ++c) 111 { 112 bp = (unsigned char *)block; 113 dp = dst; 114 quant = (c == 1) ? quantG + 8 : quantRB + 8; 115 116 bp += c; 117 dp += c; 118 119 memset(err, 0, sizeof(err)); 120 121 for(y = 0; y < 4; ++y) 122 { 123 dp[ 0] = quant[bp[ 0] + ((3 * ep2[1] + 5 * ep2[0]) >> 4)]; 124 ep1[0] = bp[ 0] - dp[ 0]; 125 126 dp[ 4] = quant[bp[ 4] + ((7 * ep1[0] + 3 * ep2[2] + 5 * ep2[1] + ep2[0]) >> 4)]; 127 ep1[1] = bp[ 4] - dp[ 4]; 128 129 dp[ 8] = quant[bp[ 8] + ((7 * ep1[1] + 3 * ep2[3] + 5 * ep2[2] + ep2[1]) >> 4)]; 130 ep1[2] = bp[ 8] - dp[ 8]; 131 132 dp[12] = quant[bp[12] + ((7 * ep1[2] + 5 * ep2[3] + ep2[2]) >> 4)]; 133 ep1[3] = bp[12] - dp[12]; 134 135 tmp = ep1; 136 ep1 = ep2; 137 ep2 = tmp; 138 139 bp += 16; 140 dp += 16; 141 } 142 } 143 } 144 145 static unsigned int match_colors_block(const unsigned char *block, 146 unsigned char color[4][3], 147 int dither) 148 { 149 unsigned int mask = 0; 150 int dirb = color[0][0] - color[1][0]; 151 int dirg = color[0][1] - color[1][1]; 152 int dirr = color[0][2] - color[1][2]; 153 int dots[16], stops[4]; 154 int c0pt, halfpt, c3pt, dot; 155 int i; 156 157 for(i = 0; i < 16; ++i) 158 dots[i] = block[4 * i] * dirb + block[4 * i + 1] * dirg + block[4 * i + 2] * dirr; 159 160 for(i = 0; i < 4; ++i) 161 stops[i] = color[i][0] * dirb + color[i][1] * dirg + color[i][2] * dirr; 162 163 c0pt = (stops[1] + stops[3]) >> 1; 164 halfpt = (stops[3] + stops[2]) >> 1; 165 c3pt = (stops[2] + stops[0]) >> 1; 166 167 if(!dither) 168 { 169 for(i = 15; i >= 0; --i) 170 { 171 mask <<= 2; 172 dot = dots[i]; 173 174 if(dot < halfpt) 175 mask |= (dot < c0pt) ? 1 : 3; 176 else 177 mask |= (dot < c3pt) ? 2 : 0; 178 } 179 } 180 else 181 { 182 int err[8], *ep1 = err, *ep2 = err + 4, *tmp; 183 int *dp = dots, y, lmask, step; 184 185 c0pt <<= 4; 186 halfpt <<= 4; 187 c3pt <<= 4; 188 189 memset(err, 0, sizeof(err)); 190 191 for(y = 0; y < 4; ++y) 192 { 193 dot = (dp[0] << 4) + (3 * ep2[1] + 5 * ep2[0]); 194 if(dot < halfpt) 195 step = (dot < c0pt) ? 1 : 3; 196 else 197 step = (dot < c3pt) ? 2 : 0; 198 199 ep1[0] = dp[0] - stops[step]; 200 lmask = step; 201 202 dot = (dp[1] << 4) + (7 * ep1[0] + 3 * ep2[2] + 5 * ep2[1] + ep2[0]); 203 if(dot < halfpt) 204 step = (dot < c0pt) ? 1 : 3; 205 else 206 step = (dot < c3pt) ? 2 : 0; 207 208 ep1[1] = dp[1] - stops[step]; 209 lmask |= step << 2; 210 211 dot = (dp[2] << 4) + (7 * ep1[1] + 3 * ep2[3] + 5 * ep2[2] + ep2[1]); 212 if(dot < halfpt) 213 step = (dot < c0pt) ? 1 : 3; 214 else 215 step = (dot < c3pt) ? 2 : 0; 216 217 ep1[2] = dp[2] - stops[step]; 218 lmask |= step << 4; 219 220 dot = (dp[3] << 4) + (7 * ep1[2] + 5 * ep2[3] + ep2[2]); 221 if(dot < halfpt) 222 step = (dot < c0pt) ? 1 : 3; 223 else 224 step = (dot < c3pt) ? 2 : 0; 225 226 ep1[3] = dp[3] - stops[step]; 227 lmask |= step << 6; 228 229 tmp = ep1; 230 ep1 = ep2; 231 ep2 = tmp; 232 233 dp += 4; 234 mask |= lmask << (y * 8); 235 } 236 } 237 238 return(mask); 239 } 240 241 static unsigned int match_colors_block_DXT1alpha(const unsigned char *block, 242 unsigned char color[4][3]) 243 { 244 int i, d0, d1, d2, idx; 245 unsigned int mask = 0; 246 247 for(i = 15; i >= 0; --i) 248 { 249 mask <<= 2; 250 d0 = color_distance(&block[4 * i], color[0]); 251 d1 = color_distance(&block[4 * i], color[1]); 252 d2 = color_distance(&block[4 * i], color[2]); 253 if(block[4 * i + 3] < 128) 254 idx = 3; 255 else if(d0 < d1 && d0 < d2) 256 idx = 0; 257 else if(d1 < d2) 258 idx = 1; 259 else 260 idx = 2; 261 mask |= idx; 262 } 263 264 return(mask); 265 } 266 267 static void optimize_colors_block(const unsigned char *block, 268 unsigned short *max16, unsigned short *min16) 269 { 270 static const int niterpow = 4; 271 272 int mu[3], mn[3], mx[3]; 273 int i, c, r, g, b, dot, iter; 274 int muv, mnv, mxv, mnd, mxd; 275 int cov[6]; 276 unsigned char *bp, mnc[3], mxc[3]; 277 float covf[6], vfr, vfg, vfb, magn; 278 float fr, fg, fb; 279 280 for(c = 0; c < 3; ++c) 281 { 282 bp = (unsigned char *)block + c; 283 284 muv = mnv = mxv = bp[0]; 285 for(i = 4; i < 64; i += 4) 286 { 287 muv += bp[i]; 288 if(mnv > bp[i]) mnv = bp[i]; 289 if(mxv < bp[i]) mxv = bp[i]; 290 } 291 292 mu[c] = (muv + 8) >> 4; 293 mn[c] = mnv; 294 mx[c] = mxv; 295 } 296 297 memset(cov, 0, sizeof(cov)); 298 299 for(i = 0; i < 16; ++i) 300 { 301 b = block[4 * i + 0] - mu[0]; 302 g = block[4 * i + 1] - mu[1]; 303 r = block[4 * i + 2] - mu[2]; 304 305 cov[0] += r * r; 306 cov[1] += r * g; 307 cov[2] += r * b; 308 cov[3] += g * g; 309 cov[4] += g * b; 310 cov[5] += b * b; 311 } 312 313 for(i = 0; i < 6; ++i) 314 covf[i] = cov[i] / 255.0f; 315 316 vfb = mx[0] - mn[0]; 317 vfg = mx[1] - mn[1]; 318 vfr = mx[2] - mn[2]; 319 320 for(iter = 0; iter < niterpow; ++iter) 321 { 322 fr = vfr * covf[0] + vfg * covf[1] + vfb * covf[2]; 323 fg = vfr * covf[1] + vfg * covf[3] + vfb * covf[4]; 324 fb = vfr * covf[2] + vfg * covf[4] + vfb * covf[5]; 325 326 vfr = fr; 327 vfg = fg; 328 vfb = fb; 329 } 330 331 vfr = fabsf(vfr); 332 vfg = fabsf(vfg); 333 vfb = fabsf(vfb); 334 335 magn = MAX(MAX(vfr, vfg), vfb); 336 337 if(magn < 4.0) 338 { 339 r = 148; 340 g = 300; 341 b = 58; 342 } 343 else 344 { 345 magn = 512.0f / magn; 346 r = (int)(vfr * magn); 347 g = (int)(vfg * magn); 348 b = (int)(vfb * magn); 349 } 350 351 mnd = 0x7fffffff; 352 mxd = -0x7fffffff; 353 354 for(i = 0; i < 16; ++i) 355 { 356 dot = block[4 * i] * b + block[4 * i + 1] * g + block[4 * i + 2] * r; 357 358 if(dot < mnd) 359 { 360 mnd = dot; 361 memcpy(mnc, &block[4 * i], 3); 362 } 363 if(dot > mxd) 364 { 365 mxd = dot; 366 memcpy(mxc, &block[4 * i], 3); 367 } 368 } 369 370 *max16 = pack_rgb565(mxc); 371 *min16 = pack_rgb565(mnc); 372 } 373 374 static int refine_block(const unsigned char *block, 375 unsigned short *max16, unsigned short *min16, 376 unsigned int mask) 377 { 378 static const int w1tab[4] = {3, 0, 2, 1}; 379 static const int prods[4] = {0x090000, 0x000900, 0x040102, 0x010402}; 380 int akku = 0; 381 int At1_r, At1_g, At1_b; 382 int At2_r, At2_g, At2_b; 383 unsigned int cm = mask; 384 int i, step, w1, r, g, b; 385 int xx, yy, xy; 386 float frb, fg; 387 unsigned short v, oldmin, oldmax; 388 int s; 389 390 At1_r = At1_g = At1_b = 0; 391 At2_r = At2_g = At2_b = 0; 392 393 for(i = 0; i < 16; ++i, cm >>= 2) 394 { 395 step = cm & 3; 396 w1 = w1tab[step]; 397 r = block[4 * i + 2]; 398 g = block[4 * i + 1]; 399 b = block[4 * i + 0]; 400 401 akku += prods[step]; 402 At1_r += w1 * r; 403 At1_g += w1 * g; 404 At1_b += w1 * b; 405 At2_r += r; 406 At2_g += g; 407 At2_b += b; 408 } 409 410 At2_r = 3 * At2_r - At1_r; 411 At2_g = 3 * At2_g - At1_g; 412 At2_b = 3 * At2_b - At1_b; 413 414 xx = akku >> 16; 415 yy = (akku >> 8) & 0xff; 416 xy = (akku >> 0) & 0xff; 417 418 if(!yy || !xx || xx * yy == xy * xy) 419 return(0); 420 421 frb = 3.0f * 31.0f / 255.0f / (xx * yy - xy * xy); 422 fg = frb * 63.0f / 31.0f; 423 424 oldmin = *min16; 425 oldmax = *max16; 426 427 s = (int)((At1_r * yy - At2_r * xy) * frb + 0.5f); 428 if(s < 0) s = 0; 429 if(s > 31) s = 31; 430 v = s << 11; 431 s = (int)((At1_g * yy - At2_g * xy) * fg + 0.5f); 432 if(s < 0) s = 0; 433 if(s > 63) s = 63; 434 v |= s << 5; 435 s = (int)((At1_b * yy - At2_b * xy) * frb + 0.5f); 436 if(s < 0) s = 0; 437 if(s > 31) s = 31; 438 v |= s; 439 *max16 = v; 440 441 s = (int)((At2_r * xx - At1_r * xy) * frb + 0.5f); 442 if(s < 0) s = 0; 443 if(s > 31) s = 31; 444 v = s << 11; 445 s = (int)((At2_g * xx - At1_g * xy) * fg + 0.5f); 446 if(s < 0) s = 0; 447 if(s > 63) s = 63; 448 v |= s << 5; 449 s = (int)((At2_b * xx - At1_b * xy) * frb + 0.5f); 450 if(s < 0) s = 0; 451 if(s > 31) s = 31; 452 v |= s; 453 *min16 = v; 454 455 return(oldmin != *min16 || oldmax != *max16); 456 } 457 458 static void get_min_max_colors_distance(const unsigned char *block, 459 unsigned short *max16, 460 unsigned short *min16) 461 { 462 int i, j, dist, maxdist = -1; 463 unsigned short c0 = 0, c1 = 0; 464 465 for(i = 0; i < 64 - 4; i += 4) 466 { 467 for(j = i + 4; j < 64; j += 4) 468 { 469 dist = color_distance(&block[i], &block[j]); 470 if(dist > maxdist) 471 { 472 maxdist = dist; 473 c0 = pack_rgb565(block + i); 474 c1 = pack_rgb565(block + j); 475 } 476 } 477 } 478 479 *max16 = MAX(c0, c1); 480 *min16 = MIN(c0, c1); 481 } 482 483 static void get_min_max_colors_luminance(const unsigned char *block, 484 unsigned short *max16, 485 unsigned short *min16) 486 { 487 int i, lum, minlum = 0x7fffffff, maxlum = -0x7fffffff; 488 unsigned char mn[3], mx[3]; 489 490 for(i = 0; i < 16; ++i) 491 { 492 lum = luminance(&block[4 * i]); 493 if(lum > maxlum) 494 { 495 maxlum = lum; 496 memcpy(mx, &block[4 * i], 3); 497 } 498 if(lum < minlum) 499 { 500 minlum = lum; 501 memcpy(mn, &block[4 * i], 3); 502 } 503 } 504 505 *max16 = pack_rgb565(mx); 506 *min16 = pack_rgb565(mn); 507 } 508 509 #define INSET_SHIFT 4 510 511 static void get_min_max_colors_inset_bbox(const unsigned char *block, 512 unsigned short *max16, 513 unsigned short *min16) 514 { 515 int i; 516 unsigned char inset[3], mx[3], mn[3]; 517 518 mn[0] = mn[1] = mn[2] = 255; 519 mx[0] = mx[1] = mx[2] = 0; 520 521 for(i = 0; i < 16; ++i) 522 { 523 if(block[4 * i + 0] < mn[0]) mn[0] = block[4 * i + 0]; 524 if(block[4 * i + 1] < mn[1]) mn[1] = block[4 * i + 1]; 525 if(block[4 * i + 2] < mn[2]) mn[2] = block[4 * i + 2]; 526 if(block[4 * i + 0] > mx[0]) mx[0] = block[4 * i + 0]; 527 if(block[4 * i + 1] > mx[1]) mx[1] = block[4 * i + 1]; 528 if(block[4 * i + 2] > mx[2]) mx[2] = block[4 * i + 2]; 529 } 530 531 inset[0] = (mx[0] - mn[0]) >> INSET_SHIFT; 532 inset[1] = (mx[1] - mn[1]) >> INSET_SHIFT; 533 inset[2] = (mx[2] - mn[2]) >> INSET_SHIFT; 534 535 mn[0] = (mn[0] + inset[0] <= 255) ? mn[0] + inset[0] : 255; 536 mn[1] = (mn[1] + inset[1] <= 255) ? mn[1] + inset[1] : 255; 537 mn[2] = (mn[2] + inset[2] <= 255) ? mn[2] + inset[2] : 255; 538 539 mx[0] = (mx[0] >= inset[0]) ? mx[0] - inset[0] : 0; 540 mx[1] = (mx[1] >= inset[1]) ? mx[1] - inset[1] : 0; 541 mx[2] = (mx[2] >= inset[2]) ? mx[2] - inset[2] : 0; 542 543 *min16 = pack_rgb565(mn); 544 *max16 = pack_rgb565(mx); 545 } 546 547 static void get_min_max_YCoCg(const unsigned char *block, 548 unsigned char *mincolor, unsigned char *maxcolor) 549 { 550 int i; 551 552 mincolor[2] = mincolor[1] = 255; 553 maxcolor[2] = maxcolor[1] = 0; 554 555 for(i = 0; i < 16; ++i) 556 { 557 if(block[4 * i + 2] < mincolor[2]) mincolor[2] = block[4 * i + 2]; 558 if(block[4 * i + 1] < mincolor[1]) mincolor[1] = block[4 * i + 1]; 559 if(block[4 * i + 2] > maxcolor[2]) maxcolor[2] = block[4 * i + 2]; 560 if(block[4 * i + 1] > maxcolor[1]) maxcolor[1] = block[4 * i + 1]; 561 } 562 } 563 564 static void scale_YCoCg(unsigned char *block, 565 unsigned char *mincolor, unsigned char *maxcolor) 566 { 567 const int s0 = 128 / 2 - 1; 568 const int s1 = 128 / 4 - 1; 569 int m0, m1, m2, m3; 570 int mask0, mask1, scale; 571 int i; 572 573 m0 = abs(mincolor[2] - 128); 574 m1 = abs(mincolor[1] - 128); 575 m2 = abs(maxcolor[2] - 128); 576 m3 = abs(maxcolor[1] - 128); 577 578 if(m1 > m0) m0 = m1; 579 if(m3 > m2) m2 = m3; 580 if(m2 > m0) m0 = m2; 581 582 mask0 = -(m0 <= s0); 583 mask1 = -(m0 <= s1); 584 scale = 1 + (1 & mask0) + (2 & mask1); 585 586 mincolor[2] = (mincolor[2] - 128) * scale + 128; 587 mincolor[1] = (mincolor[1] - 128) * scale + 128; 588 mincolor[0] = (scale - 1) << 3; 589 590 maxcolor[2] = (maxcolor[2] - 128) * scale + 128; 591 maxcolor[1] = (maxcolor[1] - 128) * scale + 128; 592 maxcolor[0] = (scale - 1) << 3; 593 594 for(i = 0; i < 16; ++i) 595 { 596 block[i * 4 + 2] = (block[i * 4 + 2] - 128) * scale + 128; 597 block[i * 4 + 1] = (block[i * 4 + 1] - 128) * scale + 128; 598 } 599 } 600 601 static void inset_bbox_YCoCg(unsigned char *mincolor, unsigned char *maxcolor) 602 { 603 int inset[4], mini[4], maxi[4]; 604 605 inset[2] = (maxcolor[2] - mincolor[2]) - ((1 << (INSET_SHIFT - 1)) - 1); 606 inset[1] = (maxcolor[1] - mincolor[1]) - ((1 << (INSET_SHIFT - 1)) - 1); 607 608 mini[2] = ((mincolor[2] << INSET_SHIFT) + inset[2]) >> INSET_SHIFT; 609 mini[1] = ((mincolor[1] << INSET_SHIFT) + inset[1]) >> INSET_SHIFT; 610 611 maxi[2] = ((maxcolor[2] << INSET_SHIFT) - inset[2]) >> INSET_SHIFT; 612 maxi[1] = ((maxcolor[1] << INSET_SHIFT) - inset[1]) >> INSET_SHIFT; 613 614 mini[2] = (mini[2] >= 0) ? mini[2] : 0; 615 mini[1] = (mini[1] >= 0) ? mini[1] : 0; 616 617 maxi[2] = (maxi[2] <= 255) ? maxi[2] : 255; 618 maxi[1] = (maxi[1] <= 255) ? maxi[1] : 255; 619 620 mincolor[2] = (mini[2] & 0xf8) | (mini[2] >> 5); 621 mincolor[1] = (mini[1] & 0xfc) | (mini[1] >> 6); 622 623 maxcolor[2] = (maxi[2] & 0xf8) | (maxi[2] >> 5); 624 maxcolor[1] = (maxi[1] & 0xfc) | (maxi[1] >> 6); 625 } 626 627 static void select_diagonal_YCoCg(const unsigned char *block, 628 unsigned char *mincolor, 629 unsigned char *maxcolor) 630 { 631 unsigned char mid0, mid1, side, mask, b0, b1, c0, c1; 632 int i; 633 634 mid0 = ((int)mincolor[2] + maxcolor[2] + 1) >> 1; 635 mid1 = ((int)mincolor[1] + maxcolor[1] + 1) >> 1; 636 637 side = 0; 638 for(i = 0; i < 16; ++i) 639 { 640 b0 = block[i * 4 + 2] >= mid0; 641 b1 = block[i * 4 + 1] >= mid1; 642 side += (b0 ^ b1); 643 } 644 645 mask = -(side > 8); 646 mask &= -(mincolor[2] != maxcolor[2]); 647 648 c0 = mincolor[1]; 649 c1 = maxcolor[1]; 650 651 c0 ^= c1; 652 mask &= c0; 653 c1 ^= mask; 654 c0 ^= c1; 655 656 mincolor[1] = c0; 657 maxcolor[1] = c1; 658 } 659 660 static void eval_colors(unsigned char color[4][3], 661 unsigned short c0, unsigned short c1) 662 { 663 unpack_rgb565(color[0], c0); 664 unpack_rgb565(color[1], c1); 665 if(c0 > c1) 666 { 667 lerp_rgb(color[2], color[0], color[1], 0x55); 668 lerp_rgb(color[3], color[0], color[1], 0xaa); 669 } 670 else 671 { 672 color[2][0] = (color[0][0] + color[1][0]) >> 1; 673 color[2][1] = (color[0][1] + color[1][1]) >> 1; 674 color[2][2] = (color[0][2] + color[1][2]) >> 1; 675 676 color[3][0] = color[3][1] = color[3][2] = 0; 677 } 678 } 679 680 static void encode_color_block(unsigned char *dst, 681 const unsigned char *block, 682 int type, int dither, int dxt1_alpha) 683 { 684 unsigned char dblock[64], color[4][3]; 685 unsigned short min16, max16; 686 unsigned int v, mn, mx, mask; 687 int i, block_has_alpha = 0; 688 689 mn = mx = GETL32(block); 690 for(i = 0; i < 16; ++i) 691 { 692 block_has_alpha = block_has_alpha || (block[4 * i + 3] < 255); 693 v = GETL32(&block[4 * i]); 694 if(v > mx) mx = v; 695 if(v < mn) mn = v; 696 } 697 698 if(mn != mx) 699 { 700 if(dither) 701 dither_block(dblock, block); 702 703 switch(type) 704 { 705 case DDS_COLOR_DISTANCE: 706 get_min_max_colors_distance(dither ? dblock : block, &max16, &min16); 707 break; 708 case DDS_COLOR_LUMINANCE: 709 get_min_max_colors_luminance(dither ? dblock : block, &max16, &min16); 710 break; 711 case DDS_COLOR_INSET_BBOX: 712 get_min_max_colors_inset_bbox(dither ? dblock : block, &max16, &min16); 713 break; 714 default: 715 optimize_colors_block(dither ? dblock : block, &max16, &min16); 716 if(max16 != min16) 717 { 718 eval_colors(color, max16, min16); 719 mask = match_colors_block(block, color, dither != 0); 720 } 721 else 722 mask = 0; 723 724 refine_block(dither ? dblock : block, &max16, &min16, mask); 725 break; 726 } 727 728 if(max16 != min16) 729 { 730 eval_colors(color, max16, min16); 731 mask = match_colors_block(block, color, dither != 0); 732 } 733 else 734 mask = 0; 735 } 736 else 737 { 738 mask = 0xaaaaaaaa; 739 max16 = (omatch5[block[2]][0] << 11) | 740 (omatch6[block[1]][0] << 5) | 741 (omatch5[block[0]][0] ); 742 min16 = (omatch5[block[2]][1] << 11) | 743 (omatch6[block[1]][1] << 5) | 744 (omatch5[block[0]][1] ); 745 } 746 747 if(dxt1_alpha && block_has_alpha) 748 { 749 if(max16 > min16) 750 { 751 max16 ^= min16; min16 ^= max16; max16 ^= min16; 752 } 753 eval_colors(color, max16, min16); 754 mask = match_colors_block_DXT1alpha(block, color); 755 } 756 757 if(max16 < min16 && !(dxt1_alpha && block_has_alpha)) 758 { 759 max16 ^= min16; min16 ^= max16; max16 ^= min16; 760 mask ^= 0x55555555; 761 } 762 763 PUTL16(&dst[0], max16); 764 PUTL16(&dst[2], min16); 765 PUTL32(&dst[4], mask); 766 } 767 768 static void encode_alpha_block_DXT3(unsigned char *dst, 769 const unsigned char *block) 770 { 771 int i, a1, a2; 772 773 block += 3; 774 775 for(i = 0; i < 8; ++i) 776 { 777 a1 = block[8 * i + 0]; 778 a2 = block[8 * i + 4]; 779 *dst++ = ((a2 >> 4) << 4) | (a1 >> 4); 780 } 781 } 782 783 static void encode_alpha_block_DXT5(unsigned char *dst, 784 const unsigned char *block) 785 { 786 int i, v, mn, mx; 787 int dist, bias, dist2, dist4, bits, mask; 788 int a, idx, t; 789 790 block += 3; 791 792 mn = mx = block[0]; 793 for(i = 0; i < 16; ++i) 794 { 795 v = block[4 * i]; 796 if(v > mx) mx = v; 797 if(v < mn) mn = v; 798 } 799 800 *dst++ = mx; 801 *dst++ = mn; 802 803 dist = mx - mn; 804 bias = mn * 7 - (dist >> 1); 805 dist4 = dist * 4; 806 dist2 = dist * 2; 807 bits = 0; 808 mask = 0; 809 810 for(i = 0; i < 16; ++i) 811 { 812 a = block[4 * i] * 7 - bias; 813 814 t = (dist4 - a) >> 31; idx = t & 4; a -= dist4 & t; 815 t = (dist2 - a) >> 31; idx += t & 2; a -= dist2 & t; 816 t = (dist - a) >> 31; idx += t & 1; 817 818 idx = -idx & 7; 819 idx ^= (2 > idx); 820 821 mask |= idx << bits; 822 if((bits += 3) >= 8) 823 { 824 *dst++ = mask; 825 mask >>= 8; 826 bits -= 8; 827 } 828 } 829 } 830 831 static void compress_DXT1(unsigned char *dst, const unsigned char *src, 832 int w, int h, int type, int dither, int alpha) 833 { 834 unsigned char block[64]; 835 int x, y; 836 837 for(y = 0; y < h; y += 4, src += w * 4 * 4) 838 { 839 for(x = 0; x < w; x += 4) 840 { 841 extract_block(src + x * 4, w, block); 842 encode_color_block(dst, block, type, dither, alpha); 843 dst += 8; 844 } 845 } 846 } 847 848 static void compress_DXT3(unsigned char *dst, const unsigned char *src, 849 int w, int h, int type, int dither) 850 { 851 unsigned char block[64]; 852 int x, y; 853 854 for(y = 0; y < h; y += 4, src += w * 4 * 4) 855 { 856 for(x = 0; x < w; x += 4) 857 { 858 extract_block(src + x * 4, w, block); 859 encode_alpha_block_DXT3(dst, block); 860 encode_color_block(dst + 8, block, type, dither, 0); 861 dst += 16; 862 } 863 } 864 } 865 866 static void compress_DXT5(unsigned char *dst, const unsigned char *src, 867 int w, int h, int type, int dither) 868 { 869 unsigned char block[64]; 870 int x, y; 871 872 for(y = 0; y < h; y += 4, src += w * 4 * 4) 873 { 874 for(x = 0; x < w; x += 4) 875 { 876 extract_block(src + x * 4, w, block); 877 encode_alpha_block_DXT5(dst, block); 878 encode_color_block(dst + 8, block, type, dither, 0); 879 dst += 16; 880 } 881 } 882 } 883 884 static void compress_BC4(unsigned char *dst, const unsigned char *src, 885 int w, int h) 886 { 887 unsigned char block[64]; 888 int x, y; 889 890 for(y = 0; y < h; y += 4, src += w * 4 * 4) 891 { 892 for(x = 0; x < w; x += 4) 893 { 894 extract_block(src + x * 4, w, block); 895 encode_alpha_block_DXT5(dst, block - 1); 896 dst += 8; 897 } 898 } 899 } 900 901 static void compress_BC5(unsigned char *dst, const unsigned char *src, 902 int w, int h) 903 { 904 unsigned char block[64]; 905 int x, y; 906 907 for(y = 0; y < h; y += 4, src += w * 4 * 4) 908 { 909 for(x = 0; x < w; x += 4) 910 { 911 extract_block(src + x * 4, w, block); 912 encode_alpha_block_DXT5(dst, block - 2); 913 encode_alpha_block_DXT5(dst + 8, block - 1); 914 dst += 16; 915 } 916 } 917 } 918 919 static void compress_YCoCg(unsigned char *dst, const unsigned char *src, 920 int w, int h) 921 { 922 unsigned char block[64], colors[4][3]; 923 unsigned char *maxcolor, *mincolor; 924 unsigned int mask; 925 int c0, c1, d0, d1, d2, d3; 926 int b0, b1, b2, b3, b4; 927 int x0, x1, x2; 928 int x, y, i; 929 930 for(y = 0; y < h; y += 4, src += w * 4 * 4) 931 { 932 for(x = 0; x < w; x += 4) 933 { 934 extract_block(src + x * 4, w, block); 935 936 encode_alpha_block_DXT5(dst, block); 937 938 maxcolor = &colors[0][0]; 939 mincolor = &colors[1][0]; 940 941 get_min_max_YCoCg(block, mincolor, maxcolor); 942 scale_YCoCg(block, mincolor, maxcolor); 943 inset_bbox_YCoCg(mincolor, maxcolor); 944 select_diagonal_YCoCg(block, mincolor, maxcolor); 945 946 lerp_rgb(&colors[2][0], maxcolor, mincolor, 0x55); 947 lerp_rgb(&colors[3][0], maxcolor, mincolor, 0xaa); 948 949 mask = 0; 950 951 for(i = 15; i >= 0; --i) 952 { 953 c0 = block[4 * i + 2]; 954 c1 = block[4 * i + 1]; 955 956 d0 = abs(colors[0][2] - c0) + abs(colors[0][1] - c1); 957 d1 = abs(colors[1][2] - c0) + abs(colors[1][1] - c1); 958 d2 = abs(colors[2][2] - c0) + abs(colors[2][1] - c1); 959 d3 = abs(colors[3][2] - c0) + abs(colors[3][1] - c1); 960 961 b0 = d0 > d3; 962 b1 = d1 > d2; 963 b2 = d0 > d2; 964 b3 = d1 > d3; 965 b4 = d2 > d3; 966 967 x0 = b1 & b2; 968 x1 = b0 & b3; 969 x2 = b0 & b4; 970 971 mask <<= 2; 972 mask |= (x1 | ((x0 | x1) << 1)); 973 } 974 975 PUTL16(&dst[ 8], pack_rgb565(maxcolor)); 976 PUTL16(&dst[10], pack_rgb565(mincolor)); 977 PUTL32(&dst[12], mask); 978 979 dst += 16; 980 } 981 } 982 } 983 984 int dxt_compress(unsigned char *dst, unsigned char *src, int format, 985 unsigned int width, unsigned int height, int bpp, 986 int mipmaps, int type, int dither) 987 { 988 int i, size, w, h; 989 unsigned int offset; 990 unsigned char *tmp; 991 int j; 992 unsigned char *tmp2, *s; 993 int dxt1_alpha = 0; 994 995 if(!(IS_POT(width) && IS_POT(height))) 996 return(0); 997 998 size = get_mipmapped_size(width, height, bpp, 0, mipmaps, 999 DDS_COMPRESS_NONE); 1000 tmp = g_malloc(size); 1001 generate_mipmaps(tmp, src, width, height, bpp, 0, mipmaps); 1002 1003 if(bpp == 4 && format == DDS_COMPRESS_BC1) 1004 dxt1_alpha = 1; 1005 1006 if(bpp == 1) 1007 { 1008 /* grayscale promoted to BGRA */ 1009 1010 size = get_mipmapped_size(width, height, 4, 0, mipmaps, 1011 DDS_COMPRESS_NONE); 1012 tmp2 = g_malloc(size); 1013 1014 for(i = j = 0; j < size; ++i, j += 4) 1015 { 1016 tmp2[j + 0] = tmp[i]; 1017 tmp2[j + 1] = tmp[i]; 1018 tmp2[j + 2] = tmp[i]; 1019 tmp2[j + 3] = 255; 1020 } 1021 1022 g_free(tmp); 1023 tmp = tmp2; 1024 bpp = 4; 1025 } 1026 else if(bpp == 2) 1027 { 1028 /* gray-alpha promoted to BGRA */ 1029 1030 size = get_mipmapped_size(width, height, 4, 0, mipmaps, 1031 DDS_COMPRESS_NONE); 1032 tmp2 = g_malloc(size); 1033 1034 for(i = j = 0; j < size; i += 2, j += 4) 1035 { 1036 tmp2[j + 0] = tmp[i]; 1037 tmp2[j + 1] = tmp[i]; 1038 tmp2[j + 2] = tmp[i]; 1039 tmp2[j + 3] = tmp[i + 1]; 1040 } 1041 1042 g_free(tmp); 1043 tmp = tmp2; 1044 bpp = 4; 1045 } 1046 else if(bpp == 3) 1047 { 1048 size = get_mipmapped_size(width, height, 4, 0, mipmaps, 1049 DDS_COMPRESS_NONE); 1050 tmp2 = g_malloc(size); 1051 1052 for(i = j = 0; j < size; i += 3, j += 4) 1053 { 1054 tmp2[j + 0] = tmp[i + 0]; 1055 tmp2[j + 1] = tmp[i + 1]; 1056 tmp2[j + 2] = tmp[i + 2]; 1057 tmp2[j + 3] = 255; 1058 } 1059 1060 g_free(tmp); 1061 tmp = tmp2; 1062 bpp = 4; 1063 } 1064 1065 offset = 0; 1066 w = width; 1067 h = height; 1068 s = tmp; 1069 1070 for(i = 0; i < mipmaps; ++i) 1071 { 1072 switch(format) 1073 { 1074 case DDS_COMPRESS_BC1: 1075 compress_DXT1(dst + offset, s, w, h, type, dither, dxt1_alpha); 1076 break; 1077 case DDS_COMPRESS_BC2: 1078 compress_DXT3(dst + offset, s, w, h, type, dither); 1079 break; 1080 case DDS_COMPRESS_BC3: 1081 compress_DXT5(dst + offset, s, w, h, type, dither); 1082 break; 1083 case DDS_COMPRESS_BC4: 1084 compress_BC4(dst + offset, s, w, h); 1085 break; 1086 case DDS_COMPRESS_BC5: 1087 compress_BC5(dst + offset, s, w, h); 1088 break; 1089 case DDS_COMPRESS_YCOCGS: 1090 compress_YCoCg(dst + offset, s, w, h); 1091 break; 1092 default: 1093 compress_DXT5(dst + offset, s, w, h, type, dither); 1094 break; 1095 } 1096 s += (w * h * bpp); 1097 offset += get_mipmapped_size(w, h, 0, 0, 1, format); 1098 if(w > 1) w >>= 1; 1099 if(h > 1) h >>= 1; 1100 } 1101 1102 g_free(tmp); 1103 1104 return(1); 1105 } 1106 1107 static void decode_color_block(unsigned char *dst, unsigned char *src, 1108 int w, int h, int rowbytes, int format) 1109 { 1110 int i, x, y; 1111 unsigned int indexes, idx; 1112 unsigned char *d; 1113 unsigned char colors[4][3]; 1114 unsigned short c0, c1; 1115 1116 c0 = GETL16(&src[0]); 1117 c1 = GETL16(&src[2]); 1118 1119 unpack_rgb565(colors[0], c0); 1120 unpack_rgb565(colors[1], c1); 1121 1122 if((c0 > c1) || (format == DDS_COMPRESS_BC3)) 1123 { 1124 lerp_rgb(colors[2], colors[0], colors[1], 0x55); 1125 lerp_rgb(colors[3], colors[0], colors[1], 0xaa); 1126 } 1127 else 1128 { 1129 for(i = 0; i < 3; ++i) 1130 { 1131 colors[2][i] = (colors[0][i] + colors[1][i] + 1) >> 1; 1132 colors[3][i] = 255; 1133 } 1134 } 1135 1136 src += 4; 1137 for(y = 0; y < h; ++y) 1138 { 1139 d = dst + (y * rowbytes); 1140 indexes = src[y]; 1141 for(x = 0; x < w; ++x) 1142 { 1143 idx = indexes & 0x03; 1144 d[0] = colors[idx][2]; 1145 d[1] = colors[idx][1]; 1146 d[2] = colors[idx][0]; 1147 if(format == DDS_COMPRESS_BC1) 1148 d[3] = ((c0 <= c1) && idx == 3) ? 0 : 255; 1149 indexes >>= 2; 1150 d += 4; 1151 } 1152 } 1153 } 1154 1155 static void decode_alpha_block_DXT3(unsigned char *dst, unsigned char *src, 1156 int w, int h, int rowbytes) 1157 { 1158 int x, y; 1159 unsigned char *d; 1160 unsigned int bits; 1161 1162 for(y = 0; y < h; ++y) 1163 { 1164 d = dst + (y * rowbytes); 1165 bits = GETL16(&src[2 * y]); 1166 for(x = 0; x < w; ++x) 1167 { 1168 d[0] = (bits & 0x0f) * 17; 1169 bits >>= 4; 1170 d += 4; 1171 } 1172 } 1173 } 1174 1175 static void decode_alpha_block_DXT5(unsigned char *dst, unsigned char *src, 1176 int w, int h, int bpp, int rowbytes) 1177 { 1178 int x, y, code; 1179 unsigned char *d; 1180 unsigned char a0 = src[0]; 1181 unsigned char a1 = src[1]; 1182 unsigned long long bits = GETL64(src) >> 16; 1183 1184 for(y = 0; y < h; ++y) 1185 { 1186 d = dst + (y * rowbytes); 1187 for(x = 0; x < w; ++x) 1188 { 1189 code = ((unsigned int)bits) & 0x07; 1190 if(code == 0) 1191 d[0] = a0; 1192 else if(code == 1) 1193 d[0] = a1; 1194 else if(a0 > a1) 1195 d[0] = ((8 - code) * a0 + (code - 1) * a1) / 7; 1196 else if(code >= 6) 1197 d[0] = (code == 6) ? 0 : 255; 1198 else 1199 d[0] = ((6 - code) * a0 + (code - 1) * a1) / 5; 1200 bits >>= 3; 1201 d += bpp; 1202 } 1203 if(w < 4) bits >>= (3 * (4 - w)); 1204 } 1205 } 1206 1207 int dxt_decompress(unsigned char *dst, unsigned char *src, int format, 1208 unsigned int size, unsigned int width, unsigned int height, 1209 int bpp) 1210 { 1211 unsigned char *d, *s; 1212 unsigned int x, y, sx, sy; 1213 1214 if(!(IS_POT(width) && IS_POT(height))) 1215 return(0); 1216 1217 sx = (width < 4) ? width : 4; 1218 sy = (height < 4) ? height : 4; 1219 1220 s = src; 1221 1222 for(y = 0; y < height; y += 4) 1223 { 1224 for(x = 0; x < width; x += 4) 1225 { 1226 d = dst + (y * width + x) * bpp; 1227 if(format == DDS_COMPRESS_BC1) 1228 { 1229 decode_color_block(d, s, sx, sy, width * bpp, format); 1230 s += 8; 1231 } 1232 else if(format == DDS_COMPRESS_BC2) 1233 { 1234 decode_alpha_block_DXT3(d + 3, s, sx, sy, width * bpp); 1235 s += 8; 1236 decode_color_block(d, s, sx, sy, width * bpp, format); 1237 s += 8; 1238 } 1239 else if(format == DDS_COMPRESS_BC3) 1240 { 1241 decode_alpha_block_DXT5(d + 3, s, sx, sy, bpp, width * bpp); 1242 s += 8; 1243 decode_color_block(d, s, sx, sy, width * bpp, format); 1244 s += 8; 1245 } 1246 else if(format == DDS_COMPRESS_BC4) 1247 { 1248 decode_alpha_block_DXT5(d, s, sx, sy, bpp, width * bpp); 1249 s += 8; 1250 } 1251 else if(format == DDS_COMPRESS_BC5) 1252 { 1253 decode_alpha_block_DXT5(d, s + 8, sx, sy, bpp, width * bpp); 1254 decode_alpha_block_DXT5(d + 1, s, sx, sy, bpp, width * bpp); 1255 s += 16; 1256 } 1257 } 1258 } 1259 1260 return(1); 1261 }
| ViewVC Help | |
| Powered by ViewVC 1.0.4 |