Parent Directory
|
Revision Log
Fixing a boo-boo part 2/2
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 #include <string.h> 24 #include <math.h> 25 26 #include "dds.h" 27 #include "mipmap.h" 28 #include "imath.h" 29 30 typedef void (*mipmapfunc_t)(unsigned char *, int, int, unsigned char *, int, int, int); 31 typedef void (*volmipmapfunc_t)(unsigned char *, int, int, int, unsigned char *, int, int, int, int); 32 33 int get_num_mipmaps(int width, int height) 34 { 35 int w = width << 1; 36 int h = height << 1; 37 int n = 0; 38 39 while(w != 1 || h != 1) 40 { 41 if(w > 1) w >>= 1; 42 if(h > 1) h >>= 1; 43 ++n; 44 } 45 46 return(n); 47 } 48 49 unsigned int get_mipmapped_size(int width, int height, int bpp, 50 int level, int num, int format) 51 { 52 int w, h, n = 0; 53 unsigned int size = 0; 54 55 w = width >> level; 56 h = height >> level; 57 if(w == 0) w = 1; 58 if(h == 0) h = 1; 59 w <<= 1; 60 h <<= 1; 61 62 while(n < num && (w != 1 || h != 1)) 63 { 64 if(w > 1) w >>= 1; 65 if(h > 1) h >>= 1; 66 if(format == DDS_COMPRESS_NONE) 67 size += (w * h); 68 else 69 size += ((w + 3) >> 2) * ((h + 3) >> 2); 70 ++n; 71 } 72 73 if(format == DDS_COMPRESS_NONE) 74 size *= bpp; 75 else 76 { 77 if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4) 78 size *= 8; 79 else 80 size *= 16; 81 } 82 83 return(size); 84 } 85 86 unsigned int get_volume_mipmapped_size(int width, int height, 87 int depth, int bpp, int level, 88 int num, int format) 89 { 90 int w, h, d, n = 0; 91 unsigned int size = 0; 92 93 w = width >> level; 94 h = height >> level; 95 d = depth >> level; 96 if(w == 0) w = 1; 97 if(h == 0) h = 1; 98 if(d == 0) d = 1; 99 w <<= 1; 100 h <<= 1; 101 d <<= 1; 102 103 while(n < num && (w != 1 || h != 1)) 104 { 105 if(w > 1) w >>= 1; 106 if(h > 1) h >>= 1; 107 if(d > 1) d >>= 1; 108 if(format == DDS_COMPRESS_NONE) 109 size += (w * h * d); 110 else 111 size += (((w + 3) >> 2) * ((h + 3) >> 2) * d); 112 ++n; 113 } 114 115 if(format == DDS_COMPRESS_NONE) 116 size *= bpp; 117 else 118 { 119 if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4) 120 size *= 8; 121 else 122 size *= 16; 123 } 124 125 return(size); 126 } 127 128 static void scale_image_nearest(unsigned char *dst, int dw, int dh, 129 unsigned char *src, int sw, int sh, 130 int bpp) 131 { 132 int n, x, y; 133 int ix, iy; 134 int srowbytes = sw * bpp; 135 int drowbytes = dw * bpp; 136 137 for(y = 0; y < dh; ++y) 138 { 139 iy = (y * sh + sh / 2) / dh; 140 for(x = 0; x < dw; ++x) 141 { 142 ix = (x * sw + sw / 2) / dw; 143 for(n = 0; n < bpp; ++n) 144 { 145 dst[y * drowbytes + (x * bpp) + n] = 146 src[iy * srowbytes + (ix * bpp) + n]; 147 } 148 } 149 } 150 } 151 152 static void scale_image_bilinear(unsigned char *dst, int dw, int dh, 153 unsigned char *src, int sw, int sh, 154 int bpp) 155 { 156 int x, y, n, ix, iy, wx, wy, v, v0, v1; 157 int dstride = dw * bpp; 158 unsigned char *s; 159 160 for(y = 0; y < dh; ++y) 161 { 162 if(dh > 1) 163 { 164 iy = (((sh - 1) * y) << 8) / (dh - 1); 165 if(y == dh - 1) --iy; 166 wy = iy & 0xff; 167 iy >>= 8; 168 } 169 else 170 iy = wy = 0; 171 172 for(x = 0; x < dw; ++x) 173 { 174 if(dw > 1) 175 { 176 ix = (((sw - 1) * x) << 8) / (dw - 1); 177 if(x == dw - 1) --ix; 178 wx = ix & 0xff; 179 ix >>= 8; 180 } 181 else 182 ix = wx = 0; 183 184 s = src + (iy * sw + ix) * bpp; 185 186 for(n = 0; n < bpp; ++n) 187 { 188 v0 = blerp(s[0], s[bpp], wx); 189 v1 = blerp(s[sw * bpp], s[(sw + 1) * bpp], wx); 190 v = blerp(v0, v1, wy); 191 if(v < 0) v = 0; 192 if(v > 255) v = 255; 193 dst[(y * dstride) + (x * bpp) + n] = v; 194 ++s; 195 } 196 } 197 } 198 } 199 200 static void scale_image_bicubic(unsigned char *dst, int dw, int dh, 201 unsigned char *src, int sw, int sh, 202 int bpp) 203 { 204 int x, y, n, ix, iy, wx, wy, v; 205 int a, b, c, d; 206 int dstride = dw * bpp; 207 unsigned char *s; 208 209 for(y = 0; y < dh; ++y) 210 { 211 if(dh > 1) 212 { 213 iy = (((sh - 1) * y) << 7) / (dh - 1); 214 if(y == dh - 1) --iy; 215 wy = iy & 0x7f; 216 iy >>= 7; 217 } 218 else 219 iy = wy = 0; 220 221 for(x = 0; x < dw; ++x) 222 { 223 if(dw > 1) 224 { 225 ix = (((sw - 1) * x) << 7) / (dw - 1); 226 if(x == dw - 1) --ix; 227 wx = ix & 0x7f; 228 ix >>= 7; 229 } 230 else 231 ix = wx = 0; 232 233 s = src + ((iy - 1) * sw + (ix - 1)) * bpp; 234 235 for(n = 0; n < bpp; ++n) 236 { 237 b = icerp(s[(sw + 0) * bpp], 238 s[(sw + 1) * bpp], 239 s[(sw + 2) * bpp], 240 s[(sw + 3) * bpp], wx); 241 if(iy > 0) 242 { 243 a = icerp(s[ 0], 244 s[ bpp], 245 s[2 * bpp], 246 s[3 * bpp], wx); 247 } 248 else 249 a = b; 250 251 c = icerp(s[(2 * sw + 0) * bpp], 252 s[(2 * sw + 1) * bpp], 253 s[(2 * sw + 2) * bpp], 254 s[(2 * sw + 3) * bpp], wx); 255 if(iy < dh - 1) 256 { 257 d = icerp(s[(3 * sw + 0) * bpp], 258 s[(3 * sw + 1) * bpp], 259 s[(3 * sw + 2) * bpp], 260 s[(3 * sw + 3) * bpp], wx); 261 } 262 else 263 d = c; 264 265 v = icerp(a, b, c, d, wy); 266 if(v < 0) v = 0; 267 if(v > 255) v = 255; 268 dst[(y * dstride) + (x * bpp) + n] = v; 269 ++s; 270 } 271 } 272 } 273 } 274 275 int generate_mipmaps(unsigned char *dst, unsigned char *src, 276 unsigned int width, unsigned int height, int bpp, 277 int indexed, int mipmaps, int filter) 278 { 279 int i; 280 unsigned int sw, sh, dw, dh; 281 unsigned char *s, *d; 282 mipmapfunc_t mipmap_func = NULL; 283 284 if(indexed) 285 mipmap_func = scale_image_nearest; 286 else 287 { 288 switch(filter) 289 { 290 case DDS_MIPMAP_NEAREST: mipmap_func = scale_image_nearest; break; 291 case DDS_MIPMAP_BICUBIC: mipmap_func = scale_image_bicubic; break; 292 case DDS_MIPMAP_BILINEAR: 293 default: mipmap_func = scale_image_bilinear; break; 294 } 295 } 296 297 memcpy(dst, src, width * height * bpp); 298 299 s = dst; 300 d = dst + (width * height * bpp); 301 302 sw = width; 303 sh = height; 304 305 for(i = 1; i < mipmaps; ++i) 306 { 307 dw = sw >> 1; 308 dh = sh >> 1; 309 if(dw < 1) dw = 1; 310 if(dh < 1) dh = 1; 311 312 mipmap_func(d, dw, dh, s, sw, sh, bpp); 313 314 s = d; 315 sw = dw; 316 sh = dh; 317 d += (dw * dh * bpp); 318 } 319 320 return(1); 321 } 322 323 static void scale_volume_image_nearest(unsigned char *dst, int dw, int dh, int dd, 324 unsigned char *src, int sw, int sh, int sd, 325 int bpp) 326 { 327 int n, x, y, z; 328 int ix, iy, iz; 329 330 for(z = 0; z < dd; ++z) 331 { 332 iz = (z * sd + sd / 2) / dd; 333 for(y = 0; y < dh; ++y) 334 { 335 iy = (y * sh + sh / 2) / dh; 336 for(x = 0; x < dw; ++x) 337 { 338 ix = (x * sw + sw / 2) / dw; 339 for(n = 0; n < bpp; ++n) 340 { 341 dst[(z * (dw * dh)) + (y * dw) + (x * bpp) + n] = 342 src[(iz * (sw * sh)) + (iy * sw) + (ix * bpp) + n]; 343 } 344 } 345 } 346 } 347 } 348 349 static void scale_volume_image_bilinear(unsigned char *dst, int dw, int dh, int dd, 350 unsigned char *src, int sw, int sh, int sd, 351 int bpp) 352 { 353 int x, y, z, n, ix, iy, iz, wx, wy, wz, v, v0, v1, r0, r1; 354 unsigned char *s1, *s2, *d = dst; 355 356 for(z = 0; z < dd; ++z) 357 { 358 if(dd > 1) 359 { 360 iz = (((sd - 1) * z) << 8) / (dd - 1); 361 if(z == dd - 1) --iz; 362 wz = iz & 0xff; 363 iz >>= 8; 364 } 365 else 366 iz = wz = 0; 367 368 for(y = 0; y < dh; ++y) 369 { 370 if(dh > 1) 371 { 372 iy = (((sh - 1) * y) << 8) / (dh - 1); 373 if(y == dh - 1) --iy; 374 wy = iy & 0xff; 375 iy >>= 8; 376 } 377 else 378 iy = wy = 0; 379 380 for(x = 0; x < dw; ++x) 381 { 382 if(dw > 1) 383 { 384 ix = (((sw - 1) * x) << 8) / (dw - 1); 385 if(x == dw - 1) --ix; 386 wx = ix & 0xff; 387 ix >>= 8; 388 } 389 else 390 ix = wx = 0; 391 392 s1 = src + ((iz * (sw * sh)) + (iy * sw) + ix) * bpp; 393 s2 = src + (((iz + 1) * (sw * sh)) + (iy * sw) + ix) * bpp; 394 395 for(n = 0; n < bpp; ++n) 396 { 397 r0 = blerp(s1[0], s1[bpp], wx); 398 r1 = blerp(s1[sw * bpp], s1[(sw + 1) * bpp], wx); 399 v0 = blerp(r0, r1, wy); 400 401 r0 = blerp(s2[0], s2[bpp], wx); 402 r1 = blerp(s2[sw * bpp], s2[(sw + 1) * bpp], wx); 403 v1 = blerp(r0, r1, wy); 404 405 v = blerp(v0, v1, wz); 406 if(v < 0) v = 0; 407 if(v > 255) v = 255; 408 *d++ = v; 409 ++s1; 410 ++s2; 411 } 412 } 413 } 414 } 415 } 416 417 static void scale_volume_image_cubic(unsigned char *dst, int dw, int dh, int dd, 418 unsigned char *src, int sw, int sh, int sd, 419 int bpp) 420 { 421 int n, x, y, z; 422 int ix, iy, iz; 423 int wx, wy, wz; 424 int a, b, c, d; 425 int val, v0, v1, v2, v3; 426 int dstride = dw * bpp; 427 int sslice = sw * sh * bpp; 428 int dslice = dw * dh * bpp; 429 unsigned char *s0, *s1, *s2, *s3; 430 431 for(z = 0; z < dd; ++z) 432 { 433 if(dd > 1) 434 { 435 iz = (((sd - 1) * z) << 7) / (dd - 1); 436 if(z == dd - 1) --iz; 437 wz = iz & 0x7f; 438 iz >>= 7; 439 } 440 else 441 iz = wz = 0; 442 443 for(y = 0; y < dh; ++y) 444 { 445 if(dh > 1) 446 { 447 iy = (((sh - 1) * y) << 7) / (dh - 1); 448 if(y == dh - 1) --iy; 449 wy = iy & 0x7f; 450 iy >>= 7; 451 } 452 else 453 iy = wy = 0; 454 455 for(x = 0; x < dw; ++x) 456 { 457 if(dw > 1) 458 { 459 ix = (((sw - 1) * x) << 7) / (dw - 1); 460 if(x == dw - 1) --ix; 461 wx = ix & 0x7f; 462 ix >>= 7; 463 } 464 else 465 ix = wx = 0; 466 467 s0 = src + (((iz - 1) * (sw * sh)) + ((iy - 1) * sw) + (ix - 1)) * bpp; 468 s1 = s0 + sslice; 469 s2 = s1 + sslice; 470 s3 = s2 + sslice; 471 472 for(n = 0; n < bpp; ++n) 473 { 474 b = icerp(s1[(sw + 0) * bpp], 475 s1[(sw + 1) * bpp], 476 s1[(sw + 2) * bpp], 477 s1[(sw + 3) * bpp], wx); 478 if(iy > 0) 479 { 480 a = icerp(s1[ 0], 481 s1[ bpp], 482 s1[2 * bpp], 483 s1[3 * bpp], wx); 484 } 485 else 486 a = b; 487 488 c = icerp(s1[(2 * sw + 0) * bpp], 489 s1[(2 * sw + 1) * bpp], 490 s1[(2 * sw + 2) * bpp], 491 s1[(2 * sw + 3) * bpp], wx); 492 if(iy < dh - 1) 493 { 494 d = icerp(s1[(3 * sw + 0) * bpp], 495 s1[(3 * sw + 1) * bpp], 496 s1[(3 * sw + 2) * bpp], 497 s1[(3 * sw + 3) * bpp], wx); 498 } 499 else 500 d = c; 501 502 v1 = icerp(a, b, c, d, wy); 503 504 if(iz > 0) 505 { 506 b = icerp(s0[(sw + 0) * bpp], 507 s0[(sw + 1) * bpp], 508 s0[(sw + 2) * bpp], 509 s0[(sw + 3) * bpp], wx); 510 if(iy > 0) 511 { 512 a = icerp(s0[ 0], 513 s0[ bpp], 514 s0[2 * bpp], 515 s0[3 * bpp], wx); 516 } 517 else 518 a = b; 519 520 c = icerp(s0[(2 * sw + 0) * bpp], 521 s0[(2 * sw + 1) * bpp], 522 s0[(2 * sw + 2) * bpp], 523 s0[(2 * sw + 3) * bpp], wx); 524 if(iy < dh - 1) 525 { 526 d = icerp(s0[(3 * sw + 0) * bpp], 527 s0[(3 * sw + 1) * bpp], 528 s0[(3 * sw + 2) * bpp], 529 s0[(3 * sw + 3) * bpp], wx); 530 } 531 else 532 d = c; 533 534 v0 = icerp(a, b, c, d, wy); 535 } 536 else 537 v0 = v1; 538 539 b = icerp(s2[(sw + 0) * bpp], 540 s2[(sw + 1) * bpp], 541 s2[(sw + 2) * bpp], 542 s2[(sw + 3) * bpp], wx); 543 if(iy > 0) 544 { 545 a = icerp(s2[ 0], 546 s2[ bpp], 547 s2[2 * bpp], 548 s2[3 * bpp], wx); 549 } 550 else 551 a = b; 552 553 c = icerp(s2[(2 * sw + 0) * bpp], 554 s2[(2 * sw + 1) * bpp], 555 s2[(2 * sw + 2) * bpp], 556 s2[(2 * sw + 3) * bpp], wx); 557 if(iy < dh - 1) 558 { 559 d = icerp(s2[(3 * sw + 0) * bpp], 560 s2[(3 * sw + 1) * bpp], 561 s2[(3 * sw + 2) * bpp], 562 s2[(3 * sw + 3) * bpp], wx); 563 } 564 else 565 d = c; 566 567 v2 = icerp(a, b, c, d, wy); 568 569 if(iz < dd - 1) 570 { 571 b = icerp(s3[(sw + 0) * bpp], 572 s3[(sw + 1) * bpp], 573 s3[(sw + 2) * bpp], 574 s3[(sw + 3) * bpp], wx); 575 if(iy > 0) 576 { 577 a = icerp(s3[ 0], 578 s3[ bpp], 579 s3[2 * bpp], 580 s3[3 * bpp], wx); 581 } 582 else 583 a = b; 584 585 c = icerp(s3[(2 * sw + 0) * bpp], 586 s3[(2 * sw + 1) * bpp], 587 s3[(2 * sw + 2) * bpp], 588 s3[(2 * sw + 3) * bpp], wx); 589 if(iy < dh - 1) 590 { 591 d = icerp(s3[(3 * sw + 0) * bpp], 592 s3[(3 * sw + 1) * bpp], 593 s3[(3 * sw + 2) * bpp], 594 s3[(3 * sw + 3) * bpp], wx); 595 } 596 else 597 d = c; 598 599 v3 = icerp(a, b, c, d, wy); 600 } 601 else 602 v3 = v2; 603 604 val = icerp(v0, v1, v2, v3, wz); 605 606 if(val < 0) val = 0; 607 if(val > 255) val = 255; 608 609 dst[(z * dslice) + (y * dstride) + (x * bpp) + n] = val; 610 611 ++s0; 612 ++s1; 613 ++s2; 614 ++s3; 615 } 616 } 617 } 618 } 619 } 620 621 int generate_volume_mipmaps(unsigned char *dst, unsigned char *src, 622 unsigned int width, unsigned int height, 623 unsigned int depth, int bpp, int indexed, 624 int mipmaps, int filter) 625 { 626 int i; 627 unsigned int sw, sh, sd; 628 unsigned int dw, dh, dd; 629 unsigned char *s, *d; 630 volmipmapfunc_t mipmap_func = NULL; 631 632 if(indexed) 633 mipmap_func = scale_volume_image_nearest; 634 else 635 { 636 switch(filter) 637 { 638 case DDS_MIPMAP_NEAREST: mipmap_func = scale_volume_image_nearest; break; 639 case DDS_MIPMAP_BICUBIC: mipmap_func = scale_volume_image_cubic; break; 640 case DDS_MIPMAP_BILINEAR: 641 default: mipmap_func = scale_volume_image_bilinear; break; 642 } 643 } 644 645 memcpy(dst, src, width * height * depth * bpp); 646 647 s = dst; 648 d = dst + (width * height * depth * bpp); 649 650 sw = width; 651 sh = height; 652 sd = depth; 653 654 for(i = 1; i < mipmaps; ++i) 655 { 656 dw = sw >> 1; 657 dh = sh >> 1; 658 dd = sd >> 1; 659 if(dw < 1) dw = 1; 660 if(dh < 1) dh = 1; 661 if(dd < 1) dd = 1; 662 663 mipmap_func(d, dw, dh, dd, s, sw, sh, sd, bpp); 664 665 s = d; 666 sw = dw; 667 sh = dh; 668 sd = dd; 669 d += (dw * dh * dd * bpp); 670 } 671 672 return(1); 673 }
| ViewVC Help | |
| Powered by ViewVC 1.0.4 |