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