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