Parent Directory
|
Revision Log
Release 2.0.2 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 <string.h> 24 #include <math.h> 25 26 #include "dds.h" 27 #include "mipmap.h" 28 29 int get_num_mipmaps(int width, int height) 30 { 31 int w = width << 1; 32 int h = height << 1; 33 int n = 0; 34 35 while(w != 1 || h != 1) 36 { 37 if(w > 1) w >>= 1; 38 if(h > 1) h >>= 1; 39 ++n; 40 } 41 42 return(n); 43 } 44 45 unsigned int get_mipmapped_size(int width, int height, int bpp, 46 int level, int num, int format) 47 { 48 int w, h, n = 0; 49 unsigned int size = 0; 50 51 w = width >> level; 52 h = height >> level; 53 if(w == 0) w = 1; 54 if(h == 0) h = 1; 55 w <<= 1; 56 h <<= 1; 57 58 while(n < num && (w != 1 || h != 1)) 59 { 60 if(w > 1) w >>= 1; 61 if(h > 1) h >>= 1; 62 if(format == DDS_COMPRESS_NONE) 63 size += (w * h); 64 else 65 size += ((w + 3) >> 2) * ((h + 3) >> 2); 66 ++n; 67 } 68 69 if(format == DDS_COMPRESS_NONE) 70 size *= bpp; 71 else 72 { 73 if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4) 74 size *= 8; 75 else 76 size *= 16; 77 } 78 79 return(size); 80 } 81 82 unsigned int get_volume_mipmapped_size(int width, int height, 83 int depth, int bpp, int level, 84 int num, int format) 85 { 86 int w, h, d, n = 0; 87 unsigned int size = 0; 88 89 w = width >> level; 90 h = height >> level; 91 d = depth >> level; 92 if(w == 0) w = 1; 93 if(h == 0) h = 1; 94 if(d == 0) d = 1; 95 w <<= 1; 96 h <<= 1; 97 d <<= 1; 98 99 while(n < num && (w != 1 || h != 1)) 100 { 101 if(w > 1) w >>= 1; 102 if(h > 1) h >>= 1; 103 if(d > 1) d >>= 1; 104 if(format == DDS_COMPRESS_NONE) 105 size += (w * h * d); 106 else 107 size += (((w + 3) >> 2) * ((h + 3) >> 2) * d); 108 ++n; 109 } 110 111 if(format == DDS_COMPRESS_NONE) 112 size *= bpp; 113 else 114 { 115 if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4) 116 size *= 8; 117 else 118 size *= 16; 119 } 120 121 return(size); 122 } 123 124 float cubic_interpolate(float a, float b, float c, float d, float x) 125 { 126 float v0, v1, v2, v3, x2; 127 128 x2 = x * x; 129 v0 = d - c - a + b; 130 v1 = a - b - v0; 131 v2 = c - a; 132 v3 = b; 133 134 return(v0 * x * x2 + v1 * x2 + v2 * x + v3); 135 } 136 137 static void scale_image_cubic(unsigned char *dst, int dw, int dh, 138 unsigned char *src, int sw, int sh, 139 int bpp) 140 { 141 int n, x, y; 142 int ix, iy; 143 float fx, fy; 144 float dx, dy, val; 145 float r0, r1, r2, r3; 146 int srowbytes = sw * bpp; 147 int drowbytes = dw * bpp; 148 149 #define VAL(x, y, c) \ 150 (float)src[((y) < 0 ? 0 : (y) >= sh ? sh - 1 : (y)) * srowbytes + \ 151 (((x) < 0 ? 0 : (x) >= sw ? sw - 1 : (x)) * bpp) + c] 152 153 for(y = 0; y < dh; ++y) 154 { 155 fy = ((float)y / (float)dh) * (float)sh; 156 iy = (int)fy; 157 dy = fy - (float)iy; 158 for(x = 0; x < dw; ++x) 159 { 160 fx = ((float)x / (float)dw) * (float)sw; 161 ix = (int)fx; 162 dx = fx - (float)ix; 163 164 for(n = 0; n < bpp; ++n) 165 { 166 r0 = cubic_interpolate(VAL(ix - 1, iy - 1, n), 167 VAL(ix, iy - 1, n), 168 VAL(ix + 1, iy - 1, n), 169 VAL(ix + 2, iy - 1, n), dx); 170 r1 = cubic_interpolate(VAL(ix - 1, iy, n), 171 VAL(ix, iy, n), 172 VAL(ix + 1, iy, n), 173 VAL(ix + 2, iy, n), dx); 174 r2 = cubic_interpolate(VAL(ix - 1, iy + 1, n), 175 VAL(ix, iy + 1, n), 176 VAL(ix + 1, iy + 1, n), 177 VAL(ix + 2, iy + 1, n), dx); 178 r3 = cubic_interpolate(VAL(ix - 1, iy + 2, n), 179 VAL(ix, iy + 2, n), 180 VAL(ix + 1, iy + 2, n), 181 VAL(ix + 2, iy + 2, n), dx); 182 val = cubic_interpolate(r0, r1, r2, r3, dy); 183 if(val < 0) val = 0; 184 if(val > 255) val = 255; 185 dst[y * drowbytes + (x * bpp) + n] = (unsigned char)val; 186 } 187 } 188 } 189 #undef VAL 190 } 191 192 static void scale_image_nearest(unsigned char *dst, int dw, int dh, 193 unsigned char *src, int sw, int sh, 194 int bpp) 195 { 196 int n, x, y; 197 int ix, iy; 198 int srowbytes = sw * bpp; 199 int drowbytes = dw * bpp; 200 201 for(y = 0; y < dh; ++y) 202 { 203 iy = (y * sh + sh / 2) / dh; 204 for(x = 0; x < dw; ++x) 205 { 206 ix = (x * sw + sw / 2) / dw; 207 for(n = 0; n < bpp; ++n) 208 { 209 dst[y * drowbytes + (x * bpp) + n] = 210 src[iy * srowbytes + (ix * bpp) + n]; 211 } 212 } 213 } 214 } 215 216 int generate_mipmaps(unsigned char *dst, unsigned char *src, 217 unsigned int width, unsigned int height, int bpp, 218 int indexed, int mipmaps) 219 { 220 int i; 221 unsigned int w, h; 222 unsigned int offset; 223 224 memcpy(dst, src, width * height * bpp); 225 offset = width * height * bpp; 226 227 for(i = 1; i < mipmaps; ++i) 228 { 229 w = width >> i; 230 h = height >> i; 231 if(w < 1) w = 1; 232 if(h < 1) h = 1; 233 234 if(indexed) 235 scale_image_nearest(dst + offset, w, h, src, width, height, bpp); 236 else 237 scale_image_cubic(dst + offset, w, h, src, width, height, bpp); 238 239 offset += (w * h * bpp); 240 } 241 242 return(1); 243 } 244 245 static void scale_volume_image_cubic(unsigned char *dst, int dw, int dh, int dd, 246 unsigned char *src, int sw, int sh, int sd, 247 int bpp) 248 { 249 int n, x, y, z; 250 int ix, iy, iz; 251 float fx, fy, fz; 252 float dx, dy, dz, val; 253 float r0, r1, r2, r3; 254 float v0, v1, v2, v3; 255 int srowbytes = sw * bpp; 256 int drowbytes = dw * bpp; 257 int sslicebytes = sw * sh * bpp; 258 int dslicebytes = dw * dh * bpp; 259 260 #define VAL(x, y, z, c) \ 261 (float)src[(((z) < 0 ? 0 : (z) >= sd ? sd - 1 : (z)) * sslicebytes) + \ 262 (((y) < 0 ? 0 : (y) >= sh ? sh - 1 : (y)) * srowbytes) + \ 263 (((x) < 0 ? 0 : (x) >= sw ? sw - 1 : (x)) * bpp) + c] 264 265 for(z = 0; z < dd; ++z) 266 { 267 fz = ((float)z / (float)dd) * (float)sd; 268 iz = (int)fz; 269 dz = fz - (float)iz; 270 for(y = 0; y < dh; ++y) 271 { 272 fy = ((float)y / (float)dh) * (float)sh; 273 iy = (int)fy; 274 dy = fy - (float)iy; 275 for(x = 0; x < dw; ++x) 276 { 277 fx = ((float)x / (float)dw) * (float)sw; 278 ix = (int)fx; 279 dx = fx - (float)ix; 280 for(n = 0; n < bpp; ++n) 281 { 282 r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z - 1, n), 283 VAL(ix, iy - 1, z - 1, n), 284 VAL(ix + 1, iy - 1, z - 1, n), 285 VAL(ix + 2, iy - 1, z - 1, n), dx); 286 r1 = cubic_interpolate(VAL(ix - 1, iy, z - 1, n), 287 VAL(ix, iy, z - 1, n), 288 VAL(ix + 1, iy, z - 1, n), 289 VAL(ix + 2, iy, z - 1, n), dx); 290 r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z - 1, n), 291 VAL(ix, iy + 1, z - 1, n), 292 VAL(ix + 1, iy + 1, z - 1, n), 293 VAL(ix + 2, iy + 1, z - 1, n), dx); 294 r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z - 1, n), 295 VAL(ix, iy + 2, z - 1, n), 296 VAL(ix + 1, iy + 2, z - 1, n), 297 VAL(ix + 2, iy + 2, z - 1, n), dx); 298 v0 = cubic_interpolate(r0, r1, r2, r3, dy); 299 300 r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z, n), 301 VAL(ix, iy - 1, z, n), 302 VAL(ix + 1, iy - 1, z, n), 303 VAL(ix + 2, iy - 1, z, n), dx); 304 r1 = cubic_interpolate(VAL(ix - 1, iy, z, n), 305 VAL(ix, iy, z, n), 306 VAL(ix + 1, iy, z, n), 307 VAL(ix + 2, iy, z, n), dx); 308 r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z, n), 309 VAL(ix, iy + 1, z, n), 310 VAL(ix + 1, iy + 1, z, n), 311 VAL(ix + 2, iy + 1, z, n), dx); 312 r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z, n), 313 VAL(ix, iy + 2, z, n), 314 VAL(ix + 1, iy + 2, z, n), 315 VAL(ix + 2, iy + 2, z, n), dx); 316 v1 = cubic_interpolate(r0, r1, r2, r3, dy); 317 318 r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z + 1, n), 319 VAL(ix, iy - 1, z + 1, n), 320 VAL(ix + 1, iy - 1, z + 1, n), 321 VAL(ix + 2, iy - 1, z + 1, n), dx); 322 r1 = cubic_interpolate(VAL(ix - 1, iy, z + 1, n), 323 VAL(ix, iy, z + 1, n), 324 VAL(ix + 1, iy, z + 1, n), 325 VAL(ix + 2, iy, z + 1, n), dx); 326 r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z + 1, n), 327 VAL(ix, iy + 1, z + 1, n), 328 VAL(ix + 1, iy + 1, z + 1, n), 329 VAL(ix + 2, iy + 1, z + 1, n), dx); 330 r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z + 1, n), 331 VAL(ix, iy + 2, z + 1, n), 332 VAL(ix + 1, iy + 2, z + 1, n), 333 VAL(ix + 2, iy + 2, z + 1, n), dx); 334 v2 = cubic_interpolate(r0, r1, r2, r3, dy); 335 336 r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z + 2, n), 337 VAL(ix, iy - 1, z + 2, n), 338 VAL(ix + 1, iy - 1, z + 2, n), 339 VAL(ix + 2, iy - 1, z + 2, n), dx); 340 r1 = cubic_interpolate(VAL(ix - 1, iy, z + 2, n), 341 VAL(ix, iy, z + 2, n), 342 VAL(ix + 1, iy, z + 2, n), 343 VAL(ix + 2, iy, z + 2, n), dx); 344 r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z + 2, n), 345 VAL(ix, iy + 1, z + 2, n), 346 VAL(ix + 1, iy + 1, z + 2, n), 347 VAL(ix + 2, iy + 1, z + 2, n), dx); 348 r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z + 2, n), 349 VAL(ix, iy + 2, z + 2, n), 350 VAL(ix + 1, iy + 2, z + 2, n), 351 VAL(ix + 2, iy + 2, z + 2, n), dx); 352 v3 = cubic_interpolate(r0, r1, r2, r3, dy); 353 354 val = cubic_interpolate(v0, v1, v2, v3, dz); 355 356 if(val < 0) val = 0; 357 if(val > 255) val = 255; 358 359 dst[(z * dslicebytes) + (y * drowbytes) + (x * bpp) + n] = 360 (unsigned char)val; 361 } 362 } 363 } 364 } 365 #undef VAL 366 } 367 368 static void scale_volume_image_nearest(unsigned char *dst, int dw, int dh, int dd, 369 unsigned char *src, int sw, int sh, int sd, 370 int bpp) 371 { 372 int n, x, y, z; 373 int ix, iy, iz; 374 375 for(z = 0; z < dd; ++z) 376 { 377 iz = (z * sd + sd / 2) / dd; 378 for(y = 0; y < dh; ++y) 379 { 380 iy = (y * sh + sh / 2) / dh; 381 for(x = 0; x < dw; ++x) 382 { 383 ix = (x * sw + sw / 2) / dw; 384 for(n = 0; n < bpp; ++n) 385 { 386 dst[(z * (dw * dh)) + (y * dw) + (x * bpp) + n] = 387 src[(iz * (sw * sh)) + (iy * sw) + (ix * bpp) + n]; 388 } 389 } 390 } 391 } 392 } 393 394 int generate_volume_mipmaps(unsigned char *dst, unsigned char *src, 395 unsigned int width, unsigned int height, 396 unsigned int depth, int bpp, int indexed, 397 int mipmaps) 398 { 399 int i; 400 unsigned int w, h, d; 401 unsigned int offset; 402 403 memcpy(dst, src, width * height * depth * bpp); 404 offset = width * height * depth * bpp; 405 406 for(i = 1; i < mipmaps; ++i) 407 { 408 w = width >> i; 409 h = height >> i; 410 d = depth >> i; 411 if(w < 1) w = 1; 412 if(h < 1) h = 1; 413 if(d < 1) d = 1; 414 415 if(indexed) 416 { 417 scale_volume_image_nearest(dst + offset, w, h, d, src, width, height, 418 depth, bpp); 419 } 420 else 421 { 422 scale_volume_image_cubic(dst + offset, w, h, d, src, width, height, 423 depth, bpp); 424 } 425 426 offset += (w * h * d * bpp); 427 } 428 429 return(1); 430 }
| ViewVC Help | |
| Powered by ViewVC 1.0.4 |