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