Parent Directory
|
Revision Log
* Update INSTALL, README * Update contact information if file headers
1 /* 2 normalmap GIMP plugin 3 4 Copyright (C) 2002-2008 Shawn Kirst <skirst@insightbb.com> 5 6 This program is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public 8 License as published by the Free Software Foundation; either 9 version 2 of the License, or (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; see the file COPYING. If not, write to 18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 Boston, MA 02111-1307, USA. 20 */ 21 22 #include <stdlib.h> 23 #include <stdio.h> 24 #include <string.h> 25 26 #include <gtk/gtk.h> 27 28 #include <libgimp/gimp.h> 29 #include <libgimp/gimpui.h> 30 31 #include "scale.h" 32 #include "preview3d.h" 33 34 #define PREVIEW_SIZE 150 35 36 enum FILTER_TYPE 37 { 38 FILTER_NONE = 0, FILTER_SOBEL_3x3, FILTER_SOBEL_5x5, FILTER_PREWITT_3x3, 39 FILTER_PREWITT_5x5, FILTER_3x3, FILTER_5x5, FILTER_7x7, FILTER_9x9, 40 MAX_FILTER_TYPE 41 }; 42 43 enum ALPHA_TYPE 44 { 45 ALPHA_NONE = 0, ALPHA_HEIGHT, ALPHA_INVERSE_HEIGHT, ALPHA_ZERO, ALPHA_ONE, 46 ALPHA_INVERT, ALPHA_MAP, MAX_ALPHA_TYPE 47 }; 48 49 enum CONVERSION_TYPE 50 { 51 CONVERT_NONE = 0, CONVERT_BIASED_RGB, CONVERT_RED, CONVERT_GREEN, 52 CONVERT_BLUE, CONVERT_MAX_RGB, CONVERT_MIN_RGB, CONVERT_COLORSPACE, 53 CONVERT_NORMALIZE_ONLY, CONVERT_DUDV_TO_NORMAL, CONVERT_HEIGHTMAP, 54 MAX_CONVERSION_TYPE 55 }; 56 57 enum DUDV_TYPE 58 { 59 DUDV_NONE, DUDV_8BIT_SIGNED, DUDV_8BIT_UNSIGNED, DUDV_16BIT_SIGNED, 60 DUDV_16BIT_UNSIGNED, 61 MAX_DUDV_TYPE 62 }; 63 64 typedef struct 65 { 66 gint filter; 67 gdouble minz; 68 gdouble scale; 69 gint wrap; 70 gint height_source; 71 gint alpha; 72 gint conversion; 73 gint dudv; 74 gint xinvert; 75 gint yinvert; 76 gint swapRGB; 77 gdouble contrast; 78 gint32 alphamap_id; 79 } NormalmapVals; 80 81 static void query(void); 82 static void run(const gchar *name, gint params, const GimpParam *param, 83 gint *nreturn_vals, GimpParam **return_vals); 84 85 static gint32 normalmap(GimpDrawable *drawable, gboolean preview_mode); 86 87 static gint normalmap_dialog(GimpDrawable *drawable); 88 89 GimpPlugInInfo PLUG_IN_INFO = 90 { 91 0, 0, query, run 92 }; 93 94 NormalmapVals nmapvals = 95 { 96 .filter = 0, 97 .minz = 0.0, 98 .scale = 1.0, 99 .wrap = 0, 100 .height_source = 0, 101 .alpha = ALPHA_NONE, 102 .conversion = CONVERT_NONE, 103 .dudv = DUDV_NONE, 104 .xinvert = 0, 105 .yinvert = 0, 106 .swapRGB = 0, 107 .contrast = 0.0, 108 .alphamap_id = 0 109 }; 110 111 static const float oneover255 = 1.0f / 255.0f; 112 113 gint runme = 0; 114 115 static GtkWidget *dialog; 116 static GtkWidget *preview; 117 118 MAIN() 119 120 static void query(void) 121 { 122 static GimpParamDef args[]= 123 { 124 {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"}, 125 {GIMP_PDB_IMAGE, "image", "Input image (unused)"}, 126 {GIMP_PDB_DRAWABLE, "drawable", "Input drawable"}, 127 {GIMP_PDB_INT32, "filter", "Filter type (0 = 4 sample, 1 = sobel 3x3, 2 = sobel 5x5, 3 = prewitt 3x3, 4 = prewitt 5x5, 5-8 = 3x3,5x5,7x7,9x9)"}, 128 {GIMP_PDB_FLOAT, "minz", "Minimun Z (0 to 1)"}, 129 {GIMP_PDB_FLOAT, "scale", "Scale (>0)"}, 130 {GIMP_PDB_INT32, "wrap", "Wrap (0 = no)"}, 131 {GIMP_PDB_INT32, "height_source", "Height source (0 = average RGB, 1 = alpha channel)"}, 132 {GIMP_PDB_INT32, "alpha", "Alpha (0 = unchanged, 1 = set to height, 2 = set to inverse height, 3 = set to 0, 4 = set to 1, 5 = invert, 6 = set to alpha map value)"}, 133 {GIMP_PDB_INT32, "conversion", "Conversion (0 = normalize only, 1 = Biased RGB, 2 = Red, 3 = Green, 4 = Blue, 5 = Max RGB, 6 = Min RGB, 7 = Colorspace, 8 = Normalize only, 9 = Convert to height map)"}, 134 {GIMP_PDB_INT32, "dudv", "DU/DV map (0 = none, 1 = 8-bit, 2 = 8-bit unsigned, 3 = 16-bit, 4 = 16-bit unsigned)"}, 135 {GIMP_PDB_INT32, "xinvert", "Invert X component of normal"}, 136 {GIMP_PDB_INT32, "yinvert", "Invert Y component of normal"}, 137 {GIMP_PDB_INT32, "swapRGB", "Swap RGB components"}, 138 {GIMP_PDB_FLOAT, "contrast", "Height contrast (0 to 1). If converting to a height map, this value is applied to the results"}, 139 {GIMP_PDB_DRAWABLE, "alphamap", "Alpha map drawable"} 140 }; 141 static gint nargs = sizeof(args) / sizeof(args[0]); 142 143 gimp_install_procedure("plug_in_normalmap", 144 "Converts image to an RGB normalmap", 145 "foo!", 146 "Shawn Kirst", 147 "Shawn Kirst", 148 "February 2002", 149 "<Image>/Filters/Map/Normalmap...", 150 "RGB*", 151 GIMP_PLUGIN, 152 nargs, 0, 153 args, NULL); 154 } 155 156 static void run(const gchar *name, gint nparams, const GimpParam *param, 157 gint *nreturn_vals, GimpParam **return_vals) 158 { 159 static GimpParam values[1]; 160 GimpDrawable *drawable; 161 GimpRunMode run_mode; 162 GimpPDBStatusType status = GIMP_PDB_SUCCESS; 163 164 run_mode = param[0].data.d_int32; 165 166 *nreturn_vals = 1; 167 *return_vals = values; 168 169 values[0].type = GIMP_PDB_STATUS; 170 values[0].data.d_status = status; 171 172 drawable = gimp_drawable_get(param[2].data.d_drawable); 173 174 switch(run_mode) 175 { 176 case GIMP_RUN_INTERACTIVE: 177 gimp_ui_init("normalmap", 0); 178 gimp_get_data("plug_in_normalmap", &nmapvals); 179 if(!normalmap_dialog(drawable)) 180 { 181 gimp_drawable_detach(drawable); 182 return; 183 } 184 break; 185 case GIMP_RUN_NONINTERACTIVE: 186 if(nparams != 16) 187 status=GIMP_PDB_CALLING_ERROR; 188 else 189 { 190 nmapvals.filter = param[3].data.d_int32; 191 nmapvals.minz = param[4].data.d_float; 192 nmapvals.scale = param[5].data.d_float; 193 nmapvals.wrap = param[6].data.d_int32; 194 nmapvals.height_source = param[7].data.d_int32; 195 nmapvals.alpha = param[8].data.d_int32; 196 nmapvals.conversion = param[9].data.d_int32; 197 nmapvals.dudv = param[10].data.d_int32; 198 nmapvals.xinvert = param[11].data.d_int32; 199 nmapvals.yinvert = param[12].data.d_int32; 200 nmapvals.swapRGB = param[13].data.d_int32; 201 nmapvals.contrast = param[14].data.d_float; 202 nmapvals.alphamap_id = gimp_drawable_get(param[15].data.d_drawable)->drawable_id; 203 } 204 break; 205 case GIMP_RUN_WITH_LAST_VALS: 206 gimp_get_data("plug_in_normalmap", &nmapvals); 207 break; 208 default: 209 break; 210 } 211 212 gimp_progress_init("Creating normalmap..."); 213 214 if(normalmap(drawable,FALSE) == -1) 215 status = GIMP_PDB_EXECUTION_ERROR; 216 217 if(run_mode != GIMP_RUN_NONINTERACTIVE) 218 gimp_displays_flush(); 219 220 if(run_mode == GIMP_RUN_INTERACTIVE) 221 gimp_set_data("plug_in_normalmap", &nmapvals, sizeof(nmapvals)); 222 223 values[0].data.d_status = status; 224 225 gimp_drawable_detach(drawable); 226 } 227 228 #ifndef min 229 #define min(a,b) ((a)<(b) ? (a) : (b)) 230 #endif 231 #ifndef max 232 #define max(a,b) ((a)>(b) ? (a) : (b)) 233 #endif 234 235 #define SQR(x) ((x) * (x)) 236 #define LERP(a,b,c) ((a) + ((b) - (a)) * (c)) 237 238 static inline void NORMALIZE(float *v) 239 { 240 float len = sqrtf(SQR(v[0]) + SQR(v[1]) + SQR(v[2])); 241 242 if(len > 1e-04f) 243 { 244 len = 1.0f / len; 245 v[0] *= len; 246 v[1] *= len; 247 v[2] *= len; 248 } 249 else 250 v[0] = v[1] = v[2] = 0; 251 } 252 253 typedef struct 254 { 255 int x,y; 256 float w; 257 } kernel_element; 258 259 static void make_kernel(kernel_element *k, float *weights, int size) 260 { 261 int x, y, idx; 262 263 for(y = 0; y < size; ++y) 264 { 265 for(x = 0; x < size; ++x) 266 { 267 idx = x + y * size; 268 k[idx].x = x - (size / 2); 269 k[idx].y = (size / 2) - y; 270 k[idx].w = weights[idx]; 271 } 272 } 273 } 274 275 static void rotate_array(float *dst, float *src, int size) 276 { 277 int x, y, newx, newy; 278 279 for(y = 0; y < size; ++y) 280 { 281 for(x = 0; x < size; ++x) 282 { 283 newy = size - x - 1; 284 newx = y; 285 dst[newx + newy * size] = src[x + y * size]; 286 } 287 } 288 } 289 290 static int sample_alpha_map(unsigned char *pixels, int x, int y, 291 int w, int h, int sw, int sh) 292 { 293 float fx, fy, dx, dy; 294 float v, r0, r1, r2, r3; 295 int ix, iy; 296 297 fx = ((float)x / (float)sw) * (float)w; 298 fy = ((float)y / (float)sh) * (float)h; 299 ix = (int)floor(fx); 300 iy = (int)floor(fy); 301 dx = fx - (float)ix; 302 dy = fy - (float)iy; 303 304 #define VAL(x, y) \ 305 (float)pixels[((y) < 0 ? 0 : (y) >= h ? h - 1 : (y)) * w + \ 306 ((x) < 0 ? 0 : (x) >= w ? w - 1 : (x))] 307 308 r0 = cubic_interpolate(VAL(ix - 1, iy - 1), 309 VAL(ix, iy - 1), 310 VAL(ix + 1, iy - 1), 311 VAL(ix + 2, iy - 1), dx); 312 r1 = cubic_interpolate(VAL(ix - 1, iy ), 313 VAL(ix, iy ), 314 VAL(ix + 1, iy ), 315 VAL(ix + 2, iy ), dx); 316 r2 = cubic_interpolate(VAL(ix - 1, iy + 1), 317 VAL(ix, iy + 1), 318 VAL(ix + 1, iy + 1), 319 VAL(ix + 2, iy + 1), dx); 320 r3 = cubic_interpolate(VAL(ix - 1, iy + 2), 321 VAL(ix, iy + 2), 322 VAL(ix + 1, iy + 2), 323 VAL(ix + 2, iy + 2), dx); 324 #undef VAL 325 326 v = cubic_interpolate(r0, r1, r2, r3, dy); 327 328 if(v < 0) v = 0; 329 if(v > 255) v = 255; 330 331 return((unsigned char)v); 332 } 333 334 static void make_heightmap(unsigned char *image, int w, int h, int bpp) 335 { 336 unsigned int i, num_pixels = w * h; 337 int x, y; 338 float v, hmin, hmax; 339 float *s, *r; 340 341 s = (float*)g_malloc(w * h * 3 * sizeof(float)); 342 if(s == 0) 343 { 344 g_message("Memory allocation error!"); 345 return; 346 } 347 r = (float*)g_malloc(w * h * 4 * sizeof(float)); 348 if(r == 0) 349 { 350 g_free(s); 351 g_message("Memory allocation error!"); 352 return; 353 } 354 355 /* scale into 0 to 1 range, make signed -1 to 1 */ 356 for(i = 0; i < num_pixels; ++i) 357 { 358 s[3 * i + 0] = (((float)image[bpp * i + 0] / 255.0f) - 0.5) * 2.0f; 359 s[3 * i + 1] = (((float)image[bpp * i + 1] / 255.0f) - 0.5) * 2.0f; 360 s[3 * i + 2] = (((float)image[bpp * i + 2] / 255.0f) - 0.5) * 2.0f; 361 } 362 363 memset(r, 0, w * h * 4 * sizeof(float)); 364 365 #define S(x, y, n) s[(y) * (w * 3) + ((x) * 3) + (n)] 366 #define R(x, y, n) r[(y) * (w * 4) + ((x) * 4) + (n)] 367 368 /* top-left to bottom-right */ 369 for(x = 1; x < w; ++x) 370 R(x, 0, 0) = R(x - 1, 0, 0) + S(x - 1, 0, 0); 371 for(y = 1; y < h; ++y) 372 R(0, y, 0) = R(0, y - 1, 0) + S(0, y - 1, 1); 373 for(y = 1; y < h; ++y) 374 { 375 for(x = 1; x < w; ++x) 376 { 377 R(x, y, 0) = (R(x, y - 1, 0) + R(x - 1, y, 0) + 378 S(x - 1, y, 0) + S(x, y - 1, 1)) * 0.5f; 379 } 380 } 381 382 /* top-right to bottom-left */ 383 for(x = w - 2; x >= 0; --x) 384 R(x, 0, 1) = R(x + 1, 0, 1) - S(x + 1, 0, 0); 385 for(y = 1; y < h; ++y) 386 R(0, y, 1) = R(0, y - 1, 1) + S(0, y - 1, 1); 387 for(y = 1; y < h; ++y) 388 { 389 for(x = w - 2; x >= 0; --x) 390 { 391 R(x, y, 1) = (R(x, y - 1, 1) + R(x + 1, y, 1) - 392 S(x + 1, y, 0) + S(x, y - 1, 1)) * 0.5f; 393 } 394 } 395 396 /* bottom-left to top-right */ 397 for(x = 1; x < w; ++x) 398 R(x, 0, 2) = R(x - 1, 0, 2) + S(x - 1, 0, 0); 399 for(y = h - 2; y >= 0; --y) 400 R(0, y, 2) = R(0, y + 1, 2) - S(0, y + 1, 1); 401 for(y = h - 2; y >= 0; --y) 402 { 403 for(x = 1; x < w; ++x) 404 { 405 R(x, y, 2) = (R(x, y + 1, 2) + R(x - 1, y, 2) + 406 S(x - 1, y, 0) - S(x, y + 1, 1)) * 0.5f; 407 } 408 } 409 410 /* bottom-right to top-left */ 411 for(x = w - 2; x >= 0; --x) 412 R(x, 0, 3) = R(x + 1, 0, 3) - S(x + 1, 0, 0); 413 for(y = h - 2; y >= 0; --y) 414 R(0, y, 3) = R(0, y + 1, 3) - S(0, y + 1, 1); 415 for(y = h - 2; y >= 0; --y) 416 { 417 for(x = w - 2; x >= 0; --x) 418 { 419 R(x, y, 3) = (R(x, y + 1, 3) + R(x + 1, y, 3) - 420 S(x + 1, y, 0) - S(x, y + 1, 1)) * 0.5f; 421 } 422 } 423 424 #undef S 425 #undef R 426 427 /* accumulate, find min/max */ 428 hmin = 1e10f; 429 hmax = -1e10f; 430 for(i = 0; i < num_pixels; ++i) 431 { 432 r[4 * i] += r[4 * i + 1] + r[4 * i + 2] + r[4 * i + 3]; 433 if(r[4 * i] < hmin) hmin = r[4 * i]; 434 if(r[4 * i] > hmax) hmax = r[4 * i]; 435 } 436 437 /* scale into 0 - 1 range */ 438 for(i = 0; i < num_pixels; ++i) 439 { 440 v = (r[4 * i] - hmin) / (hmax - hmin); 441 /* adjust contrast */ 442 v = (v - 0.5f) * nmapvals.contrast + v; 443 if(v < 0) v = 0; 444 if(v > 1) v = 1; 445 r[4 * i] = v; 446 } 447 448 /* write out results */ 449 for(i = 0; i < num_pixels; ++i) 450 { 451 v = r[4 * i] * 255.0f; 452 image[bpp * i + 0] = (unsigned char)v; 453 image[bpp * i + 1] = (unsigned char)v; 454 image[bpp * i + 2] = (unsigned char)v; 455 } 456 457 g_free(s); 458 g_free(r); 459 } 460 461 static gint32 normalmap(GimpDrawable *drawable, gboolean preview_mode) 462 { 463 gint x, y; 464 gint width, height, bpp, rowbytes, pw, ph, amap_w = 0, amap_h = 0; 465 guchar *d, *dst, *s, *src, *tmp, *amap = 0; 466 float *heights; 467 float val, du, dv, n[3], weight; 468 float rgb_bias[3]; 469 int i, num_elements = 0; 470 kernel_element *kernel_du = 0; 471 kernel_element *kernel_dv = 0; 472 GimpPixelRgn src_rgn, dst_rgn, amap_rgn; 473 GdkCursor *cursor = 0; 474 475 if(nmapvals.filter < 0 || nmapvals.filter >= MAX_FILTER_TYPE) 476 nmapvals.filter = FILTER_NONE; 477 if(drawable->bpp != 4) nmapvals.height_source = 0; 478 if(drawable->bpp != 4 && (nmapvals.dudv == DUDV_16BIT_SIGNED || 479 nmapvals.dudv == DUDV_16BIT_UNSIGNED)) 480 nmapvals.dudv = DUDV_NONE; 481 482 width = drawable->width; 483 height = drawable->height; 484 bpp = drawable->bpp; 485 rowbytes = width * bpp; 486 487 dst = g_malloc(width * height * bpp); 488 if(dst == 0) 489 { 490 g_message("Memory allocation error!"); 491 return(-1); 492 } 493 494 src = g_malloc(width * height * bpp); 495 if(src == 0) 496 { 497 g_message("Memory allocation error!"); 498 return(-1); 499 } 500 501 heights = g_new(float, width * height); 502 if(heights == 0) 503 { 504 g_message("Memory allocation error!"); 505 return(-1); 506 } 507 508 if(!nmapvals.dudv && drawable->bpp == 4 && nmapvals.alpha == ALPHA_MAP && 509 nmapvals.alphamap_id != 0) 510 { 511 GimpDrawable *alphamap = gimp_drawable_get(nmapvals.alphamap_id); 512 513 amap_w = alphamap->width; 514 amap_h = alphamap->height; 515 516 amap = g_malloc(amap_w * amap_h); 517 518 gimp_pixel_rgn_init(&amap_rgn, alphamap, 0, 0, amap_w, amap_h, 0, 0); 519 gimp_pixel_rgn_get_rect(&amap_rgn, amap, 0, 0, amap_w, amap_h); 520 } 521 522 gimp_pixel_rgn_init(&src_rgn, drawable, 0, 0, width, height, 0, 0); 523 gimp_pixel_rgn_get_rect(&src_rgn, src, 0, 0, width, height); 524 525 switch(nmapvals.filter) 526 { 527 case FILTER_NONE: 528 num_elements = 2; 529 kernel_du = (kernel_element*)g_malloc(2 * sizeof(kernel_element)); 530 kernel_dv = (kernel_element*)g_malloc(2 * sizeof(kernel_element)); 531 532 kernel_du[0].x = -1; kernel_du[0].y = 0; kernel_du[0].w = -0.5f; 533 kernel_du[1].x = 1; kernel_du[1].y = 0; kernel_du[1].w = 0.5f; 534 535 kernel_dv[0].x = 0; kernel_dv[0].y = 1; kernel_dv[0].w = 0.5f; 536 kernel_dv[1].x = 0; kernel_dv[1].y = -1; kernel_dv[1].w = -0.5f; 537 538 break; 539 case FILTER_SOBEL_3x3: 540 num_elements = 6; 541 kernel_du = (kernel_element*)g_malloc(6 * sizeof(kernel_element)); 542 kernel_dv = (kernel_element*)g_malloc(6 * sizeof(kernel_element)); 543 544 kernel_du[0].x = -1; kernel_du[0].y = 1; kernel_du[0].w = -1.0f; 545 kernel_du[1].x = -1; kernel_du[1].y = 0; kernel_du[1].w = -2.0f; 546 kernel_du[2].x = -1; kernel_du[2].y = -1; kernel_du[2].w = -1.0f; 547 kernel_du[3].x = 1; kernel_du[3].y = 1; kernel_du[3].w = 1.0f; 548 kernel_du[4].x = 1; kernel_du[4].y = 0; kernel_du[4].w = 2.0f; 549 kernel_du[5].x = 1; kernel_du[5].y = -1; kernel_du[5].w = 1.0f; 550 551 kernel_dv[0].x = -1; kernel_dv[0].y = 1; kernel_dv[0].w = 1.0f; 552 kernel_dv[1].x = 0; kernel_dv[1].y = 1; kernel_dv[1].w = 2.0f; 553 kernel_dv[2].x = 1; kernel_dv[2].y = 1; kernel_dv[2].w = 1.0f; 554 kernel_dv[3].x = -1; kernel_dv[3].y = -1; kernel_dv[3].w = -1.0f; 555 kernel_dv[4].x = 0; kernel_dv[4].y = -1; kernel_dv[4].w = -2.0f; 556 kernel_dv[5].x = 1; kernel_dv[5].y = -1; kernel_dv[5].w = -1.0f; 557 558 break; 559 case FILTER_SOBEL_5x5: 560 num_elements = 20; 561 kernel_du = (kernel_element*)g_malloc(20 * sizeof(kernel_element)); 562 kernel_dv = (kernel_element*)g_malloc(20 * sizeof(kernel_element)); 563 564 kernel_du[ 0].x = -2; kernel_du[ 0].y = 2; kernel_du[ 0].w = -1.0f; 565 kernel_du[ 1].x = -2; kernel_du[ 1].y = 1; kernel_du[ 1].w = -4.0f; 566 kernel_du[ 2].x = -2; kernel_du[ 2].y = 0; kernel_du[ 2].w = -6.0f; 567 kernel_du[ 3].x = -2; kernel_du[ 3].y = -1; kernel_du[ 3].w = -4.0f; 568 kernel_du[ 4].x = -2; kernel_du[ 4].y = -2; kernel_du[ 4].w = -1.0f; 569 kernel_du[ 5].x = -1; kernel_du[ 5].y = 2; kernel_du[ 5].w = -2.0f; 570 kernel_du[ 6].x = -1; kernel_du[ 6].y = 1; kernel_du[ 6].w = -8.0f; 571 kernel_du[ 7].x = -1; kernel_du[ 7].y = 0; kernel_du[ 7].w = -12.0f; 572 kernel_du[ 8].x = -1; kernel_du[ 8].y = -1; kernel_du[ 8].w = -8.0f; 573 kernel_du[ 9].x = -1; kernel_du[ 9].y = -2; kernel_du[ 9].w = -2.0f; 574 kernel_du[10].x = 1; kernel_du[10].y = 2; kernel_du[10].w = 2.0f; 575 kernel_du[11].x = 1; kernel_du[11].y = 1; kernel_du[11].w = 8.0f; 576 kernel_du[12].x = 1; kernel_du[12].y = 0; kernel_du[12].w = 12.0f; 577 kernel_du[13].x = 1; kernel_du[13].y = -1; kernel_du[13].w = 8.0f; 578 kernel_du[14].x = 1; kernel_du[14].y = -2; kernel_du[14].w = 2.0f; 579 kernel_du[15].x = 2; kernel_du[15].y = 2; kernel_du[15].w = 1.0f; 580 kernel_du[16].x = 2; kernel_du[16].y = 1; kernel_du[16].w = 4.0f; 581 kernel_du[17].x = 2; kernel_du[17].y = 0; kernel_du[17].w = 6.0f; 582 kernel_du[18].x = 2; kernel_du[18].y = -1; kernel_du[18].w = 4.0f; 583 kernel_du[19].x = 2; kernel_du[19].y = -2; kernel_du[19].w = 1.0f; 584 585 kernel_dv[ 0].x = -2; kernel_dv[ 0].y = 2; kernel_dv[ 0].w = 1.0f; 586 kernel_dv[ 1].x = -1; kernel_dv[ 1].y = 2; kernel_dv[ 1].w = 4.0f; 587 kernel_dv[ 2].x = 0; kernel_dv[ 2].y = 2; kernel_dv[ 2].w = 6.0f; 588 kernel_dv[ 3].x = 1; kernel_dv[ 3].y = 2; kernel_dv[ 3].w = 4.0f; 589 kernel_dv[ 4].x = 2; kernel_dv[ 4].y = 2; kernel_dv[ 4].w = 1.0f; 590 kernel_dv[ 5].x = -2; kernel_dv[ 5].y = 1; kernel_dv[ 5].w = 2.0f; 591 kernel_dv[ 6].x = -1; kernel_dv[ 6].y = 1; kernel_dv[ 6].w = 8.0f; 592 kernel_dv[ 7].x = 0; kernel_dv[ 7].y = 1; kernel_dv[ 7].w = 12.0f; 593 kernel_dv[ 8].x = 1; kernel_dv[ 8].y = 1; kernel_dv[ 8].w = 8.0f; 594 kernel_dv[ 9].x = 2; kernel_dv[ 9].y = 1; kernel_dv[ 9].w = 2.0f; 595 kernel_dv[10].x = -2; kernel_dv[10].y = -1; kernel_dv[10].w = -2.0f; 596 kernel_dv[11].x = -1; kernel_dv[11].y = -1; kernel_dv[11].w = -8.0f; 597 kernel_dv[12].x = 0; kernel_dv[12].y = -1; kernel_dv[12].w = -12.0f; 598 kernel_dv[13].x = 1; kernel_dv[13].y = -1; kernel_dv[13].w = -8.0f; 599 kernel_dv[14].x = 2; kernel_dv[14].y = -1; kernel_dv[14].w = -2.0f; 600 kernel_dv[15].x = -2; kernel_dv[15].y = -2; kernel_dv[15].w = -1.0f; 601 kernel_dv[16].x = -1; kernel_dv[16].y = -2; kernel_dv[16].w = -4.0f; 602 kernel_dv[17].x = 0; kernel_dv[17].y = -2; kernel_dv[17].w = -6.0f; 603 kernel_dv[18].x = 1; kernel_dv[18].y = -2; kernel_dv[18].w = -4.0f; 604 kernel_dv[19].x = 2; kernel_dv[19].y = -2; kernel_dv[19].w = -1.0f; 605 606 break; 607 case FILTER_PREWITT_3x3: 608 num_elements = 6; 609 kernel_du = (kernel_element*)g_malloc(6 * sizeof(kernel_element)); 610 kernel_dv = (kernel_element*)g_malloc(6 * sizeof(kernel_element)); 611 612 kernel_du[0].x = -1; kernel_du[0].y = 1; kernel_du[0].w = -1.0f; 613 kernel_du[1].x = -1; kernel_du[1].y = 0; kernel_du[1].w = -1.0f; 614 kernel_du[2].x = -1; kernel_du[2].y = -1; kernel_du[2].w = -1.0f; 615 kernel_du[3].x = 1; kernel_du[3].y = 1; kernel_du[3].w = 1.0f; 616 kernel_du[4].x = 1; kernel_du[4].y = 0; kernel_du[4].w = 1.0f; 617 kernel_du[5].x = 1; kernel_du[5].y = -1; kernel_du[5].w = 1.0f; 618 619 kernel_dv[0].x = -1; kernel_dv[0].y = 1; kernel_dv[0].w = 1.0f; 620 kernel_dv[1].x = 0; kernel_dv[1].y = 1; kernel_dv[1].w = 1.0f; 621 kernel_dv[2].x = 1; kernel_dv[2].y = 1; kernel_dv[2].w = 1.0f; 622 kernel_dv[3].x = -1; kernel_dv[3].y = -1; kernel_dv[3].w = -1.0f; 623 kernel_dv[4].x = 0; kernel_dv[4].y = -1; kernel_dv[4].w = -1.0f; 624 kernel_dv[5].x = 1; kernel_dv[5].y = -1; kernel_dv[5].w = -1.0f; 625 626 break; 627 case FILTER_PREWITT_5x5: 628 num_elements = 20; 629 kernel_du = (kernel_element*)g_malloc(20 * sizeof(kernel_element)); 630 kernel_dv = (kernel_element*)g_malloc(20 * sizeof(kernel_element)); 631 632 kernel_du[ 0].x = -2; kernel_du[ 0].y = 2; kernel_du[ 0].w = -1.0f; 633 kernel_du[ 1].x = -2; kernel_du[ 1].y = 1; kernel_du[ 1].w = -1.0f; 634 kernel_du[ 2].x = -2; kernel_du[ 2].y = 0; kernel_du[ 2].w = -1.0f; 635 kernel_du[ 3].x = -2; kernel_du[ 3].y = -1; kernel_du[ 3].w = -1.0f; 636 kernel_du[ 4].x = -2; kernel_du[ 4].y = -2; kernel_du[ 4].w = -1.0f; 637 kernel_du[ 5].x = -1; kernel_du[ 5].y = 2; kernel_du[ 5].w = -2.0f; 638 kernel_du[ 6].x = -1; kernel_du[ 6].y = 1; kernel_du[ 6].w = -2.0f; 639 kernel_du[ 7].x = -1; kernel_du[ 7].y = 0; kernel_du[ 7].w = -2.0f; 640 kernel_du[ 8].x = -1; kernel_du[ 8].y = -1; kernel_du[ 8].w = -2.0f; 641 kernel_du[ 9].x = -1; kernel_du[ 9].y = -2; kernel_du[ 9].w = -2.0f; 642 kernel_du[10].x = 1; kernel_du[10].y = 2; kernel_du[10].w = 2.0f; 643 kernel_du[11].x = 1; kernel_du[11].y = 1; kernel_du[11].w = 2.0f; 644 kernel_du[12].x = 1; kernel_du[12].y = 0; kernel_du[12].w = 2.0f; 645 kernel_du[13].x = 1; kernel_du[13].y = -1; kernel_du[13].w = 2.0f; 646 kernel_du[14].x = 1; kernel_du[14].y = -2; kernel_du[14].w = 2.0f; 647 kernel_du[15].x = 2; kernel_du[15].y = 2; kernel_du[15].w = 1.0f; 648 kernel_du[16].x = 2; kernel_du[16].y = 1; kernel_du[16].w = 1.0f; 649 kernel_du[17].x = 2; kernel_du[17].y = 0; kernel_du[17].w = 1.0f; 650 kernel_du[18].x = 2; kernel_du[18].y = -1; kernel_du[18].w = 1.0f; 651 kernel_du[19].x = 2; kernel_du[19].y = -2; kernel_du[19].w = 1.0f; 652 653 kernel_dv[ 0].x = -2; kernel_dv[ 0].y = 2; kernel_dv[ 0].w = 1.0f; 654 kernel_dv[ 1].x = -1; kernel_dv[ 1].y = 2; kernel_dv[ 1].w = 1.0f; 655 kernel_dv[ 2].x = 0; kernel_dv[ 2].y = 2; kernel_dv[ 2].w = 1.0f; 656 kernel_dv[ 3].x = 1; kernel_dv[ 3].y = 2; kernel_dv[ 3].w = 1.0f; 657 kernel_dv[ 4].x = 2; kernel_dv[ 4].y = 2; kernel_dv[ 4].w = 1.0f; 658 kernel_dv[ 5].x = -2; kernel_dv[ 5].y = 1; kernel_dv[ 5].w = 2.0f; 659 kernel_dv[ 6].x = -1; kernel_dv[ 6].y = 1; kernel_dv[ 6].w = 2.0f; 660 kernel_dv[ 7].x = 0; kernel_dv[ 7].y = 1; kernel_dv[ 7].w = 2.0f; 661 kernel_dv[ 8].x = 1; kernel_dv[ 8].y = 1; kernel_dv[ 8].w = 2.0f; 662 kernel_dv[ 9].x = 2; kernel_dv[ 9].y = 1; kernel_dv[ 9].w = 2.0f; 663 kernel_dv[10].x = -2; kernel_dv[10].y = -1; kernel_dv[10].w = -2.0f; 664 kernel_dv[11].x = -1; kernel_dv[11].y = -1; kernel_dv[11].w = -2.0f; 665 kernel_dv[12].x = 0; kernel_dv[12].y = -1; kernel_dv[12].w = -2.0f; 666 kernel_dv[13].x = 1; kernel_dv[13].y = -1; kernel_dv[13].w = -2.0f; 667 kernel_dv[14].x = 2; kernel_dv[14].y = -1; kernel_dv[14].w = -2.0f; 668 kernel_dv[15].x = -2; kernel_dv[15].y = -2; kernel_dv[15].w = -1.0f; 669 kernel_dv[16].x = -1; kernel_dv[16].y = -2; kernel_dv[16].w = -1.0f; 670 kernel_dv[17].x = 0; kernel_dv[17].y = -2; kernel_dv[17].w = -1.0f; 671 kernel_dv[18].x = 1; kernel_dv[18].y = -2; kernel_dv[18].w = -1.0f; 672 kernel_dv[19].x = 2; kernel_dv[19].y = -2; kernel_dv[19].w = -1.0f; 673 674 break; 675 case FILTER_3x3: 676 num_elements = 6; 677 kernel_du = (kernel_element*)g_malloc(6 * sizeof(kernel_element)); 678 kernel_dv = (kernel_element*)g_malloc(6 * sizeof(kernel_element)); 679 680 weight = 1.0f / 6.0f; 681 682 kernel_du[0].x = -1; kernel_du[0].y = 1; kernel_du[0].w = -weight; 683 kernel_du[1].x = -1; kernel_du[1].y = 0; kernel_du[1].w = -weight; 684 kernel_du[2].x = -1; kernel_du[2].y = -1; kernel_du[2].w = -weight; 685 kernel_du[3].x = 1; kernel_du[3].y = 1; kernel_du[3].w = weight; 686 kernel_du[4].x = 1; kernel_du[4].y = 0; kernel_du[4].w = weight; 687 kernel_du[5].x = 1; kernel_du[5].y = -1; kernel_du[5].w = weight; 688 689 kernel_dv[0].x = -1; kernel_dv[0].y = 1; kernel_dv[0].w = weight; 690 kernel_dv[1].x = 0; kernel_dv[1].y = 1; kernel_dv[1].w = weight; 691 kernel_dv[2].x = 1; kernel_dv[2].y = 1; kernel_dv[2].w = weight; 692 kernel_dv[3].x = -1; kernel_dv[3].y = -1; kernel_dv[3].w = -weight; 693 kernel_dv[4].x = 0; kernel_dv[4].y = -1; kernel_dv[4].w = -weight; 694 kernel_dv[5].x = 1; kernel_dv[5].y = -1; kernel_dv[5].w = -weight; 695 break; 696 case FILTER_5x5: 697 { 698 int n; 699 float usum = 0, vsum = 0; 700 float wt22 = 1.0f / 16.0f; 701 float wt12 = 1.0f / 10.0f; 702 float wt02 = 1.0f / 8.0f; 703 float wt11 = 1.0f / 2.8f; 704 num_elements = 20; 705 kernel_du = (kernel_element*)g_malloc(20 * sizeof(kernel_element)); 706 kernel_dv = (kernel_element*)g_malloc(20 * sizeof(kernel_element)); 707 708 kernel_du[0 ].x = -2; kernel_du[0 ].y = 2; kernel_du[0 ].w = -wt22; 709 kernel_du[1 ].x = -1; kernel_du[1 ].y = 2; kernel_du[1 ].w = -wt12; 710 kernel_du[2 ].x = 1; kernel_du[2 ].y = 2; kernel_du[2 ].w = wt12; 711 kernel_du[3 ].x = 2; kernel_du[3 ].y = 2; kernel_du[3 ].w = wt22; 712 kernel_du[4 ].x = -2; kernel_du[4 ].y = 1; kernel_du[4 ].w = -wt12; 713 kernel_du[5 ].x = -1; kernel_du[5 ].y = 1; kernel_du[5 ].w = -wt11; 714 kernel_du[6 ].x = 1; kernel_du[6 ].y = 1; kernel_du[6 ].w = wt11; 715 kernel_du[7 ].x = 2; kernel_du[7 ].y = 1; kernel_du[7 ].w = wt12; 716 kernel_du[8 ].x = -2; kernel_du[8 ].y = 0; kernel_du[8 ].w = -wt02; 717 kernel_du[9 ].x = -1; kernel_du[9 ].y = 0; kernel_du[9 ].w = -0.5f; 718 kernel_du[10].x = 1; kernel_du[10].y = 0; kernel_du[10].w = 0.5f; 719 kernel_du[11].x = 2; kernel_du[11].y = 0; kernel_du[11].w = wt02; 720 kernel_du[12].x = -2; kernel_du[12].y = -1; kernel_du[12].w = -wt12; 721 kernel_du[13].x = -1; kernel_du[13].y = -1; kernel_du[13].w = -wt11; 722 kernel_du[14].x = 1; kernel_du[14].y = -1; kernel_du[14].w = wt11; 723 kernel_du[15].x = 2; kernel_du[15].y = -1; kernel_du[15].w = wt12; 724 kernel_du[16].x = -2; kernel_du[16].y = -2; kernel_du[16].w = -wt22; 725 kernel_du[17].x = -1; kernel_du[17].y = -2; kernel_du[17].w = -wt12; 726 kernel_du[18].x = 1; kernel_du[18].y = -2; kernel_du[18].w = wt12; 727 kernel_du[19].x = 2; kernel_du[19].y = -2; kernel_du[19].w = wt22; 728 729 kernel_dv[0 ].x = -2; kernel_dv[0 ].y = 2; kernel_dv[0 ].w = wt22; 730 kernel_dv[1 ].x = -1; kernel_dv[1 ].y = 2; kernel_dv[1 ].w = wt12; 731 kernel_dv[2 ].x = 0; kernel_dv[2 ].y = 2; kernel_dv[2 ].w = 0.25f; 732 kernel_dv[3 ].x = 1; kernel_dv[3 ].y = 2; kernel_dv[3 ].w = wt12; 733 kernel_dv[4 ].x = 2; kernel_dv[4 ].y = 2; kernel_dv[4 ].w = wt22; 734 kernel_dv[5 ].x = -2; kernel_dv[5 ].y = 1; kernel_dv[5 ].w = wt12; 735 kernel_dv[6 ].x = -1; kernel_dv[6 ].y = 1; kernel_dv[6 ].w = wt11; 736 kernel_dv[7 ].x = 0; kernel_dv[7 ].y = 1; kernel_dv[7 ].w = 0.5f; 737 kernel_dv[8 ].x = 1; kernel_dv[8 ].y = 1; kernel_dv[8 ].w = wt11; 738 kernel_dv[9 ].x = 2; kernel_dv[9 ].y = 1; kernel_dv[9 ].w = wt22; 739 kernel_dv[10].x = -2; kernel_dv[10].y = -1; kernel_dv[10].w = -wt22; 740 kernel_dv[11].x = -1; kernel_dv[11].y = -1; kernel_dv[11].w = -wt11; 741 kernel_dv[12].x = 0; kernel_dv[12].y = -1; kernel_dv[12].w = -0.5f; 742 kernel_dv[13].x = 1; kernel_dv[13].y = -1; kernel_dv[13].w = -wt11; 743 kernel_dv[14].x = 2; kernel_dv[14].y = -1; kernel_dv[14].w = -wt12; 744 kernel_dv[15].x = -2; kernel_dv[15].y = -2; kernel_dv[15].w = -wt22; 745 kernel_dv[16].x = -1; kernel_dv[16].y = -2; kernel_dv[16].w = -wt12; 746 kernel_dv[17].x = 0; kernel_dv[17].y = -2; kernel_dv[17].w = -0.25f; 747 kernel_dv[18].x = 1; kernel_dv[18].y = -2; kernel_dv[18].w = -wt12; 748 kernel_dv[19].x = 2; kernel_dv[19].y = -2; kernel_dv[19].w = -wt22; 749 750 for(n = 0; n < 20; ++n) 751 { 752 usum += fabsf(kernel_du[n].w); 753 vsum += fabsf(kernel_dv[n].w); 754 } 755 for(n = 0; n < 20; ++n) 756 { 757 kernel_du[n].w /= usum; 758 kernel_dv[n].w /= vsum; 759 } 760 761 break; 762 } 763 case FILTER_7x7: 764 { 765 float du_weights[]= 766 { 767 -1, -2, -3, 0, 3, 2, 1, 768 -2, -3, -4, 0, 4, 3, 2, 769 -3, -4, -5, 0, 5, 4, 3, 770 -4, -5, -6, 0, 6, 5, 4, 771 -3, -4, -5, 0, 5, 4, 3, 772 -2, -3, -4, 0, 4, 3, 2, 773 -1, -2, -3, 0, 3, 2, 1 774 }; 775 float dv_weights[49]; 776 int n; 777 float usum = 0, vsum = 0; 778 779 num_elements = 49; 780 kernel_du = (kernel_element*)g_malloc(49 * sizeof(kernel_element)); 781 kernel_dv = (kernel_element*)g_malloc(49 * sizeof(kernel_element)); 782 783 make_kernel(kernel_du, du_weights, 7); 784 rotate_array(dv_weights, du_weights, 7); 785 make_kernel(kernel_dv, dv_weights, 7); 786 787 for(n = 0; n < 49; ++n) 788 { 789 usum += fabsf(kernel_du[n].w); 790 vsum += fabsf(kernel_dv[n].w); 791 } 792 for(n = 0; n < 49; ++n) 793 { 794 kernel_du[n].w /= usum; 795 kernel_dv[n].w /= vsum; 796 } 797 798 break; 799 } 800 case FILTER_9x9: 801 { 802 float du_weights[]= 803 { 804 -1, -2, -3, -4, 0, 4, 3, 2, 1, 805 -2, -3, -4, -5, 0, 5, 4, 3, 2, 806 -3, -4, -5, -6, 0, 6, 5, 4, 3, 807 -4, -5, -6, -7, 0, 7, 6, 5, 4, 808 -5, -6, -7, -8, 0, 8, 7, 6, 5, 809 -4, -5, -6, -7, 0, 7, 6, 5, 4, 810 -3, -4, -5, -6, 0, 6, 5, 4, 3, 811 -2, -3, -4, -5, 0, 5, 4, 3, 2, 812 -1, -2, -3, -4, 0, 4, 3, 2, 1 813 }; 814 float dv_weights[81]; 815 int n; 816 float usum = 0, vsum = 0; 817 818 num_elements = 81; 819 kernel_du = (kernel_element*)g_malloc(81 * sizeof(kernel_element)); 820 kernel_dv = (kernel_element*)g_malloc(81 * sizeof(kernel_element)); 821 822 make_kernel(kernel_du, du_weights, 9); 823 rotate_array(dv_weights, du_weights, 9); 824 make_kernel(kernel_dv, dv_weights, 9); 825 826 for(n = 0; n < 81; ++n) 827 { 828 usum += fabsf(kernel_du[n].w); 829 vsum += fabsf(kernel_dv[n].w); 830 } 831 for(n = 0; n < 81; ++n) 832 { 833 kernel_du[n].w /= usum; 834 kernel_dv[n].w /= vsum; 835 } 836 837 break; 838 } 839 } 840 841 if(nmapvals.conversion == CONVERT_BIASED_RGB) 842 { 843 /* approximated average color of the image 844 * scale to 16x16, accumulate the pixels and average */ 845 unsigned int sum[3]; 846 847 tmp = g_malloc(16 * 16 * bpp); 848 scale_pixels(tmp, 16, 16, src, width, height, bpp); 849 850 sum[0] = sum[1] = sum[2] = 0; 851 852 s = src; 853 for(y = 0; y < 16; ++y) 854 { 855 for(x = 0; x < 16; ++x) 856 { 857 sum[0] += *s++; 858 sum[1] += *s++; 859 sum[2] += *s++; 860 if(bpp == 4) s++; 861 } 862 } 863 864 rgb_bias[0] = (float)sum[0] / 256.0f; 865 rgb_bias[1] = (float)sum[1] / 256.0f; 866 rgb_bias[2] = (float)sum[2] / 256.0f; 867 868 g_free(tmp); 869 } 870 else 871 { 872 rgb_bias[0] = 0; 873 rgb_bias[1] = 0; 874 rgb_bias[2] = 0; 875 } 876 877 if(nmapvals.conversion != CONVERT_NORMALIZE_ONLY && 878 nmapvals.conversion != CONVERT_DUDV_TO_NORMAL && 879 nmapvals.conversion != CONVERT_HEIGHTMAP) 880 { 881 s = src; 882 for(y = 0; y < height; ++y) 883 { 884 for(x = 0; x < width; ++x) 885 { 886 if(!nmapvals.height_source) 887 { 888 switch(nmapvals.conversion) 889 { 890 case CONVERT_NONE: 891 val = (float)s[0] * 0.3f + 892 (float)s[1] * 0.59f + 893 (float)s[2] * 0.11f; 894 break; 895 case CONVERT_BIASED_RGB: 896 val = (((float)max(0, s[0] - rgb_bias[0])) * 0.3f ) + 897 (((float)max(0, s[1] - rgb_bias[1])) * 0.59f) + 898 (((float)max(0, s[2] - rgb_bias[2])) * 0.11f); 899 break; 900 case CONVERT_RED: 901 val = (float)s[0]; 902 break; 903 case CONVERT_GREEN: 904 val = (float)s[1]; 905 break; 906 case CONVERT_BLUE: 907 val = (float)s[2]; 908 break; 909 case CONVERT_MAX_RGB: 910 val = (float)max(s[0], max(s[1], s[2])); 911 break; 912 case CONVERT_MIN_RGB: 913 val = (float)min(s[0], min(s[1], s[2])); 914 break; 915 case CONVERT_COLORSPACE: 916 val = (1.0f - ((1.0f - ((float)s[0] / 255.0f)) * 917 (1.0f - ((float)s[1] / 255.0f)) * 918 (1.0f - ((float)s[2] / 255.0f)))) * 255.0f; 919 break; 920 default: 921 val = 255.0f; 922 break; 923 } 924 } 925 else 926 val = (float)s[3]; 927 928 heights[x + y * width] = val * oneover255; 929 930 s += bpp; 931 } 932 } 933 } 934 935 #define HEIGHT(x,y) \ 936 (heights[(max(0, min(width - 1, (x)))) + (max(0, min(height - 1, (y)))) * width]) 937 #define HEIGHT_WRAP(x,y) \ 938 (heights[((x) < 0 ? (width + (x)) : ((x) >= width ? ((x) - width) : (x)))+ \ 939 (((y) < 0 ? (height + (y)) : ((y) >= height ? ((y) - height) : (y))) * width)]) 940 941 if(preview_mode) 942 { 943 cursor = gdk_cursor_new(GDK_WATCH); 944 gdk_window_set_cursor(GDK_WINDOW(dialog->window), cursor); 945 gdk_cursor_unref(cursor); 946 } 947 948 for(y = 0; y < height; ++y) 949 { 950 while(gtk_events_pending()) 951 gtk_main_iteration(); 952 953 for(x = 0; x < width; ++x) 954 { 955 d = dst + ((y * rowbytes) + (x * bpp)); 956 s = src + ((y * rowbytes) + (x * bpp)); 957 958 if(nmapvals.conversion == CONVERT_NORMALIZE_ONLY || 959 nmapvals.conversion == CONVERT_HEIGHTMAP) 960 { 961 n[0] = (((float)s[0] * oneover255) - 0.5f) * 2.0f; 962 n[1] = (((float)s[1] * oneover255) - 0.5f) * 2.0f; 963 n[2] = (((float)s[2] * oneover255) - 0.5f) * 2.0f; 964 n[0] *= nmapvals.scale; 965 n[1] *= nmapvals.scale; 966 } 967 else if(nmapvals.conversion == CONVERT_DUDV_TO_NORMAL) 968 { 969 n[0] = (((float)s[0] * oneover255) - 0.5f) * 2.0f; 970 n[1] = (((float)s[1] * oneover255) - 0.5f) * 2.0f; 971 n[2] = sqrtf(1.0f - (n[0] * n[0] - n[1] * n[1])); 972 n[0] *= nmapvals.scale; 973 n[1] *= nmapvals.scale; 974 } 975 else 976 { 977 du = 0; dv = 0; 978 if(!nmapvals.wrap) 979 { 980 for(i = 0; i < num_elements; ++i) 981 du += HEIGHT(x + kernel_du[i].x, 982 y + kernel_du[i].y) * kernel_du[i].w; 983 for(i = 0; i < num_elements; ++i) 984 dv += HEIGHT(x + kernel_dv[i].x, 985 y + kernel_dv[i].y) * kernel_dv[i].w; 986 } 987 else 988 { 989 for(i = 0; i < num_elements; ++i) 990 du += HEIGHT_WRAP(x + kernel_du[i].x, 991 y + kernel_du[i].y) * kernel_du[i].w; 992 for(i = 0; i < num_elements; ++i) 993 dv += HEIGHT_WRAP(x + kernel_dv[i].x, 994 y + kernel_dv[i].y) * kernel_dv[i].w; 995 } 996 997 n[0] = -du * nmapvals.scale; 998 n[1] = -dv * nmapvals.scale; 999 n[2] = 1.0f; 1000 } 1001 1002 NORMALIZE(n); 1003 1004 if(n[2] < nmapvals.minz) 1005 { 1006 n[2] = nmapvals.minz; 1007 NORMALIZE(n); 1008 } 1009 1010 if(nmapvals.xinvert) n[0] = -n[0]; 1011 if(nmapvals.yinvert) n[1] = -n[1]; 1012 if(nmapvals.swapRGB) 1013 { 1014 val = n[0]; 1015 n[0] = n[2]; 1016 n[2] = val; 1017 } 1018 1019 if(!nmapvals.dudv) 1020 { 1021 *d++ = (unsigned char)((n[0] + 1.0f) * 127.5f); 1022 *d++ = (unsigned char)((n[1] + 1.0f) * 127.5f); 1023 *d++ = (unsigned char)((n[2] + 1.0f) * 127.5f); 1024 1025 if(drawable->bpp == 4) 1026 { 1027 switch(nmapvals.alpha) 1028 { 1029 case ALPHA_NONE: 1030 *d++ = s[3]; break; 1031 case ALPHA_HEIGHT: 1032 *d++ = (unsigned char)(heights[x + y * width] * 255.0f); break; 1033 case ALPHA_INVERSE_HEIGHT: 1034 *d++ = 255 - (unsigned char)(heights[x + y * width] * 255.0f); break; 1035 case ALPHA_ZERO: 1036 *d++ = 0; break; 1037 case ALPHA_ONE: 1038 *d++ = 255; break; 1039 case ALPHA_INVERT: 1040 *d++ = 255 - s[3]; break; 1041 case ALPHA_MAP: 1042 *d++ = sample_alpha_map(amap, x, y, amap_w, amap_h, 1043 width, height); break; 1044 default: 1045 *d++ = s[3]; break; 1046 } 1047 } 1048 } 1049 else 1050 { 1051 if(nmapvals.dudv == DUDV_8BIT_SIGNED || 1052 nmapvals.dudv == DUDV_8BIT_UNSIGNED) 1053 { 1054 if(nmapvals.dudv == DUDV_8BIT_UNSIGNED) 1055 { 1056 n[0] += 1.0f; 1057 n[1] += 1.0f; 1058 } 1059 *d++ = (unsigned char)(n[0] * 127.5f); 1060 *d++ = (unsigned char)(n[1] * 127.5f); 1061 *d++ = 0; 1062 if(drawable->bpp == 4) *d++ = 255; 1063 } 1064 else if(nmapvals.dudv == DUDV_16BIT_SIGNED || 1065 nmapvals.dudv == DUDV_16BIT_UNSIGNED) 1066 { 1067 unsigned short *d16 = (unsigned short*)d; 1068 if(nmapvals.dudv == DUDV_16BIT_UNSIGNED) 1069 { 1070 n[0] += 1.0f; 1071 n[1] += 1.0f; 1072 } 1073 *d16++ = (unsigned short)(n[0] * 32767.5f); 1074 *d16++ = (unsigned short)(n[1] * 32767.5f); 1075 } 1076 } 1077 } 1078 1079 if(!preview_mode) 1080 gimp_progress_update((double)(y - 1) / (double)(height - 2)); 1081 } 1082 1083 if(nmapvals.conversion == CONVERT_HEIGHTMAP) 1084 make_heightmap(dst, width, height, bpp); 1085 1086 #undef HEIGHT 1087 #undef HEIGHT_WRAP 1088 1089 if(preview_mode) 1090 { 1091 update_3D_preview(width, height, bpp, dst); 1092 1093 pw = GIMP_PREVIEW_AREA(preview)->width; 1094 ph = GIMP_PREVIEW_AREA(preview)->height; 1095 rowbytes = pw * bpp; 1096 1097 tmp = g_malloc(pw * ph * bpp); 1098 scale_pixels(tmp, pw, ph, dst, width, height, bpp); 1099 1100 gimp_preview_area_draw(GIMP_PREVIEW_AREA(preview), 0, 0, pw, ph, 1101 (bpp == 4) ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE, 1102 tmp, rowbytes); 1103 1104 g_free(tmp); 1105 1106 gdk_window_set_cursor(GDK_WINDOW(dialog->window), 0); 1107 } 1108 else 1109 { 1110 gimp_progress_update(100.0); 1111 1112 gimp_pixel_rgn_init(&dst_rgn, drawable, 0, 0, width, height, 1, 1); 1113 gimp_pixel_rgn_set_rect(&dst_rgn, dst, 0, 0, width, height); 1114 1115 gimp_drawable_flush(drawable); 1116 gimp_drawable_merge_shadow(drawable->drawable_id, 1); 1117 gimp_drawable_update(drawable->drawable_id, 0, 0, width, height); 1118 } 1119 1120 g_free(heights); 1121 g_free(src); 1122 g_free(dst); 1123 g_free(kernel_du); 1124 g_free(kernel_dv); 1125 if(amap) g_free(amap); 1126 1127 return(0); 1128 } 1129 1130 static void do_cleanup(gpointer data) 1131 { 1132 destroy_3D_preview(); 1133 gtk_main_quit(); 1134 } 1135 1136 static int update_preview = 0; 1137 1138 static gint idle_callback(gpointer data) 1139 { 1140 if(update_preview) 1141 { 1142 update_preview = 0; 1143 normalmap((GimpDrawable*)data, TRUE); 1144 } 1145 return(1); 1146 } 1147 1148 static void filter_type_selected(GtkWidget *widget, gpointer data) 1149 { 1150 if(nmapvals.filter != (gint)(long)data) 1151 { 1152 nmapvals.filter = (gint)(long)data; 1153 update_preview = 1; 1154 } 1155 } 1156 1157 static void minz_changed(GtkWidget *widget, gpointer data) 1158 { 1159 nmapvals.minz = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); 1160 update_preview = 1; 1161 } 1162 1163 static void scale_changed(GtkWidget *widget, gpointer data) 1164 { 1165 nmapvals.scale = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); 1166 update_preview = 1; 1167 } 1168 1169 static void height_source_selected(GtkWidget *widget, gpointer data) 1170 { 1171 GtkWidget *opt; 1172 1173 if(nmapvals.height_source == (gint)(long)data) return; 1174 1175 nmapvals.height_source = (gint)(long)data; 1176 1177 opt = g_object_get_data(G_OBJECT(widget), "conversion_opt"); 1178 if(!nmapvals.height_source) 1179 { 1180 gtk_widget_set_sensitive(opt, 1); 1181 } 1182 else 1183 { 1184 nmapvals.conversion = CONVERT_NONE; 1185 gtk_option_menu_set_history(GTK_OPTION_MENU(opt), nmapvals.conversion); 1186 gtk_widget_set_sensitive(opt, 0); 1187 } 1188 1189 update_preview = 1; 1190 } 1191 1192 static void alpha_result_selected(GtkWidget *widget, gpointer data) 1193 { 1194 if(nmapvals.alpha != (gint)(long)data) 1195 { 1196 nmapvals.alpha = (gint)(long)data; 1197 update_preview = 1; 1198 } 1199 } 1200 1201 static void conversion_selected(GtkWidget *widget, gpointer data) 1202 { 1203 GtkWidget *contrast_spin; 1204 1205 if(nmapvals.conversion != (gint)(long)data) 1206 { 1207 nmapvals.conversion = (gint)(long)data; 1208 contrast_spin = g_object_get_data(G_OBJECT(widget), "contrast_spin"); 1209 gtk_widget_set_sensitive(contrast_spin, nmapvals.conversion == CONVERT_HEIGHTMAP); 1210 update_preview = 1; 1211 } 1212 } 1213 1214 static void preview_clicked(GtkWidget *widget, gpointer data) 1215 { 1216 GimpDrawable *drawable; 1217 if(!is_3D_preview_active()) 1218 { 1219 drawable = g_object_get_data(G_OBJECT(widget), "drawable"); 1220 show_3D_preview(drawable); 1221 update_preview = 1; 1222 } 1223 } 1224 1225 static void dudv_selected(GtkWidget *widget, gpointer data) 1226 { 1227 GimpDrawable *drawable; 1228 GtkWidget *opt; 1229 1230 if(nmapvals.dudv == (gint)(long)data) return; 1231 1232 nmapvals.dudv = (gint)(long)data; 1233 1234 drawable = g_object_get_data(G_OBJECT(widget), "drawable"); 1235 opt = g_object_get_data(G_OBJECT(widget), "alpha_opt"); 1236 1237 if(nmapvals.dudv == DUDV_NONE) 1238 { 1239 if(drawable->bpp == 4) 1240 gtk_widget_set_sensitive(opt, 1); 1241 } 1242 else 1243 { 1244 nmapvals.alpha = 0; 1245 gtk_option_menu_set_history(GTK_OPTION_MENU(opt), nmapvals.alpha); 1246 gtk_widget_set_sensitive(opt, 0); 1247 } 1248 1249 update_preview = 1; 1250 } 1251 1252 static void contrast_changed(GtkWidget *widget, gpointer data) 1253 { 1254 nmapvals.contrast = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); 1255 update_preview = 1; 1256 } 1257 1258 static void toggle_clicked(GtkWidget *widget, gpointer data) 1259 { 1260 *((int*)data) = !(*((int*)data)); 1261 update_preview = 1; 1262 } 1263 1264 static gint dialog_constrain(gint32 image_id, gint32 drawable_id, 1265 gpointer data) 1266 { 1267 if(drawable_id == -1) return(1); 1268 if(gimp_drawable_is_gray(drawable_id)) 1269 { 1270 *(int*)data += 1; 1271 return(1); 1272 } 1273 return(0); 1274 } 1275 1276 static void alphamap_callback(gint32 id, gpointer data) 1277 { 1278 if(nmapvals.alphamap_id != id) 1279 { 1280 nmapvals.alphamap_id = id; 1281 update_preview = 1; 1282 } 1283 } 1284 1285 static void normalmap_dialog_response(GtkWidget *widget, gint response_id, 1286 gpointer data) 1287 { 1288 switch(response_id) 1289 { 1290 case GTK_RESPONSE_OK: 1291 runme = 1; 1292 default: 1293 gtk_widget_destroy(widget); 1294 break; 1295 } 1296 } 1297 1298 static gint normalmap_dialog(GimpDrawable *drawable) 1299 { 1300 GtkWidget *hbox, *vbox, *abox; 1301 GtkWidget *btn; 1302 GtkWidget *table; 1303 GtkWidget *opt, *alpha_result_opt; 1304 GtkWidget *menu; 1305 GtkWidget *menuitem, *item_height_source[2]; 1306 GtkWidget *label; 1307 GtkObject *adj; 1308 GtkWidget *spin; 1309 GtkWidget *frame; 1310 GtkWidget *check; 1311 GtkWidget *conversion_menu; 1312 GList *curr; 1313 int num_amaps = 0; 1314 1315 if(nmapvals.alpha == ALPHA_MAP) 1316 { 1317 if(!gimp_drawable_get(nmapvals.alphamap_id) || 1318 !gimp_drawable_is_gray(nmapvals.alphamap_id)) 1319 { 1320 nmapvals.alpha = 0; 1321 nmapvals.alphamap_id = 0; 1322 } 1323 } 1324 1325 gimp_ui_init("normalmap", TRUE); 1326 1327 dialog = gimp_dialog_new("Normalmap", "normalmap", 1328 0, 0, gimp_standard_help_func, 0, 1329 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 1330 GTK_STOCK_OK, GTK_RESPONSE_OK, 1331 NULL); 1332 1333 gtk_signal_connect(GTK_OBJECT(dialog), "response", 1334 GTK_SIGNAL_FUNC(normalmap_dialog_response), 1335 0); 1336 gtk_signal_connect(GTK_OBJECT(dialog), "destroy", 1337 GTK_SIGNAL_FUNC(do_cleanup), 1338 0); 1339 1340 hbox = gtk_hbox_new(0, 8); 1341 gtk_container_set_border_width(GTK_CONTAINER(hbox), 8); 1342 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),hbox, 1, 1, 0); 1343 gtk_widget_show(hbox); 1344 1345 vbox = gtk_vbox_new(0, 8); 1346 gtk_box_pack_start(GTK_BOX(hbox), vbox, 1, 1, 0); 1347 gtk_widget_show(vbox); 1348 1349 frame = gtk_frame_new("Preview"); 1350 gtk_box_pack_start(GTK_BOX(vbox), frame, 0, 0, 0); 1351 gtk_widget_show(frame); 1352 1353 abox = gtk_alignment_new(0.5, 0.5, 0.0, 0.0); 1354 gtk_container_set_border_width(GTK_CONTAINER (abox), 4); 1355 gtk_container_add(GTK_CONTAINER(frame), abox); 1356 gtk_widget_show(abox); 1357 1358 frame = gtk_frame_new(NULL); 1359 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); 1360 gtk_container_add(GTK_CONTAINER(abox), frame); 1361 gtk_widget_show(frame); 1362 1363 preview = gimp_preview_area_new(); 1364 gimp_preview_area_set_max_size(GIMP_PREVIEW_AREA(preview), PREVIEW_SIZE, PREVIEW_SIZE); 1365 gtk_drawing_area_size(GTK_DRAWING_AREA(preview), PREVIEW_SIZE, PREVIEW_SIZE); 1366 gtk_container_add(GTK_CONTAINER(frame), preview); 1367 gtk_widget_show(preview); 1368 1369 btn = gtk_button_new_with_label("3D Preview"); 1370 gtk_signal_connect(GTK_OBJECT(btn), "clicked", 1371 GTK_SIGNAL_FUNC(preview_clicked), 0); 1372 g_object_set_data(G_OBJECT(btn), "drawable", drawable); 1373 gtk_box_pack_start(GTK_BOX(vbox), btn, 0, 0, 0); 1374 gtk_widget_show(btn); 1375 1376 label = gtk_label_new("Alpha map:"); 1377 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 1378 gtk_widget_show(label); 1379 gtk_box_pack_start(GTK_BOX(vbox), label, 0, 0, 0); 1380 1381 opt = gtk_option_menu_new(); 1382 gtk_widget_show(opt); 1383 menu = gimp_drawable_menu_new(dialog_constrain, 1384 alphamap_callback, 1385 &num_amaps, drawable->drawable_id); 1386 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); 1387 gtk_box_pack_start(GTK_BOX(vbox), opt, 0, 0, 0); 1388 1389 if(drawable->bpp != 4) 1390 gtk_widget_set_sensitive(opt, 0); 1391 1392 table = gtk_table_new(9, 2, 0); 1393 gtk_widget_show(table); 1394 gtk_box_pack_start(GTK_BOX(hbox), table, 1, 1, 0); 1395 gtk_table_set_row_spacings(GTK_TABLE(table), 8); 1396 gtk_table_set_col_spacings(GTK_TABLE(table), 8); 1397 1398 opt = gtk_option_menu_new(); 1399 gtk_widget_show(opt); 1400 gimp_table_attach_aligned(GTK_TABLE(table), 0, 0, "Filter:", 0, 0.5, 1401 opt, 1, 0); 1402 1403 menu = gtk_menu_new(); 1404 1405 menuitem = gtk_menu_item_new_with_label("4 sample"); 1406 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1407 GTK_SIGNAL_FUNC(filter_type_selected), 1408 (gpointer)FILTER_NONE); 1409 gtk_widget_show(menuitem); 1410 gtk_menu_append(GTK_MENU(menu), menuitem); 1411 menuitem = gtk_menu_item_new_with_label("Sobel 3x3"); 1412 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1413 GTK_SIGNAL_FUNC(filter_type_selected), 1414 (gpointer)FILTER_SOBEL_3x3); 1415 gtk_widget_show(menuitem); 1416 gtk_menu_append(GTK_MENU(menu), menuitem); 1417 menuitem = gtk_menu_item_new_with_label("Sobel 5x5"); 1418 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1419 GTK_SIGNAL_FUNC(filter_type_selected), 1420 (gpointer)FILTER_SOBEL_5x5); 1421 gtk_widget_show(menuitem); 1422 gtk_menu_append(GTK_MENU(menu), menuitem); 1423 menuitem = gtk_menu_item_new_with_label("Prewitt 3x3"); 1424 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1425 GTK_SIGNAL_FUNC(filter_type_selected), 1426 (gpointer)FILTER_PREWITT_3x3); 1427 gtk_widget_show(menuitem); 1428 gtk_menu_append(GTK_MENU(menu), menuitem); 1429 menuitem = gtk_menu_item_new_with_label("Prewitt 5x5"); 1430 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1431 GTK_SIGNAL_FUNC(filter_type_selected), 1432 (gpointer)FILTER_PREWITT_5x5); 1433 gtk_widget_show(menuitem); 1434 gtk_menu_append(GTK_MENU(menu), menuitem); 1435 menuitem = gtk_menu_item_new_with_label("3x3"); 1436 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1437 GTK_SIGNAL_FUNC(filter_type_selected), 1438 (gpointer)FILTER_3x3); 1439 gtk_widget_show(menuitem); 1440 gtk_menu_append(GTK_MENU(menu), menuitem); 1441 menuitem = gtk_menu_item_new_with_label("5x5"); 1442 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1443 GTK_SIGNAL_FUNC(filter_type_selected), 1444 (gpointer)FILTER_5x5); 1445 gtk_widget_show(menuitem); 1446 gtk_menu_append(GTK_MENU(menu), menuitem); 1447 menuitem = gtk_menu_item_new_with_label("7x7"); 1448 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1449 GTK_SIGNAL_FUNC(filter_type_selected), 1450 (gpointer)FILTER_7x7); 1451 gtk_widget_show(menuitem); 1452 gtk_menu_append(GTK_MENU(menu), menuitem); 1453 menuitem = gtk_menu_item_new_with_label("9x9"); 1454 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1455 GTK_SIGNAL_FUNC(filter_type_selected), 1456 (gpointer)FILTER_9x9); 1457 gtk_widget_show(menuitem); 1458 gtk_menu_append(GTK_MENU(menu), menuitem); 1459 gtk_menu_set_active(GTK_MENU(menu), nmapvals.filter); 1460 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); 1461 1462 adj = gtk_adjustment_new(nmapvals.minz, 0, 1, 0.01, 0.05, 0.1); 1463 spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.01, 5); 1464 gtk_widget_show(spin); 1465 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_IF_VALID); 1466 gtk_signal_connect(GTK_OBJECT(spin), "value_changed", 1467 GTK_SIGNAL_FUNC(minz_changed), 0); 1468 gimp_table_attach_aligned(GTK_TABLE(table), 0, 1, "Minimum Z:", 0, 0.5, 1469 spin, 1, 0); 1470 1471 adj = gtk_adjustment_new(nmapvals.scale, -100, 100, 1, 5, 5); 1472 spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 5); 1473 gtk_widget_show(spin); 1474 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_IF_VALID); 1475 gtk_signal_connect(GTK_OBJECT(spin), "value_changed", 1476 GTK_SIGNAL_FUNC(scale_changed), 0); 1477 gimp_table_attach_aligned(GTK_TABLE(table), 0, 2, "Scale:", 0, 0.5, 1478 spin, 1, 0); 1479 1480 opt = gtk_option_menu_new(); 1481 gtk_widget_show(opt); 1482 gimp_table_attach_aligned(GTK_TABLE(table), 0, 3, "Height source:", 0, 0.5, 1483 opt, 1, 0); 1484 1485 menu = gtk_menu_new(); 1486 1487 if(drawable->bpp != 4) 1488 nmapvals.height_source = 0; 1489 1490 menuitem = item_height_source[0] = gtk_menu_item_new_with_label("Average RGB"); 1491 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1492 GTK_SIGNAL_FUNC(height_source_selected), 1493 (gpointer)0); 1494 gtk_widget_show(menuitem); 1495 gtk_menu_append(GTK_MENU(menu), menuitem); 1496 menuitem = item_height_source[1] = gtk_menu_item_new_with_label("Alpha"); 1497 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1498 GTK_SIGNAL_FUNC(height_source_selected), 1499 (gpointer)1); 1500 gtk_widget_show(menuitem); 1501 gtk_menu_append(GTK_MENU(menu), menuitem); 1502 1503 gtk_menu_set_active(GTK_MENU(menu), nmapvals.height_source); 1504 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); 1505 1506 if(drawable->bpp != 4) 1507 gtk_widget_set_sensitive(opt, 0); 1508 1509 opt = alpha_result_opt = gtk_option_menu_new(); 1510 gtk_widget_show(opt); 1511 gimp_table_attach_aligned(GTK_TABLE(table), 0, 4, "Alpha channel:", 0, 0.5, 1512 opt, 1, 0); 1513 1514 if(drawable->bpp != 4) 1515 nmapvals.alpha = 0; 1516 1517 menu = gtk_menu_new(); 1518 1519 menuitem = gtk_menu_item_new_with_label("Unchanged"); 1520 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1521 GTK_SIGNAL_FUNC(alpha_result_selected), 1522 (gpointer)ALPHA_NONE); 1523 gtk_widget_show(menuitem); 1524 gtk_menu_append(GTK_MENU(menu), menuitem); 1525 menuitem = gtk_menu_item_new_with_label("Height"); 1526 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1527 GTK_SIGNAL_FUNC(alpha_result_selected), 1528 (gpointer)ALPHA_HEIGHT); 1529 gtk_widget_show(menuitem); 1530 gtk_menu_append(GTK_MENU(menu), menuitem); 1531 menuitem = gtk_menu_item_new_with_label("Inverse height"); 1532 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1533 GTK_SIGNAL_FUNC(alpha_result_selected), 1534 (gpointer)ALPHA_INVERSE_HEIGHT); 1535 gtk_widget_show(menuitem); 1536 gtk_menu_append(GTK_MENU(menu), menuitem); 1537 menuitem = gtk_menu_item_new_with_label("Set to 0"); 1538 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1539 GTK_SIGNAL_FUNC(alpha_result_selected), 1540 (gpointer)ALPHA_ZERO); 1541 gtk_widget_show(menuitem); 1542 gtk_menu_append(GTK_MENU(menu), menuitem); 1543 menuitem = gtk_menu_item_new_with_label("Set to 1"); 1544 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1545 GTK_SIGNAL_FUNC(alpha_result_selected), 1546 (gpointer)ALPHA_ONE); 1547 gtk_widget_show(menuitem); 1548 gtk_menu_append(GTK_MENU(menu), menuitem); 1549 menuitem = gtk_menu_item_new_with_label("Invert"); 1550 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1551 GTK_SIGNAL_FUNC(alpha_result_selected), 1552 (gpointer)ALPHA_INVERT); 1553 gtk_widget_show(menuitem); 1554 gtk_menu_append(GTK_MENU(menu), menuitem); 1555 menuitem = gtk_menu_item_new_with_label("Use alpha map"); 1556 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1557 GTK_SIGNAL_FUNC(alpha_result_selected), 1558 (gpointer)ALPHA_MAP); 1559 gtk_widget_show(menuitem); 1560 gtk_menu_append(GTK_MENU(menu), menuitem); 1561 1562 if(num_amaps == 0) 1563 { 1564 gtk_widget_set_sensitive(menuitem, 0); 1565 if(nmapvals.alpha == ALPHA_MAP) 1566 nmapvals.alpha = 0; 1567 } 1568 1569 gtk_menu_set_active(GTK_MENU(menu), nmapvals.alpha); 1570 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); 1571 1572 if(drawable->bpp !=4 || nmapvals.dudv != DUDV_NONE) 1573 gtk_widget_set_sensitive(opt, 0); 1574 1575 opt = gtk_option_menu_new(); 1576 gtk_widget_show(opt); 1577 gimp_table_attach_aligned(GTK_TABLE(table), 0, 5, "Conversion:", 0, 0.5, 1578 opt, 1, 0); 1579 1580 g_object_set_data(G_OBJECT(item_height_source[0]), "conversion_opt", opt); 1581 g_object_set_data(G_OBJECT(item_height_source[1]), "conversion_opt", opt); 1582 1583 conversion_menu = menu = gtk_menu_new(); 1584 1585 menuitem = gtk_menu_item_new_with_label("None"); 1586 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1587 GTK_SIGNAL_FUNC(conversion_selected), 1588 (gpointer)CONVERT_NONE); 1589 gtk_widget_show(menuitem); 1590 gtk_menu_append(GTK_MENU(menu), menuitem); 1591 menuitem = gtk_menu_item_new_with_label("Biased RGB"); 1592 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1593 GTK_SIGNAL_FUNC(conversion_selected), 1594 (gpointer)CONVERT_BIASED_RGB); 1595 gtk_widget_show(menuitem); 1596 gtk_menu_append(GTK_MENU(menu), menuitem); 1597 menuitem = gtk_menu_item_new_with_label("Red"); 1598 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1599 GTK_SIGNAL_FUNC(conversion_selected), 1600 (gpointer)CONVERT_RED); 1601 gtk_widget_show(menuitem); 1602 gtk_menu_append(GTK_MENU(menu), menuitem); 1603 menuitem = gtk_menu_item_new_with_label("Green"); 1604 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1605 GTK_SIGNAL_FUNC(conversion_selected), 1606 (gpointer)CONVERT_GREEN); 1607 gtk_widget_show(menuitem); 1608 gtk_menu_append(GTK_MENU(menu), menuitem); 1609 menuitem = gtk_menu_item_new_with_label("Blue"); 1610 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1611 GTK_SIGNAL_FUNC(conversion_selected), 1612 (gpointer)CONVERT_BLUE); 1613 gtk_widget_show(menuitem); 1614 gtk_menu_append(GTK_MENU(menu), menuitem); 1615 menuitem = gtk_menu_item_new_with_label("Max RGB"); 1616 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1617 GTK_SIGNAL_FUNC(conversion_selected), 1618 (gpointer)CONVERT_MAX_RGB); 1619 gtk_widget_show(menuitem); 1620 gtk_menu_append(GTK_MENU(menu), menuitem); 1621 menuitem = gtk_menu_item_new_with_label("Min RGB"); 1622 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1623 GTK_SIGNAL_FUNC(conversion_selected), 1624 (gpointer)CONVERT_MIN_RGB); 1625 gtk_widget_show(menuitem); 1626 gtk_menu_append(GTK_MENU(menu), menuitem); 1627 menuitem = gtk_menu_item_new_with_label("Colorspace"); 1628 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1629 GTK_SIGNAL_FUNC(conversion_selected), 1630 (gpointer)CONVERT_COLORSPACE); 1631 gtk_widget_show(menuitem); 1632 gtk_menu_append(GTK_MENU(menu), menuitem); 1633 menuitem = gtk_menu_item_new_with_label("Normalize only"); 1634 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1635 GTK_SIGNAL_FUNC(conversion_selected), 1636 (gpointer)CONVERT_NORMALIZE_ONLY); 1637 gtk_widget_show(menuitem); 1638 gtk_menu_append(GTK_MENU(menu), menuitem); 1639 menuitem = gtk_menu_item_new_with_label("DUDV to Normal"); 1640 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1641 GTK_SIGNAL_FUNC(conversion_selected), 1642 (gpointer)CONVERT_DUDV_TO_NORMAL); 1643 gtk_widget_show(menuitem); 1644 gtk_menu_append(GTK_MENU(menu), menuitem); 1645 menuitem = gtk_menu_item_new_with_label("Convert to height"); 1646 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1647 GTK_SIGNAL_FUNC(conversion_selected), 1648 (gpointer)CONVERT_HEIGHTMAP); 1649 gtk_widget_show(menuitem); 1650 gtk_menu_append(GTK_MENU(menu), menuitem); 1651 1652 gtk_menu_set_active(GTK_MENU(menu), nmapvals.conversion); 1653 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); 1654 1655 if(nmapvals.height_source) 1656 gtk_widget_set_sensitive(opt, 0); 1657 1658 opt = gtk_option_menu_new(); 1659 gtk_widget_show(opt); 1660 gimp_table_attach_aligned(GTK_TABLE(table), 0, 6, "DU/DV map:", 0, 0.5, 1661 opt, 1, 0); 1662 1663 if(drawable->bpp != 4 && (nmapvals.dudv == DUDV_16BIT_SIGNED || 1664 nmapvals.dudv == DUDV_16BIT_UNSIGNED)) 1665 nmapvals.dudv = DUDV_NONE; 1666 1667 menu = gtk_menu_new(); 1668 1669 menuitem = gtk_menu_item_new_with_label("None"); 1670 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1671 GTK_SIGNAL_FUNC(dudv_selected), 1672 (gpointer)DUDV_NONE); 1673 g_object_set_data(G_OBJECT(menuitem), "drawable", drawable); 1674 g_object_set_data(G_OBJECT(menuitem), "alpha_opt", alpha_result_opt); 1675 gtk_widget_show(menuitem); 1676 gtk_menu_append(GTK_MENU(menu), menuitem); 1677 menuitem = gtk_menu_item_new_with_label("8 bits"); 1678 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1679 GTK_SIGNAL_FUNC(dudv_selected), 1680 (gpointer)DUDV_8BIT_SIGNED); 1681 g_object_set_data(G_OBJECT(menuitem), "drawable", drawable); 1682 g_object_set_data(G_OBJECT(menuitem), "alpha_opt", alpha_result_opt); 1683 gtk_widget_show(menuitem); 1684 gtk_menu_append(GTK_MENU(menu), menuitem); 1685 menuitem = gtk_menu_item_new_with_label("8 bits (unsigned)"); 1686 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1687 GTK_SIGNAL_FUNC(dudv_selected), 1688 (gpointer)DUDV_8BIT_UNSIGNED); 1689 g_object_set_data(G_OBJECT(menuitem), "drawable", drawable); 1690 g_object_set_data(G_OBJECT(menuitem), "alpha_opt", alpha_result_opt); 1691 gtk_widget_show(menuitem); 1692 gtk_menu_append(GTK_MENU(menu), menuitem); 1693 menuitem = gtk_menu_item_new_with_label("16 bits"); 1694 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1695 GTK_SIGNAL_FUNC(dudv_selected), 1696 (gpointer)DUDV_16BIT_SIGNED); 1697 g_object_set_data(G_OBJECT(menuitem), "drawable", drawable); 1698 g_object_set_data(G_OBJECT(menuitem), "alpha_opt", alpha_result_opt); 1699 gtk_widget_show(menuitem); 1700 gtk_menu_append(GTK_MENU(menu), menuitem); 1701 if(drawable->bpp != 4) 1702 gtk_widget_set_sensitive(menuitem, 0); 1703 menuitem = gtk_menu_item_new_with_label("16 bits (unsigned)"); 1704 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1705 GTK_SIGNAL_FUNC(dudv_selected), 1706 (gpointer)DUDV_16BIT_UNSIGNED); 1707 g_object_set_data(G_OBJECT(menuitem), "drawable", drawable); 1708 g_object_set_data(G_OBJECT(menuitem), "alpha_opt", alpha_result_opt); 1709 gtk_widget_show(menuitem); 1710 gtk_menu_append(GTK_MENU(menu), menuitem); 1711 if(drawable->bpp != 4) 1712 gtk_widget_set_sensitive(menuitem, 0); 1713 1714 gtk_menu_set_active(GTK_MENU(menu), nmapvals.dudv); 1715 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); 1716 1717 adj = gtk_adjustment_new(nmapvals.contrast, 0, 1, 0.01, 0.05, 0.1); 1718 spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.01, 5); 1719 gtk_widget_show(spin); 1720 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_IF_VALID); 1721 gtk_signal_connect(GTK_OBJECT(spin), "value_changed", 1722 GTK_SIGNAL_FUNC(contrast_changed), 0); 1723 gimp_table_attach_aligned(GTK_TABLE(table), 0, 7, "Contrast:", 0, 0.5, 1724 spin, 1, 0); 1725 1726 gtk_widget_set_sensitive(spin, nmapvals.conversion == CONVERT_HEIGHTMAP); 1727 1728 curr = gtk_container_get_children(GTK_CONTAINER(conversion_menu)); 1729 while(curr) 1730 { 1731 g_object_set_data(G_OBJECT(curr->data), "contrast_spin", spin); 1732 curr = curr->next; 1733 } 1734 1735 frame = gtk_frame_new("Options"); 1736 gtk_box_pack_start(GTK_BOX(hbox), frame, 0, 1, 0); 1737 gtk_widget_show(frame); 1738 1739 vbox = gtk_vbox_new(0, 0); 1740 gtk_widget_show(vbox); 1741 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4); 1742 gtk_container_add(GTK_CONTAINER(frame), vbox); 1743 1744 check = gtk_check_button_new_with_label("Wrap"); 1745 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), nmapvals.wrap); 1746 gtk_widget_show(check); 1747 gtk_box_pack_start(GTK_BOX(vbox), check, 0, 1, 0); 1748 gtk_signal_connect(GTK_OBJECT(check), "clicked", 1749 GTK_SIGNAL_FUNC(toggle_clicked), &nmapvals.wrap); 1750 check = gtk_check_button_new_with_label("Invert X"); 1751 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), nmapvals.xinvert); 1752 gtk_widget_show(check); 1753 gtk_box_pack_start(GTK_BOX(vbox), check, 0, 1, 0); 1754 gtk_signal_connect(GTK_OBJECT(check), "clicked", 1755 GTK_SIGNAL_FUNC(toggle_clicked), &nmapvals.xinvert); 1756 check = gtk_check_button_new_with_label("Invert Y"); 1757 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), nmapvals.yinvert); 1758 gtk_widget_show(check); 1759 gtk_box_pack_start(GTK_BOX(vbox), check, 0, 1, 0); 1760 gtk_signal_connect(GTK_OBJECT(check), "clicked", 1761 GTK_SIGNAL_FUNC(toggle_clicked), &nmapvals.yinvert); 1762 check = gtk_check_button_new_with_label("Swap RGB"); 1763 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), nmapvals.swapRGB); 1764 gtk_widget_show(check); 1765 gtk_box_pack_start(GTK_BOX(vbox), check, 0, 1, 0); 1766 gtk_signal_connect(GTK_OBJECT(check), "clicked", 1767 GTK_SIGNAL_FUNC(toggle_clicked), &nmapvals.swapRGB); 1768 1769 gtk_widget_show(dialog); 1770 1771 update_preview = 1; 1772 gtk_timeout_add(100, idle_callback, drawable); 1773 1774 runme = 0; 1775 1776 gtk_main(); 1777 1778 return(runme); 1779 }
| ViewVC Help | |
| Powered by ViewVC 1.0.4 |