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