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