Parent Directory
|
Revision Log
I think i got it this time... Create release 2.0 tag.
1 /* 2 DDS GIMP plugin 3 4 Copyright (C) 2004 Shawn Kirst <skirst@fuse.net>, 5 with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> where specified. 6 7 This program is free software; you can redistribute it and/or 8 modify it under the terms of the GNU General Public 9 License as published by the Free Software Foundation; either 10 version 2 of the License, or (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; see the file COPYING. If not, write to 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. 21 */ 22 23 #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 void dither_block(unsigned char *dst, const unsigned char *block) 85 { 86 int err[8], *ep1 = err, *ep2 = err + 4, *tmp; 87 int c, y; 88 unsigned char *bp, *dp; 89 const unsigned char *quant; 90 91 for(c = 0; c < 3; ++c) 92 { 93 bp = (unsigned char *)block; 94 dp = dst; 95 quant = (c == 1) ? quantG + 8 : quantRB + 8; 96 97 bp += c; 98 dp += c; 99 100 memset(err, 0, sizeof(err)); 101 102 for(y = 0; y < 4; ++y) 103 { 104 dp[ 0] = quant[bp[ 0] + ((3 * ep2[1] + 5 * ep2[0]) >> 4)]; 105 ep1[0] = bp[ 0] - dp[ 0]; 106 107 dp[ 4] = quant[bp[ 4] + ((7 * ep1[0] + 3 * ep2[2] + 5 * ep2[1] + ep2[0]) >> 4)]; 108 ep1[1] = bp[ 4] - dp[ 4]; 109 110 dp[ 8] = quant[bp[ 8] + ((7 * ep1[1] + 3 * ep2[3] + 5 * ep2[2] + ep2[1]) >> 4)]; 111 ep1[2] = bp[ 8] - dp[ 8]; 112 113 dp[12] = quant[bp[12] + ((7 * ep1[2] + 5 * ep2[3] + ep2[2]) >> 4)]; 114 ep1[3] = bp[12] - dp[12]; 115 116 tmp = ep1; 117 ep1 = ep2; 118 ep2 = tmp; 119 120 bp += 16; 121 dp += 16; 122 } 123 } 124 } 125 126 static unsigned int match_colors_block(const unsigned char *block, 127 const unsigned char *color, 128 int dither) 129 { 130 unsigned int mask = 0; 131 int dirb = color[0] - color[4]; 132 int dirg = color[1] - color[5]; 133 int dirr = color[2] - color[6]; 134 int dots[16], stops[4]; 135 int c0pt, halfpt, c3pt, dot; 136 int i; 137 138 for(i = 0; i < 16; ++i) 139 dots[i] = block[4 * i] * dirb + block[4 * i + 1] * dirg + block[4 * i + 2] * dirr; 140 141 for(i = 0; i < 4; ++i) 142 stops[i] = color[4 * i] * dirb + color[4 * i + 1] * dirg + color[4 * i + 2] * dirr; 143 144 c0pt = (stops[1] + stops[3]) >> 1; 145 halfpt = (stops[3] + stops[2]) >> 1; 146 c3pt = (stops[2] + stops[0]) >> 1; 147 148 if(!dither) 149 { 150 for(i = 15; i >= 0; --i) 151 { 152 mask <<= 2; 153 dot = dots[i]; 154 155 if(dot < halfpt) 156 mask |= (dot < c0pt) ? 1 : 3; 157 else 158 mask |= (dot < c3pt) ? 2 : 0; 159 } 160 } 161 else 162 { 163 int err[8], *ep1 = err, *ep2 = err + 4, *tmp; 164 int *dp = dots, y, lmask, step; 165 166 c0pt <<= 4; 167 halfpt <<= 4; 168 c3pt <<= 4; 169 170 memset(err, 0, sizeof(err)); 171 172 for(y = 0; y < 4; ++y) 173 { 174 dot = (dp[0] << 4) + (3 * ep2[1] + 5 * ep2[0]); 175 if(dot < halfpt) 176 step = (dot < c0pt) ? 1 : 3; 177 else 178 step = (dot < c3pt) ? 2 : 0; 179 180 ep1[0] = dp[0] - stops[step]; 181 lmask = step; 182 183 dot = (dp[1] << 4) + (7 * ep1[0] + 3 * ep2[2] + 5 * ep2[1] + ep2[0]); 184 if(dot < halfpt) 185 step = (dot < c0pt) ? 1 : 3; 186 else 187 step = (dot < c3pt) ? 2 : 0; 188 189 ep1[1] = dp[1] - stops[step]; 190 lmask |= step << 2; 191 192 dot = (dp[2] << 4) + (7 * ep1[1] + 3 * ep2[3] + 5 * ep2[2] + ep2[1]); 193 if(dot < halfpt) 194 step = (dot < c0pt) ? 1 : 3; 195 else 196 step = (dot < c3pt) ? 2 : 0; 197 198 ep1[2] = dp[2] - stops[step]; 199 lmask |= step << 4; 200 201 dot = (dp[3] << 4) + (7 * ep1[2] + 5 * ep2[3] + ep2[2]); 202 if(dot < halfpt) 203 step = (dot < c0pt) ? 1 : 3; 204 else 205 step = (dot < c3pt) ? 2 : 0; 206 207 ep1[3] = dp[3] - stops[step]; 208 lmask |= step << 6; 209 210 tmp = ep1; 211 ep1 = ep2; 212 ep2 = tmp; 213 214 dp += 4; 215 mask |= lmask << (y * 8); 216 } 217 } 218 219 return(mask); 220 } 221 222 static void optimize_colors_block(const unsigned char *block, 223 unsigned short *max16, unsigned short *min16) 224 { 225 static const int niterpow = 4; 226 227 int mu[3], mn[3], mx[3]; 228 int i, c, r, g, b, dot, iter; 229 int muv, mnv, mxv, mnd, mxd; 230 int cov[6]; 231 unsigned char *bp, mnc[3], mxc[3]; 232 float covf[6], vfr, vfg, vfb, magn; 233 float fr, fg, fb; 234 235 for(c = 0; c < 3; ++c) 236 { 237 bp = (unsigned char *)block + c; 238 239 muv = mnv = mxv = bp[0]; 240 for(i = 4; i < 64; i += 4) 241 { 242 muv += bp[i]; 243 if(mnv > bp[i]) mnv = bp[i]; 244 if(mxv < bp[i]) mxv = bp[i]; 245 } 246 247 mu[c] = (muv + 8) >> 4; 248 mn[c] = mnv; 249 mx[c] = mxv; 250 } 251 252 memset(cov, 0, sizeof(cov)); 253 254 for(i = 0; i < 16; ++i) 255 { 256 b = block[4 * i + 0] - mu[0]; 257 g = block[4 * i + 1] - mu[1]; 258 r = block[4 * i + 2] - mu[3]; 259 260 cov[0] += r * r; 261 cov[1] += r * g; 262 cov[2] += r * b; 263 cov[3] += g * g; 264 cov[4] += g * b; 265 cov[5] += b * b; 266 } 267 268 for(i = 0; i < 6; ++i) 269 covf[i] = cov[i] / 255.0f; 270 271 vfb = mx[0] - mn[0]; 272 vfg = mx[1] - mn[1]; 273 vfr = mx[2] - mn[2]; 274 275 for(iter = 0; iter < niterpow; ++iter) 276 { 277 fr = vfr * covf[0] + vfg * covf[1] + vfb * covf[2]; 278 fg = vfr * covf[1] + vfg * covf[3] + vfb * covf[4]; 279 fb = vfr * covf[2] + vfg * covf[4] + vfb * covf[5]; 280 281 vfr = fr; 282 vfg = fg; 283 vfb = fb; 284 } 285 286 vfr = fabsf(vfr); 287 vfg = fabsf(vfg); 288 vfb = fabsf(vfb); 289 290 magn = MAX(MAX(vfr, vfg), vfb); 291 292 if(magn < 4.0) 293 { 294 r = 148; 295 g = 300; 296 b = 58; 297 } 298 else 299 { 300 magn = 512.0f / magn; 301 r = (int)(vfr * magn); 302 g = (int)(vfg * magn); 303 b = (int)(vfb * magn); 304 } 305 306 mnd = 0x7fffffff; 307 mxd = -0x7fffffff; 308 309 for(i = 0; i < 16; ++i) 310 { 311 dot = block[4 * i] * b + block[4 * i + 1] * g + block[4 * i + 2] * r; 312 313 if(dot < mnd) 314 { 315 mnd = dot; 316 memcpy(mnc, &block[4 * i], 3); 317 } 318 if(dot > mxd) 319 { 320 mxd = dot; 321 memcpy(mxc, &block[4 * i], 3); 322 } 323 } 324 325 *max16 = pack_rgb565(mxc); 326 *min16 = pack_rgb565(mnc); 327 } 328 329 static int refine_block(const unsigned char *block, 330 unsigned short *max16, unsigned short *min16, 331 unsigned int mask) 332 { 333 static const int w1tab[4] = {3, 0, 2, 1}; 334 static const int prods[4] = {0x090000, 0x000900, 0x040102, 0x010402}; 335 int akku = 0; 336 int At1_r, At1_g, At1_b; 337 int At2_r, At2_g, At2_b; 338 unsigned int cm = mask; 339 int i, step, w1, r, g, b; 340 int xx, yy, xy; 341 float frb, fg; 342 unsigned short v, oldmin, oldmax; 343 int s; 344 345 At1_r = At1_g = At1_b = 0; 346 At2_r = At2_g = At2_b = 0; 347 348 for(i = 0; i < 16; ++i, cm >>= 2) 349 { 350 step = cm & 3; 351 w1 = w1tab[step]; 352 r = block[4 * i + 2]; 353 g = block[4 * i + 1]; 354 b = block[4 * i + 0]; 355 356 akku += prods[step]; 357 At1_r += w1 * r; 358 At1_g += w1 * g; 359 At1_b += w1 * b; 360 At2_r += r; 361 At2_g += g; 362 At2_b += b; 363 } 364 365 At2_r = 3 * At2_r - At1_r; 366 At2_g = 3 * At2_g - At1_g; 367 At2_b = 3 * At2_b - At1_b; 368 369 xx = akku >> 16; 370 yy = (akku >> 8) & 0xff; 371 xy = (akku >> 0) & 0xff; 372 373 if(!yy || !xx || xx * yy == xy * xy) 374 return(0); 375 376 frb = 3.0f * 31.0f / 255.0f / (xx * yy - xy * xy); 377 fg = frb * 63.0f / 31.0f; 378 379 oldmin = *min16; 380 oldmax = *max16; 381 382 s = (int)((At1_r * yy - At2_r * xy) * frb + 0.5f); 383 if(s < 0) s = 0; 384 if(s > 31) s = 31; 385 v = s << 11; 386 s = (int)((At1_g * yy - At2_g * xy) * fg + 0.5f); 387 if(s < 0) s = 0; 388 if(s > 63) s = 63; 389 v |= s << 5; 390 s = (int)((At1_b * yy - At2_b * xy) * frb + 0.5f); 391 if(s < 0) s = 0; 392 if(s > 31) s = 31; 393 v |= s; 394 *max16 = v; 395 396 s = (int)((At2_r * xx - At1_r * xy) * frb + 0.5f); 397 if(s < 0) s = 0; 398 if(s > 31) s = 31; 399 v = s << 11; 400 s = (int)((At2_g * xx - At1_g * xy) * fg + 0.5f); 401 if(s < 0) s = 0; 402 if(s > 63) s = 63; 403 v |= s << 5; 404 s = (int)((At2_b * xx - At1_b * xy) * frb + 0.5f); 405 if(s < 0) s = 0; 406 if(s > 31) s = 31; 407 v |= s; 408 *min16 = v; 409 410 return(oldmin != *min16 || oldmax != *max16); 411 } 412 413 static int color_distance(const unsigned char *c0, 414 const unsigned char *c1) 415 { 416 return(((c0[0] - c1[0]) * (c0[0] - c1[0])) + 417 ((c0[1] - c1[1]) * (c0[1] - c1[1])) + 418 ((c0[2] - c1[2]) * (c0[2] - c1[2]))); 419 } 420 421 static int luminance(const unsigned char *c) 422 { 423 return((c[2] * 54 + c[1] * 182 + c[0] * 20) >> 8); 424 } 425 426 static void get_min_max_colors_distance(const unsigned char *block, 427 unsigned short *max16, 428 unsigned short *min16) 429 { 430 int i, j, dist, maxdist = -1; 431 unsigned short c0 = 0, c1 = 0; 432 433 for(i = 0; i < 64 - 4; i += 4) 434 { 435 for(j = i + 4; j < 64; j += 4) 436 { 437 dist = color_distance(&block[i], &block[j]); 438 if(dist > maxdist) 439 { 440 maxdist = dist; 441 c0 = pack_rgb565(block + i); 442 c1 = pack_rgb565(block + j); 443 } 444 } 445 } 446 447 *max16 = MAX(c0, c1); 448 *min16 = MIN(c0, c1); 449 } 450 451 static void get_min_max_colors_luminance(const unsigned char *block, 452 unsigned short *max16, 453 unsigned short *min16) 454 { 455 int i, lum, minlum = 0x7fffffff, maxlum = -0x7fffffff; 456 unsigned char mn[3], mx[3]; 457 458 for(i = 0; i < 16; ++i) 459 { 460 lum = luminance(&block[4 * i]); 461 if(lum > maxlum) 462 { 463 maxlum = lum; 464 memcpy(mx, &block[4 * i], 3); 465 } 466 if(lum < minlum) 467 { 468 minlum = lum; 469 memcpy(mn, &block[4 * i], 3); 470 } 471 } 472 473 *max16 = pack_rgb565(mx); 474 *min16 = pack_rgb565(mn); 475 } 476 477 #define INSET_SHIFT 4 478 479 static void get_min_max_colors_inset_bbox(const unsigned char *block, 480 unsigned short *max16, 481 unsigned short *min16) 482 { 483 int i; 484 unsigned char inset[3], mx[3], mn[3]; 485 486 mn[0] = mn[1] = mn[2] = 255; 487 mx[0] = mx[1] = mx[2] = 3; 488 489 for(i = 0; i < 16; ++i) 490 { 491 if(block[4 * i + 0] < mn[0]) mn[0] = block[4 * i + 0]; 492 if(block[4 * i + 1] < mn[1]) mn[1] = block[4 * i + 1]; 493 if(block[4 * i + 2] < mn[2]) mn[2] = block[4 * i + 2]; 494 if(block[4 * i + 0] > mx[0]) mx[0] = block[4 * i + 0]; 495 if(block[4 * i + 1] > mx[1]) mx[1] = block[4 * i + 1]; 496 if(block[4 * i + 2] > mx[2]) mx[2] = block[4 * i + 2]; 497 } 498 499 inset[0] = (mx[0] - mn[0]) >> INSET_SHIFT; 500 inset[1] = (mx[1] - mn[1]) >> INSET_SHIFT; 501 inset[2] = (mx[2] - mn[2]) >> INSET_SHIFT; 502 503 mn[0] = (mn[0] + inset[0] <= 255) ? mn[0] + inset[0] : 255; 504 mn[1] = (mn[1] + inset[1] <= 255) ? mn[1] + inset[1] : 255; 505 mn[2] = (mn[2] + inset[2] <= 255) ? mn[2] + inset[2] : 255; 506 507 mx[0] = (mx[0] >= inset[0]) ? mx[0] - inset[0] : 0; 508 mx[1] = (mx[1] >= inset[1]) ? mx[1] - inset[1] : 0; 509 mx[2] = (mx[2] >= inset[2]) ? mx[2] - inset[2] : 0; 510 511 *min16 = pack_rgb565(mn); 512 *max16 = pack_rgb565(mx); 513 } 514 515 static void eval_colors(unsigned char *color, 516 unsigned short c0, unsigned short c1) 517 { 518 unpack_rgb565(&color[0], c0); 519 unpack_rgb565(&color[4], c1); 520 if(c0 > c1) 521 { 522 lerp_rgb(&color[ 8], &color[0], &color[4], 0x55); 523 lerp_rgb(&color[12], &color[0], &color[4], 0xaa); 524 } 525 else 526 { 527 color[ 8] = (color[0] + color[4]) >> 1; 528 color[ 9] = (color[1] + color[5]) >> 1; 529 color[10] = (color[3] + color[8]) >> 1; 530 531 color[12] = color[13] = color[14] = 0; 532 } 533 } 534 535 static void encode_color_block(unsigned char *dst, 536 const unsigned char *block, 537 int type, int dither) 538 { 539 unsigned char dblock[64], color[16]; 540 unsigned short min16, max16; 541 unsigned int v, mn, mx, mask; 542 int i; 543 544 mn = mx = GETL32(block); 545 for(i = 0; i < 16; ++i) 546 { 547 v = GETL32(&block[4 * i]); 548 if(v > mx) mx = v; 549 if(v < mn) mn = v; 550 } 551 552 if(mn != mx) 553 { 554 if(dither) 555 dither_block(dblock, block); 556 557 switch(type) 558 { 559 case DDS_COLOR_DISTANCE: 560 get_min_max_colors_distance(dither ? dblock : block, &max16, &min16); 561 break; 562 case DDS_COLOR_LUMINANCE: 563 get_min_max_colors_luminance(dither ? dblock : block, &max16, &min16); 564 break; 565 case DDS_COLOR_INSET_BBOX: 566 get_min_max_colors_inset_bbox(dither ? dblock : block, &max16, &min16); 567 break; 568 default: 569 optimize_colors_block(dither ? dblock : block, &max16, &min16); 570 if(max16 != min16) 571 { 572 eval_colors(color, max16, min16); 573 mask = match_colors_block(block, color, dither != 0); 574 } 575 else 576 mask = 0; 577 578 refine_block(dither ? dblock : block, &max16, &min16, mask); 579 break; 580 } 581 582 if(max16 != min16) 583 { 584 eval_colors(color, max16, min16); 585 mask = match_colors_block(block, color, dither != 0); 586 } 587 else 588 mask = 0; 589 } 590 else 591 { 592 mask = 0xaaaaaaaa; 593 max16 = (omatch5[block[2]][0] << 11) | 594 (omatch6[block[1]][0] << 5) | 595 (omatch5[block[0]][0] ); 596 min16 = (omatch5[block[2]][1] << 11) | 597 (omatch6[block[1]][1] << 5) | 598 (omatch5[block[0]][1] ); 599 } 600 601 if(max16 < min16) 602 { 603 max16 ^= min16 ^= max16 ^= min16; 604 mask ^= 0x55555555; 605 } 606 607 PUTL16(&dst[0], max16); 608 PUTL16(&dst[2], min16); 609 PUTL32(&dst[4], mask); 610 } 611 612 static void encode_alpha_block_DXT3(unsigned char *dst, 613 const unsigned char *block) 614 { 615 int i, a1, a2; 616 617 block += 3; 618 619 for(i = 0; i < 8; ++i) 620 { 621 a1 = block[8 * i + 0]; 622 a2 = block[8 * i + 4]; 623 *dst++ = ((a2 >> 4) << 4) | (a1 >> 4); 624 } 625 } 626 627 static void encode_alpha_block_DXT5(unsigned char *dst, 628 const unsigned char *block) 629 { 630 int i, v, mn, mx; 631 int dist, bias, dist2, dist4, bits, mask; 632 int a, idx, t; 633 634 block += 3; 635 636 mn = mx = block[0]; 637 for(i = 0; i < 16; ++i) 638 { 639 v = block[4 * i]; 640 if(v > mx) mx = v; 641 if(v < mn) mn = v; 642 } 643 644 *dst++ = mx; 645 *dst++ = mn; 646 647 dist = mx - mn; 648 bias = mn * 7 - (dist >> 1); 649 dist4 = dist * 4; 650 dist2 = dist * 2; 651 bits = 0; 652 mask = 0; 653 654 for(i = 0; i < 16; ++i) 655 { 656 a = block[4 * i] * 7 - bias; 657 658 t = (dist4 - a) >> 31; idx = t & 4; a -= dist4 & t; 659 t = (dist2 - a) >> 31; idx += t & 2; a -= dist2 & t; 660 t = (dist - a) >> 31; idx += t & 1; 661 662 idx = -idx & 7; 663 idx ^= (2 > idx); 664 665 mask |= idx << bits; 666 if((bits += 3) >= 8) 667 { 668 *dst++ = mask; 669 mask >>= 8; 670 bits -= 8; 671 } 672 } 673 } 674 675 static void compress_DXT1(unsigned char *dst, const unsigned char *src, 676 int w, int h, int type, int dither) 677 { 678 unsigned char block[64]; 679 int x, y; 680 681 for(y = 0; y < h; y += 4, src += w * 4 * 4) 682 { 683 for(x = 0; x < w; x += 4) 684 { 685 extract_block(src + x * 4, w, block); 686 encode_color_block(dst, block, type, dither); 687 dst += 8; 688 } 689 } 690 } 691 692 static void compress_DXT3(unsigned char *dst, const unsigned char *src, 693 int w, int h, int type, int dither) 694 { 695 unsigned char block[64]; 696 int x, y; 697 698 for(y = 0; y < h; y += 4, src += w * 4 * 4) 699 { 700 for(x = 0; x < w; x += 4) 701 { 702 extract_block(src + x * 4, w, block); 703 encode_alpha_block_DXT3(dst, block); 704 encode_color_block(dst + 8, block, type, dither); 705 dst += 16; 706 } 707 } 708 } 709 710 static void compress_DXT5(unsigned char *dst, const unsigned char *src, 711 int w, int h, int type, int dither) 712 { 713 unsigned char block[64]; 714 int x, y; 715 716 for(y = 0; y < h; y += 4, src += w * 4 * 4) 717 { 718 for(x = 0; x < w; x += 4) 719 { 720 extract_block(src + x * 4, w, block); 721 encode_alpha_block_DXT5(dst, block); 722 encode_color_block(dst + 8, block, type, dither); 723 dst += 16; 724 } 725 } 726 } 727 728 static void compress_BC4(unsigned char *dst, const unsigned char *src, 729 int w, int h) 730 { 731 unsigned char block[64]; 732 int x, y; 733 734 for(y = 0; y < h; y += 4, src += w * 4 * 4) 735 { 736 for(x = 0; x < w; x += 4) 737 { 738 extract_block(src + x * 4, w, block); 739 encode_alpha_block_DXT5(dst, block - 1); 740 dst += 8; 741 } 742 } 743 } 744 745 static void compress_BC5(unsigned char *dst, const unsigned char *src, 746 int w, int h) 747 { 748 unsigned char block[64]; 749 int x, y; 750 751 for(y = 0; y < h; y += 4, src += w * 4 * 4) 752 { 753 for(x = 0; x < w; x += 4) 754 { 755 extract_block(src + x * 4, w, block); 756 encode_alpha_block_DXT5(dst, block - 2); 757 encode_alpha_block_DXT5(dst + 8, block - 1); 758 dst += 16; 759 } 760 } 761 } 762 763 int dxt_compress(unsigned char *dst, unsigned char *src, int format, 764 unsigned int width, unsigned int height, int bpp, 765 int mipmaps, int type, int dither) 766 { 767 int i, size, w, h; 768 unsigned int offset; 769 unsigned char *tmp; 770 int j; 771 unsigned char *tmp2, *s; 772 773 if(!(IS_POT(width) && IS_POT(height))) 774 return(0); 775 776 size = get_mipmapped_size(width, height, bpp, 0, mipmaps, 777 DDS_COMPRESS_NONE); 778 tmp = g_malloc(size); 779 generate_mipmaps(tmp, src, width, height, bpp, 0, mipmaps); 780 781 if(bpp == 1) 782 { 783 /* grayscale promoted to BGRA */ 784 785 size = get_mipmapped_size(width, height, 4, 0, mipmaps, 786 DDS_COMPRESS_NONE); 787 tmp2 = g_malloc(size); 788 789 for(i = j = 0; j < size; ++i, j += 4) 790 { 791 tmp2[j + 0] = tmp[i]; 792 tmp2[j + 1] = tmp[i]; 793 tmp2[j + 2] = tmp[i]; 794 tmp2[j + 3] = 255; 795 } 796 797 g_free(tmp); 798 tmp = tmp2; 799 bpp = 4; 800 } 801 else if(bpp == 2) 802 { 803 /* gray-alpha promoted to BGRA */ 804 805 size = get_mipmapped_size(width, height, 4, 0, mipmaps, 806 DDS_COMPRESS_NONE); 807 tmp2 = g_malloc(size); 808 809 for(i = j = 0; j < size; i += 2, j += 4) 810 { 811 tmp2[j + 0] = tmp[i]; 812 tmp2[j + 1] = tmp[i]; 813 tmp2[j + 2] = tmp[i]; 814 tmp2[j + 3] = tmp[i + 1]; 815 } 816 817 g_free(tmp); 818 tmp = tmp2; 819 bpp = 4; 820 } 821 else if(bpp == 3) 822 { 823 size = get_mipmapped_size(width, height, 4, 0, mipmaps, 824 DDS_COMPRESS_NONE); 825 tmp2 = g_malloc(size); 826 827 for(i = j = 0; j < size; i += 3, j += 4) 828 { 829 tmp2[j + 0] = tmp[i + 0]; 830 tmp2[j + 1] = tmp[i + 1]; 831 tmp2[j + 2] = tmp[i + 2]; 832 tmp2[j + 3] = 255; 833 } 834 835 g_free(tmp); 836 tmp = tmp2; 837 bpp = 4; 838 } 839 840 offset = 0; 841 w = width; 842 h = height; 843 s = tmp; 844 845 for(i = 0; i < mipmaps; ++i) 846 { 847 switch(format) 848 { 849 case DDS_COMPRESS_BC1: 850 compress_DXT1(dst + offset, s, w, h, type, dither); 851 break; 852 case DDS_COMPRESS_BC2: 853 compress_DXT3(dst + offset, s, w, h, type, dither); 854 break; 855 case DDS_COMPRESS_BC3: 856 compress_DXT5(dst + offset, s, w, h, type, dither); 857 break; 858 case DDS_COMPRESS_BC4: 859 compress_BC4(dst + offset, s, w, h); 860 break; 861 case DDS_COMPRESS_BC5: 862 compress_BC5(dst + offset, s, w, h); 863 break; 864 } 865 s += (w * h * bpp); 866 offset += get_mipmapped_size(w, h, 0, 0, 1, format); 867 if(w > 1) w >>= 1; 868 if(h > 1) h >>= 1; 869 } 870 871 g_free(tmp); 872 873 return(1); 874 } 875 876 static void decode_color_block(unsigned char *dst, unsigned char *src, 877 int w, int h, int rowbytes, int format) 878 { 879 int i, x, y; 880 unsigned int indexes, idx; 881 unsigned char *d; 882 unsigned char colors[4][3]; 883 unsigned short c0, c1; 884 885 c0 = GETL16(&src[0]); 886 c1 = GETL16(&src[2]); 887 888 unpack_rgb565(colors[0], c0); 889 unpack_rgb565(colors[1], c1); 890 891 if((c0 > c1) || (format == DDS_COMPRESS_BC3)) 892 { 893 for(i = 0; i < 3; ++i) 894 { 895 colors[2][i] = (2 * colors[0][i] + colors[1][i] + 1) / 3; 896 colors[3][i] = (2 * colors[1][i] + colors[0][i] + 1) / 3; 897 } 898 } 899 else 900 { 901 for(i = 0; i < 3; ++i) 902 { 903 colors[2][i] = (colors[0][i] + colors[1][i] + 1) >> 1; 904 colors[3][i] = 255; 905 } 906 } 907 908 src += 4; 909 for(y = 0; y < h; ++y) 910 { 911 d = dst + (y * rowbytes); 912 indexes = src[y]; 913 for(x = 0; x < w; ++x) 914 { 915 idx = indexes & 0x03; 916 d[0] = colors[idx][2]; 917 d[1] = colors[idx][1]; 918 d[2] = colors[idx][0]; 919 if(format == DDS_COMPRESS_BC1) 920 d[3] = ((c0 <= c1) && idx == 3) ? 0 : 255; 921 indexes >>= 2; 922 d += 4; 923 } 924 } 925 } 926 927 static void decode_alpha_block_DXT3(unsigned char *dst, unsigned char *src, 928 int w, int h, int rowbytes) 929 { 930 int x, y; 931 unsigned char *d; 932 unsigned int bits; 933 934 for(y = 0; y < h; ++y) 935 { 936 d = dst + (y * rowbytes); 937 bits = GETL16(&src[2 * y]); 938 for(x = 0; x < w; ++x) 939 { 940 d[0] = (bits & 0x0f) * 17; 941 bits >>= 4; 942 d += 4; 943 } 944 } 945 } 946 947 static void decode_alpha_block_DXT5(unsigned char *dst, unsigned char *src, 948 int w, int h, int bpp, int rowbytes) 949 { 950 int x, y, code; 951 unsigned char *d; 952 unsigned char a0 = src[0]; 953 unsigned char a1 = src[1]; 954 unsigned long long bits = GETL64(src) >> 16; 955 956 for(y = 0; y < h; ++y) 957 { 958 d = dst + (y * rowbytes); 959 for(x = 0; x < w; ++x) 960 { 961 code = ((unsigned int)bits) & 0x07; 962 if(code == 0) 963 d[0] = a0; 964 else if(code == 1) 965 d[0] = a1; 966 else if(a0 > a1) 967 d[0] = ((8 - code) * a0 + (code - 1) * a1) / 7; 968 else if(code >= 6) 969 d[0] = (code == 6) ? 0 : 255; 970 else 971 d[0] = ((6 - code) * a0 + (code - 1) * a1) / 5; 972 bits >>= 3; 973 d += bpp; 974 } 975 if(w < 4) bits >>= (3 * (4 - w)); 976 } 977 } 978 979 int dxt_decompress(unsigned char *dst, unsigned char *src, int format, 980 unsigned int size, unsigned int width, unsigned int height, 981 int bpp) 982 { 983 unsigned char *d, *s; 984 unsigned int x, y, sx, sy; 985 986 if(!(IS_POT(width) && IS_POT(height))) 987 return(0); 988 989 sx = (width < 4) ? width : 4; 990 sy = (height < 4) ? height : 4; 991 992 s = src; 993 994 for(y = 0; y < height; y += 4) 995 { 996 for(x = 0; x < width; x += 4) 997 { 998 d = dst + (y * width + x) * bpp; 999 if(format == DDS_COMPRESS_BC1) 1000 { 1001 decode_color_block(d, s, sx, sy, width * bpp, format); 1002 s += 8; 1003 } 1004 else if(format == DDS_COMPRESS_BC2) 1005 { 1006 decode_alpha_block_DXT3(d + 3, s, sx, sy, width * bpp); 1007 s += 8; 1008 decode_color_block(d, s, sx, sy, width * bpp, format); 1009 s += 8; 1010 } 1011 else if(format == DDS_COMPRESS_BC3) 1012 { 1013 decode_alpha_block_DXT5(d + 3, s, sx, sy, bpp, width * bpp); 1014 s += 8; 1015 decode_color_block(d, s, sx, sy, width * bpp, format); 1016 s += 8; 1017 } 1018 else if(format == DDS_COMPRESS_BC4) 1019 { 1020 decode_alpha_block_DXT5(d, s, sx, sy, bpp, width * bpp); 1021 s += 8; 1022 } 1023 else if(format == DDS_COMPRESS_BC5) 1024 { 1025 decode_alpha_block_DXT5(d, s + 8, sx, sy, bpp, width * bpp); 1026 decode_alpha_block_DXT5(d + 1, s, sx, sy, bpp, width * bpp); 1027 s += 16; 1028 } 1029 } 1030 } 1031 1032 return(1); 1033 }
| ViewVC Help | |
| Powered by ViewVC 1.0.4 |