Parent Directory
|
Revision Log
Added white point setting to log average luminance tone mapping operator
1 /* 2 hdrtools GIMP plugin 3 4 Copyright (C) 2007 Shawn Kirst <skirst@fuse.net> 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 <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <ctype.h> 26 #include <float.h> 27 28 #include <gtk/gtk.h> 29 30 #include <libgimp/gimp.h> 31 #include <libgimp/gimpui.h> 32 33 static inline float max(float a, float b) 34 { 35 return(a > b ? a : b); 36 } 37 38 static inline float min(float a, float b) 39 { 40 return(a < b ? a : b); 41 42 } 43 44 static inline float clamp(float x, float l, float h) 45 { 46 return(max(l, min(h, x))); 47 } 48 49 typedef struct rgbe_header_s 50 { 51 int width; 52 int height; 53 int flags; 54 float gamma; 55 float exposure; 56 } rgbe_header_t; 57 58 typedef enum rgbe_flags_e 59 { 60 RGBE_HAS_GAMMA = 1 << 0, 61 RGBE_HAS_EXPOSURE = 1 << 1 62 } rgbe_flags_t; 63 64 #define PROG_NAME "hdrtools" 65 #define LOAD_PROC "file_rgbe_load" 66 #define SAVE_PROC "file_rgbe_save" 67 68 static gint g_run_interactive; 69 static int g_runme = 0; 70 71 static void query(void); 72 static void run(const gchar *name, gint nparams, const GimpParam *param, 73 gint *nreturn_vals, GimpParam **return_vals); 74 static int rgbe_read_header(rgbe_header_t *hdr, FILE *fp); 75 static int rgbe_read_pixels(FILE *fp, unsigned char *data, int num); 76 static int rgbe_read_pixels_RLE(FILE *fp, unsigned char *data, 77 int width, int height); 78 static gint32 read_rgbe_image(gchar *filename); 79 static GimpPDBStatusType write_rgbe_image(gchar *filename, gint32 imageID, 80 gint32 drawableID); 81 static void convert_rgbe_to_rgbdiv8(GimpPreview *preview, 82 GimpDrawable *drawable); 83 static float compute_log_average_luminance(unsigned char *pixels, 84 int imgtype, int w, int h); 85 static void tonemap_image_logavg(GimpPreview *preview, GimpDrawable *drawable); 86 static void tonemap_image(GimpPreview *preview, GimpDrawable *drawable); 87 static int tonemap_logavg_dialog(GimpDrawable *drawable); 88 static int tonemap_dialog(GimpDrawable *drawable); 89 static int rgbd8_dialog(GimpDrawable *drawable); 90 static int read_rgbe_dialog(void); 91 static int write_rgbe_dialog(void); 92 93 GimpPlugInInfo PLUG_IN_INFO = 94 { 95 0, 0, query, run 96 }; 97 98 enum 99 { 100 IMAGE_TYPE_RGBE, 101 IMAGE_TYPE_RGBDIV8 102 }; 103 104 /* plug-in data storage structures */ 105 106 static struct 107 { 108 gboolean preview; 109 int imgtype; 110 int tonemap; 111 int usefilelevels; 112 int reinhard; 113 float exposure; 114 float gamma; 115 float midtone; 116 float white; 117 } g_tonemap_vals = { 1, IMAGE_TYPE_RGBE, 0, 1, 0, 1.0f, 2.2f, 0.36f, 1.0f }; 118 119 static struct 120 { 121 int rle; 122 int writelevels; 123 float exposure; 124 float gamma; 125 } g_write_vals = { 1, 0, 1.0f, 2.2f }; 126 127 static struct 128 { 129 gboolean preview; 130 float range; 131 } g_rgbd8_vals = { 1, 1.0f }; 132 133 MAIN() 134 135 static void query(void) 136 { 137 static GimpParamDef load_args[]= 138 { 139 {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"}, 140 {GIMP_PDB_STRING, "filename", "The name of the file to load"}, 141 {GIMP_PDB_STRING, "raw_filename", "The name entered"}, 142 {GIMP_PDB_INT32, "tonemap", "Tone map the loaded image"}, 143 {GIMP_PDB_INT32, "use_file_levels", "Use exposure and gamma levels in file for tone mapping"}, 144 {GIMP_PDB_FLOAT, "exposure", "Exposure level (default 1.0)"}, 145 {GIMP_PDB_FLOAT, "gamma", "Gamma level (default 2.2)"} 146 }; 147 148 static GimpParamDef load_return_vals[]= 149 { 150 {GIMP_PDB_IMAGE, "image", "Output image"} 151 }; 152 153 static GimpParamDef save_args[]= 154 { 155 {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"}, 156 {GIMP_PDB_IMAGE, "image", "Input image"}, 157 {GIMP_PDB_DRAWABLE, "drawable", "Drawable to save"}, 158 {GIMP_PDB_STRING, "filename", "The name of the file to save the image as"}, 159 {GIMP_PDB_STRING, "raw_filename", "The name entered"} 160 }; 161 162 static GimpParamDef rgbd8_args[] = 163 { 164 {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"}, 165 {GIMP_PDB_IMAGE, "image", "Input image (unused)"}, 166 {GIMP_PDB_DRAWABLE, "drawable", "Input drawable"}, 167 {GIMP_PDB_FLOAT, "range", "Map values [0..1] to [0..range] (default 1.0)"} 168 }; 169 170 static GimpParamDef tonemap_args[] = 171 { 172 {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"}, 173 {GIMP_PDB_IMAGE, "image", "Input image (unused)"}, 174 {GIMP_PDB_DRAWABLE, "drawable", "Input drawable"}, 175 {GIMP_PDB_INT32, "type", "Image type (0 = RGBE, 1 = RGBdiv8)"}, 176 {GIMP_PDB_FLOAT, "exposure", "Exposure"}, 177 {GIMP_PDB_FLOAT, "gamma", "Gamma"}, 178 }; 179 180 static GimpParamDef tonemap_logavg_args[] = 181 { 182 {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"}, 183 {GIMP_PDB_IMAGE, "image", "Input image (unused)"}, 184 {GIMP_PDB_DRAWABLE, "drawable", "Input drawable"}, 185 {GIMP_PDB_INT32, "type", "Image type (0 = RGBE, 1 = RGBdiv8)"}, 186 {GIMP_PDB_FLOAT, "midtone", "Midtone level"}, 187 {GIMP_PDB_FLOAT, "white", "White point"}, 188 {GIMP_PDB_FLOAT, "gamma", "Gamma"}, 189 }; 190 191 gimp_install_procedure(LOAD_PROC, 192 "Loads files in Radiance RGBE format", 193 "Loads files in Radiance RGBE format", 194 "Shawn Kirst", 195 "Shawn Kirst", 196 "2007", 197 "<Load>/Radiance RGBE", 198 0, 199 GIMP_PLUGIN, 200 G_N_ELEMENTS(load_args), 201 G_N_ELEMENTS(load_return_vals), 202 load_args, load_return_vals); 203 204 gimp_register_magic_load_handler(LOAD_PROC, 205 "hdr", 206 "", 207 "0,string,#?RADIANCE"); 208 209 gimp_install_procedure(SAVE_PROC, 210 "Saves files in Radiance RGBE format", 211 "Saves files in Radiance RGBE format", 212 "Shawn Kirst", 213 "Copyright 2007 Shawn Kirst", 214 "2007", 215 "<Save>/Radiance RGBE", 216 "RGBA", 217 GIMP_PLUGIN, 218 G_N_ELEMENTS(save_args), 0, 219 save_args, 0); 220 221 gimp_register_save_handler(SAVE_PROC, "hdr", ""); 222 223 gimp_install_procedure("convert_rgbe_to_rgbdiv8", 224 "Converts image from Radiance RGBE to RGBdiv8 format", 225 "foo!", 226 "Shawn Kirst", 227 "Copyright 2007 Shawn Kirst", 228 "2007", 229 "<Image>/Filters/Colors/HDR Tools/Convert Radiance RGBE to RGBdiv8...", 230 "RGBA", 231 GIMP_PLUGIN, 232 G_N_ELEMENTS(rgbd8_args), 0, 233 rgbd8_args, NULL); 234 235 gimp_install_procedure("plug_in_tonemap_rgbe", 236 "Converts Radiance RGBE data to LDR RGB", 237 "foo!", 238 "Shawn Kirst", 239 "Copyright 2007 Shawn Kirst", 240 "2007", 241 "<Image>/Filters/Colors/HDR Tools/Tone map Radiance RGBE image", 242 "RGBA", 243 GIMP_PLUGIN, 244 G_N_ELEMENTS(tonemap_args), 0, 245 tonemap_args, NULL); 246 247 gimp_install_procedure("plug_in_tonemap_rgbdiv8", 248 "Converts HDR RGBdiv8 data to LDR RGB using the Reinhard tone mapping operator", 249 "foo!", 250 "Shawn Kirst", 251 "Copyright 2007 Shawn Kirst", 252 "2007", 253 "<Image>/Filters/Colors/HDR Tools/Tone map RGBdiv8 image", 254 "RGBA", 255 GIMP_PLUGIN, 256 G_N_ELEMENTS(tonemap_args), 0, 257 tonemap_args, NULL); 258 259 gimp_install_procedure("plug_in_tonemap_logavg_rgbe", 260 "Converts Radiance RGBE data to LDR RGB using the Log average luminance tone mapping operator", 261 "foo!", 262 "Shawn Kirst", 263 "Copyright 2007 Shawn Kirst", 264 "2007", 265 "<Image>/Filters/Colors/HDR Tools/Tone map Radiance RGBE image (Log avg. luminance)", 266 "RGBA", 267 GIMP_PLUGIN, 268 G_N_ELEMENTS(tonemap_logavg_args), 0, 269 tonemap_logavg_args, NULL); 270 271 gimp_install_procedure("plug_in_tonemap_logavg_rgbdiv8", 272 "Converts HDR RGBdiv8 data to LDR RGB using the Log average luminance tone mapping operator", 273 "foo!", 274 "Shawn Kirst", 275 "Copyright 2007 Shawn Kirst", 276 "2007", 277 "<Image>/Filters/Colors/HDR Tools/Tone map RGBdiv8 image (Log avg. luminance)", 278 "RGBA", 279 GIMP_PLUGIN, 280 G_N_ELEMENTS(tonemap_logavg_args), 0, 281 tonemap_logavg_args, NULL); 282 283 } 284 285 static void run(const gchar *name, gint nparams, const GimpParam *param, 286 gint *nreturn_vals, GimpParam **return_vals) 287 { 288 static GimpParam values[2]; 289 GimpRunMode run_mode; 290 GimpPDBStatusType status = GIMP_PDB_SUCCESS; 291 gint32 imageID, drawableID; 292 GimpDrawable *drawable; 293 GimpExportReturn export = GIMP_EXPORT_CANCEL; 294 295 run_mode = param[0].data.d_int32; 296 297 *nreturn_vals = 1; 298 *return_vals = values; 299 300 values[0].type = GIMP_PDB_STATUS; 301 values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; 302 303 if(!strcmp(name, LOAD_PROC)) 304 { 305 switch(run_mode) 306 { 307 case GIMP_RUN_INTERACTIVE: 308 g_run_interactive = 1; 309 gimp_ui_init(PROG_NAME, 1); 310 311 if(!gimp_get_data(name, &g_tonemap_vals)) 312 { 313 g_tonemap_vals.tonemap = 0; 314 g_tonemap_vals.usefilelevels = 1; 315 g_tonemap_vals.exposure = 1.0f; 316 g_tonemap_vals.gamma = 2.2f; 317 g_tonemap_vals.midtone = 0.36f; 318 } 319 320 if(!read_rgbe_dialog()) 321 { 322 status = GIMP_PDB_CANCEL; 323 } 324 break; 325 case GIMP_RUN_NONINTERACTIVE: 326 g_run_interactive = 0; 327 if(nparams != 8) 328 status = GIMP_PDB_CALLING_ERROR; 329 else 330 { 331 g_tonemap_vals.tonemap = param[3].data.d_int32; 332 g_tonemap_vals.usefilelevels = param[4].data.d_int32; 333 g_tonemap_vals.exposure = param[5].data.d_float; 334 g_tonemap_vals.gamma = param[6].data.d_float; 335 g_tonemap_vals.midtone = param[7].data.d_float; 336 } 337 break; 338 default: 339 break; 340 } 341 342 if(status == GIMP_PDB_SUCCESS) 343 { 344 imageID = read_rgbe_image(param[1].data.d_string); 345 if(imageID != -1) 346 { 347 *nreturn_vals = 2; 348 values[1].type = GIMP_PDB_IMAGE; 349 values[1].data.d_image = imageID; 350 351 if(g_run_interactive) 352 gimp_set_data(name, &g_tonemap_vals, sizeof(g_tonemap_vals)); 353 } 354 else 355 status = GIMP_PDB_EXECUTION_ERROR; 356 } 357 } 358 else if(!strcmp(name, SAVE_PROC)) 359 { 360 imageID = param[1].data.d_int32; 361 drawableID = param[2].data.d_int32; 362 363 switch(run_mode) 364 { 365 case GIMP_RUN_INTERACTIVE: 366 case GIMP_RUN_WITH_LAST_VALS: 367 gimp_ui_init(PROG_NAME, 0); 368 export = gimp_export_image(&imageID, &drawableID, 369 "Radiance RGBE", 370 (GIMP_EXPORT_CAN_HANDLE_RGB | 371 GIMP_EXPORT_CAN_HANDLE_ALPHA)); 372 if(export == GIMP_EXPORT_CANCEL) 373 { 374 values[0].data.d_status = GIMP_PDB_CANCEL; 375 return; 376 } 377 default: 378 break; 379 } 380 381 switch(run_mode) 382 { 383 case GIMP_RUN_INTERACTIVE: 384 g_run_interactive = 1; 385 if(!gimp_get_data(name, &g_write_vals)) 386 { 387 g_write_vals.rle = 1; 388 g_write_vals.writelevels = 0; 389 g_write_vals.exposure = 1.0f; 390 g_write_vals.gamma = 2.2f; 391 } 392 if(!write_rgbe_dialog()) 393 { 394 values[0].data.d_status = GIMP_PDB_CANCEL; 395 return; 396 } 397 break; 398 case GIMP_RUN_NONINTERACTIVE: 399 g_run_interactive = 0; 400 if(nparams != 5) 401 status = GIMP_PDB_CALLING_ERROR; 402 break; 403 case GIMP_RUN_WITH_LAST_VALS: 404 g_run_interactive = 1; 405 gimp_get_data(name, &g_write_vals); 406 break; 407 default: 408 break; 409 } 410 411 if(status == GIMP_PDB_SUCCESS) 412 { 413 status = write_rgbe_image(param[3].data.d_string, imageID, 414 drawableID); 415 if(g_run_interactive) 416 gimp_set_data(name, &g_write_vals, sizeof(g_write_vals)); 417 } 418 419 if(export == GIMP_EXPORT_EXPORT) 420 gimp_image_delete(imageID); 421 } 422 else if(!strcmp(name, "convert_rgbe_to_rgbdiv8")) 423 { 424 *nreturn_vals = 1; 425 426 drawable = gimp_drawable_get(param[2].data.d_drawable); 427 428 switch(run_mode) 429 { 430 case GIMP_RUN_NONINTERACTIVE: 431 g_run_interactive = 0; 432 if(nparams != 4) 433 status = GIMP_PDB_CALLING_ERROR; 434 g_rgbd8_vals.range = clamp(param[3].data.d_float, 0, 1); 435 break; 436 case GIMP_RUN_WITH_LAST_VALS: 437 g_run_interactive = 1; 438 gimp_get_data(name, &g_rgbd8_vals); 439 break; 440 case GIMP_RUN_INTERACTIVE: 441 g_run_interactive = 1; 442 gimp_ui_init(PROG_NAME, 1); 443 gimp_get_data(name, &g_rgbd8_vals); 444 if(!rgbd8_dialog(drawable)) 445 { 446 status = GIMP_PDB_CANCEL; 447 } 448 break; 449 } 450 451 if(status == GIMP_PDB_SUCCESS) 452 { 453 convert_rgbe_to_rgbdiv8(NULL, drawable); 454 if(g_run_interactive) 455 gimp_set_data(name, &g_rgbd8_vals, sizeof(g_rgbd8_vals)); 456 gimp_displays_flush(); 457 gimp_drawable_detach(drawable); 458 } 459 } 460 else if(!strcmp(name, "plug_in_tonemap_rgbe") || 461 !strcmp(name, "plug_in_tonemap_rgbdiv8")) 462 { 463 int imgtype = !strcmp(name, "plug_in_tonemap_rgbe") ? IMAGE_TYPE_RGBE : IMAGE_TYPE_RGBDIV8; 464 465 *nreturn_vals = 1; 466 467 drawable = gimp_drawable_get(param[2].data.d_drawable); 468 469 switch(run_mode) 470 { 471 case GIMP_RUN_INTERACTIVE: 472 gimp_ui_init(PROG_NAME, 1); 473 474 if(!gimp_get_data(name, &g_tonemap_vals)) 475 { 476 g_tonemap_vals.preview = 1; 477 g_tonemap_vals.exposure = 1.0f; 478 g_tonemap_vals.gamma = 2.2f; 479 } 480 481 g_tonemap_vals.imgtype = imgtype; 482 483 if(!tonemap_dialog(drawable)) 484 { 485 gimp_drawable_detach(drawable); 486 return; 487 } 488 break; 489 case GIMP_RUN_NONINTERACTIVE: 490 if(nparams != 6) 491 status = GIMP_PDB_CALLING_ERROR; 492 else 493 { 494 g_tonemap_vals.imgtype = param[3].data.d_int32; 495 g_tonemap_vals.exposure = param[4].data.d_float; 496 g_tonemap_vals.gamma = param[5].data.d_float; 497 } 498 break; 499 case GIMP_RUN_WITH_LAST_VALS: 500 gimp_get_data(name, &g_tonemap_vals); 501 g_tonemap_vals.imgtype = imgtype; 502 break; 503 default: 504 break; 505 } 506 507 tonemap_image(NULL, drawable); 508 509 if(run_mode != GIMP_RUN_NONINTERACTIVE) 510 gimp_displays_flush(); 511 512 if(run_mode == GIMP_RUN_INTERACTIVE) 513 gimp_set_data(name, &g_tonemap_vals, sizeof(g_tonemap_vals)); 514 515 gimp_drawable_detach(drawable); 516 } 517 else if(!strcmp(name, "plug_in_tonemap_logavg_rgbe") || 518 !strcmp(name, "plug_in_tonemap_logavg_rgbdiv8")) 519 { 520 int imgtype = !strcmp(name, "plug_in_tonemap_logavg_rgbe") ? IMAGE_TYPE_RGBE : IMAGE_TYPE_RGBDIV8; 521 522 *nreturn_vals = 1; 523 524 drawable = gimp_drawable_get(param[2].data.d_drawable); 525 526 switch(run_mode) 527 { 528 case GIMP_RUN_INTERACTIVE: 529 gimp_ui_init(PROG_NAME, 1); 530 531 if(!gimp_get_data(name, &g_tonemap_vals)) 532 { 533 g_tonemap_vals.preview = 1; 534 g_tonemap_vals.midtone = 0.36f; 535 g_tonemap_vals.white = 1e6f; 536 g_tonemap_vals.gamma = 2.2f; 537 } 538 539 g_tonemap_vals.imgtype = imgtype; 540 541 if(!tonemap_logavg_dialog(drawable)) 542 { 543 gimp_drawable_detach(drawable); 544 return; 545 } 546 break; 547 case GIMP_RUN_NONINTERACTIVE: 548 if(nparams != 7) 549 status = GIMP_PDB_CALLING_ERROR; 550 else 551 { 552 g_tonemap_vals.imgtype = param[3].data.d_int32; 553 g_tonemap_vals.midtone = param[4].data.d_float; 554 g_tonemap_vals.white = param[5].data.d_float; 555 g_tonemap_vals.gamma = param[6].data.d_float; 556 } 557 break; 558 case GIMP_RUN_WITH_LAST_VALS: 559 gimp_get_data(name, &g_tonemap_vals); 560 g_tonemap_vals.imgtype = imgtype; 561 break; 562 default: 563 break; 564 } 565 566 tonemap_image_logavg(NULL, drawable); 567 568 if(run_mode != GIMP_RUN_NONINTERACTIVE) 569 gimp_displays_flush(); 570 571 if(run_mode == GIMP_RUN_INTERACTIVE) 572 gimp_set_data(name, &g_tonemap_vals, sizeof(g_tonemap_vals)); 573 574 gimp_drawable_detach(drawable); 575 } 576 else 577 status = GIMP_PDB_CALLING_ERROR; 578 579 values[0].data.d_status = status; 580 } 581 582 static int rgbe_read_header(rgbe_header_t *hdr, FILE *fp) 583 { 584 char buf[128]; 585 float val; 586 587 hdr->flags = 0; 588 589 if(fgets(buf, sizeof(buf), fp) == 0) 590 return(-1); 591 592 if(strncmp(buf, "#?RADIANCE", 10)) 593 return(-2); 594 595 while(fgets(buf, sizeof(buf), fp)) 596 { 597 if(strncmp(buf, "FORMAT=", 7) == 0) 598 { 599 // eat format 600 } 601 else if(strncmp(buf, "SOFTWARE=", 9) == 0) 602 { 603 // eat creator 604 } 605 else if(sscanf(buf, "GAMMA=%g", &val) == 1) 606 { 607 hdr->gamma = val; 608 hdr->flags |= RGBE_HAS_GAMMA; 609 } 610 else if(sscanf(buf, "EXPOSURE=%g", &val) == 1) 611 { 612 hdr->exposure = val; 613 hdr->flags |= RGBE_HAS_EXPOSURE; 614 } 615 else if(buf[0] == '-' && buf[1] == 'Y') 616 { 617 if(sscanf(buf, "-Y %d +X %d", &hdr->height, &hdr->width) < 2) 618 return(-3); 619 break; 620 } 621 else if(buf[0] == '+' && buf[1] == 'X') 622 { 623 if(sscanf(buf, "+X %d +Y %d", &hdr->width, &hdr->height) < 2) 624 return(-3); 625 break; 626 } 627 } 628 629 return(0); 630 } 631 632 static int rgbe_read_pixels(FILE *fp, unsigned char *data, int num) 633 { 634 int n = num * 4; 635 int r = fread(data, 1, n, fp); 636 return(-(n != r)); 637 } 638 639 static int rgbe_read_pixels_RLE(FILE *fp, unsigned char *data, 640 int width, int height) 641 { 642 unsigned char rgbe[4], *buffer, *ptr, *end, *dst; 643 int i, count, rc = 0, h = height; 644 unsigned char buf[2]; 645 646 dst = data; 647 648 if((width < 8) || (width > 0x7fff)) 649 return(rgbe_read_pixels(fp, data, width * height)); 650 651 buffer = 0; 652 653 while(h > 0) 654 { 655 if(fread(rgbe, 1, 4, fp) != 4) 656 { 657 rc = -1; 658 goto read_error; 659 } 660 661 if((rgbe[0] != 2) || (rgbe[1] != 2) || (rgbe[2] & 0x80)) 662 { 663 data[0] = rgbe[0]; 664 data[1] = rgbe[1]; 665 data[2] = rgbe[2]; 666 data[3] = rgbe[3]; 667 668 if(buffer) 669 g_free(buffer); 670 671 rc = rgbe_read_pixels(fp, &data[4], (width * h) - 1); 672 673 return(rc ? -2 : 0); 674 } 675 676 if((((int)rgbe[2]) << 8 | rgbe[3]) != width) 677 { 678 rc = -3; 679 goto read_error; 680 } 681 682 if(buffer == 0) 683 buffer = g_malloc(4 * width); 684 685 ptr = buffer; 686 687 for(i = 0; i < 4; ++i) 688 { 689 end = &buffer[(i + 1) * width]; 690 while(ptr < end) 691 { 692 if(fread(buf, 1, 2, fp) != 2) 693 { 694 rc = -4; 695 goto read_error; 696 } 697 698 if(buf[0] > 128) 699 { 700 count = buf[0] & 0x7f; 701 if((count == 0) || (count > (end - ptr))) 702 { 703 rc = -5; 704 goto read_error; 705 } 706 707 while(count-- > 0) 708 *ptr++ = buf[1]; 709 } 710 else 711 { 712 count = buf[0]; 713 if((count == 0) || (count > (end - ptr))) 714 { 715 rc = -6; 716 goto read_error; 717 } 718 719 *ptr++ = buf[1]; 720 721 if(--count > 0) 722 { 723 if(fread(ptr, 1, count, fp) != count) 724 { 725 rc = -7; 726 goto read_error; 727 } 728 729 ptr += count; 730 } 731 } 732 } 733 } 734 735 for(i = 0; i < width; ++i) 736 { 737 dst[4 * i + 0] = buffer[i]; 738 dst[4 * i + 1] = buffer[i + width]; 739 dst[4 * i + 2] = buffer[i + 2 * width]; 740 dst[4 * i + 3] = buffer[i + 3 * width]; 741 } 742 743 dst += 4 * width; 744 745 --h; 746 747 if(g_run_interactive) 748 gimp_progress_update((gdouble)(height - h) / (gdouble)height); 749 } 750 751 read_error: 752 753 if(buffer) 754 g_free(buffer); 755 756 return(rc); 757 } 758 759 static gint32 read_rgbe_image(gchar *filename) 760 { 761 FILE *fp; 762 int rc; 763 rgbe_header_t hdr; 764 unsigned char *pixels; 765 gchar *tmp; 766 GimpPixelRgn pixel_rgn; 767 gint32 image, layer; 768 GimpDrawable *drawable; 769 770 if(g_run_interactive) 771 { 772 tmp = g_strdup_printf("Loading %s:", filename); 773 gimp_progress_init(tmp); 774 g_free(tmp); 775 } 776 777 fp = fopen(filename, "rb"); 778 if(fp == 0) 779 { 780 g_message("%s: can't open \"%s\"", PROG_NAME, filename); 781 return(-1); 782 } 783 784 rc = rgbe_read_header(&hdr, fp); 785 786 if(rc != 0) 787 { 788 g_message("rgbe_read_header() = %d\n", rc); 789 fclose(fp); 790 return(-1); 791 } 792 793 if(g_tonemap_vals.usefilelevels) 794 { 795 if(hdr.flags & RGBE_HAS_EXPOSURE) 796 g_tonemap_vals.exposure = hdr.exposure; 797 else 798 g_tonemap_vals.exposure = 1.0f; 799 800 if(hdr.flags & RGBE_HAS_GAMMA) 801 g_tonemap_vals.gamma = hdr.gamma; 802 else 803 g_tonemap_vals.gamma = 2.2f; 804 } 805 806 pixels = g_malloc(4 * hdr.width * hdr.height); 807 if(pixels == 0) 808 { 809 g_message("Can't allocate pixel buffer\n%s", filename); 810 fclose(fp); 811 return(-1); 812 } 813 814 image = gimp_image_new(hdr.width, hdr.height, GIMP_RGB); 815 if(image == -1) 816 { 817 g_message("Can't allocate new image\n%s", filename); 818 fclose(fp); 819 g_free(pixels); 820 return(-1); 821 } 822 823 layer = gimp_layer_new(image, "Background", hdr.width, hdr.height, 824 GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE); 825 826 gimp_image_set_filename(image, filename); 827 gimp_image_add_layer(image, layer, 0); 828 drawable = gimp_drawable_get(layer); 829 830 rc = rgbe_read_pixels_RLE(fp, pixels, hdr.width, hdr.height); 831 if(rc != 0) 832 { 833 g_message("rgbe_read_pixels_RLE() = %d\n", rc); 834 fclose(fp); 835 g_free(pixels); 836 return(-1); 837 } 838 839 fclose(fp); 840 841 if(g_run_interactive) 842 gimp_progress_update(1.0); 843 844 gimp_pixel_rgn_init(&pixel_rgn, drawable, 0, 0, drawable->width, 845 drawable->height, 1, 0); 846 gimp_pixel_rgn_set_rect(&pixel_rgn, pixels, 0, 0, drawable->width, 847 drawable->height); 848 849 gimp_drawable_flush(drawable); 850 851 if(g_tonemap_vals.tonemap) 852 { 853 g_tonemap_vals.imgtype = IMAGE_TYPE_RGBE; 854 tonemap_image(NULL, drawable); 855 } 856 857 gimp_drawable_detach(drawable); 858 859 g_free(pixels); 860 861 return(image); 862 } 863 864 static int rgbe_write_pixels(FILE *fp, unsigned char *data, int num) 865 { 866 int n = 4 * num; 867 int w = fwrite(data, 1, n, fp); 868 return(-(w != n)); 869 } 870 871 static int rgbe_write_bytes_RLE(FILE *fp, unsigned char *data, int num) 872 { 873 #define MIN_RUN_LENGTH 4 874 875 int cur, beg_run, run_count, old_run_count, nonrun_count; 876 unsigned char buf[2]; 877 878 cur = 0; 879 while(cur < num) 880 { 881 beg_run = cur; 882 883 run_count = old_run_count = 0; 884 while((run_count < MIN_RUN_LENGTH) && (beg_run < num)) 885 { 886 beg_run += run_count; 887 old_run_count = run_count; 888 run_count = 1; 889 while((beg_run + run_count < num) && (run_count < 127) && 890 (data[beg_run] == data[beg_run + run_count])) 891 run_count++; 892 } 893 894 if((old_run_count > 1) && (old_run_count == beg_run - cur)) 895 { 896 buf[0] = 128 + old_run_count; 897 buf[1] = data[cur]; 898 if(fwrite(buf, 2, 1, fp) < 1) 899 return(-1); 900 cur = beg_run; 901 } 902 903 while(cur < beg_run) 904 { 905 nonrun_count = beg_run - cur; 906 if(nonrun_count > 128) 907 nonrun_count = 128; 908 buf[0] = nonrun_count; 909 if(fwrite(buf, 1, 1, fp) < 1) 910 return(-1); 911 if(fwrite(&data[cur], nonrun_count, 1, fp) < 1) 912 return(-1); 913 cur += nonrun_count; 914 } 915 916 if (run_count >= MIN_RUN_LENGTH) 917 { 918 buf[0] = 128 + run_count; 919 buf[1] = data[beg_run]; 920 if(fwrite(buf, 2, 1, fp) < 1) 921 return(-1); 922 cur += run_count; 923 } 924 } 925 926 return(0); 927 928 #undef MINRUNLENGTH 929 } 930 931 static int rgbe_write_pixels_RLE(FILE *fp, unsigned char *data, 932 int rle, int width, int height) 933 { 934 unsigned char rgbe[4], *buffer; 935 int i, rc = 0; 936 937 if(!rle || ((width < 8) || (width > 0x7fff))) 938 return(rgbe_write_pixels(fp, data, width * height)); 939 940 buffer = (unsigned char *)g_malloc(4 * width); 941 942 while(height-- > 0) 943 { 944 rgbe[0] = 2; 945 rgbe[1] = 2; 946 rgbe[2] = width >> 8; 947 rgbe[3] = width & 0xff; 948 949 if(fwrite(rgbe, sizeof(rgbe), 1, fp) < 1) 950 { 951 g_free(buffer); 952 return(-1); 953 } 954 955 for(i = 0; i < width; ++i) 956 { 957 buffer[i] = data[4 * i]; 958 buffer[i + width] = data[4 * i + 1]; 959 buffer[i + 2 * width] = data[4 * i + 2]; 960 buffer[i + 3 * width] = data[4 * i + 3]; 961 } 962 963 data += 4 * width; 964 965 /* write out each of the four channels separately run length encoded */ 966 /* first red, then green, then blue, then exponent */ 967 for(i = 0; i < 4; ++i) 968 { 969 if((rc = rgbe_write_bytes_RLE(fp, &buffer[i * width], width))) 970 { 971 g_free(buffer); 972 return(rc); 973 } 974 } 975 } 976 977 g_free(buffer); 978 979 return(rc); 980 } 981 982 static GimpPDBStatusType write_rgbe_image(gchar *filename, gint32 imageID, 983 gint32 drawableID) 984 { 985 FILE *fp; 986 GimpDrawable *drawable; 987 GimpImageType drawable_type; 988 GimpPixelRgn rgn; 989 int rc; 990 guchar *pixels; 991 gchar *tmp; 992 993 drawable = gimp_drawable_get(drawableID); 994 drawable_type = gimp_drawable_type(drawableID); 995 gimp_pixel_rgn_init(&rgn, drawable, 0, 0, drawable->width, 996 drawable->height, 0, 0); 997 998 fp = fopen(filename, "wb"); 999 if(fp == 0) 1000 { 1001 g_message("Error opening %s", filename); 1002 return(GIMP_PDB_EXECUTION_ERROR); 1003 } 1004 1005 pixels = g_malloc(drawable->width * drawable->height * 4); 1006 gimp_pixel_rgn_get_rect(&rgn, pixels, 0, 0, drawable->width, 1007 drawable->height); 1008 1009 if(g_run_interactive) 1010 { 1011 tmp = g_strdup_printf("Saving %s:", filename); 1012 gimp_progress_init(tmp); 1013 g_free(tmp); 1014 } 1015 1016 fprintf(fp, 1017 "#?RADIANCE\n" 1018 "# %s\n" 1019 "SOFTWARE=GIMP HDR tools\n" 1020 "FORMAT=32-bit_rle_rgbe\n", 1021 g_write_vals.rle ? "RLE compressed" : "Not RLE compressed"); 1022 1023 if(g_write_vals.writelevels) 1024 { 1025 fprintf(fp, 1026 "EXPOSURE=%f\n" 1027 "GAMMA=%f\n", 1028 g_write_vals.exposure, g_write_vals.gamma); 1029 } 1030 1031 fprintf(fp, 1032 "\n-Y %d +X %d\n", 1033 drawable->height, drawable->width); 1034 1035 rc = rgbe_write_pixels_RLE(fp, pixels, g_write_vals.rle, 1036 drawable->width, drawable->height); 1037 fclose(fp); 1038 1039 gimp_drawable_detach(drawable); 1040 1041 g_free(pixels); 1042 1043 return(rc ? GIMP_PDB_EXECUTION_ERROR : GIMP_PDB_SUCCESS); 1044 } 1045 1046 static void convert_rgbe_to_rgbdiv8(GimpPreview *preview, 1047 GimpDrawable *drawable) 1048 { 1049 GimpPixelRgn srcrgn, dstrgn; 1050 unsigned char *src, *dst, *rgbe; 1051 float rgb[3], maxchan, v, range; 1052 int sx, sy, x, y, w, h, n, idx = 0; 1053 1054 range = g_rgbd8_vals.range; 1055 1056 if(preview) 1057 { 1058 gimp_preview_get_position(preview, &sx, &sy); 1059 gimp_preview_get_size(preview, &w, &h); 1060 } 1061 else 1062 { 1063 sx = 0; 1064 sy = 0; 1065 w = drawable->width; 1066 h = drawable->height; 1067 } 1068 1069 n = w * h; 1070 dst = g_malloc(n * 4); 1071 src = g_malloc(n * 4); 1072 1073 gimp_pixel_rgn_init(&srcrgn, drawable, sx, sy, w, h, 0, 0); 1074 gimp_pixel_rgn_get_rect(&srcrgn, src, sx, sy, w, h); 1075 1076 if(!preview) 1077 gimp_progress_init("Converting to RGBdiv8..."); 1078 1079 for(y = 0; y < h; ++y) 1080 { 1081 for(x = 0; x < w; ++x) 1082 { 1083 rgbe = &src[idx]; 1084 if(rgbe[3]) 1085 { 1086 v = ldexpf(1.0f, rgbe[3] - 136); 1087 rgb[0] = (float)rgbe[0] * v; 1088 rgb[1] = (float)rgbe[1] * v; 1089 rgb[2] = (float)rgbe[2] * v; 1090 } 1091 else 1092 rgb[0] = rgb[1] = rgb[2] = 0; 1093 1094 maxchan = max(range, max(rgb[0], max(rgb[1], rgb[2]))); 1095 1096 dst[idx++] = (unsigned char)(255.0f * rgb[0] / maxchan); 1097 dst[idx++] = (unsigned char)(255.0f * rgb[1] / maxchan); 1098 dst[idx++] = (unsigned char)(255.0f * rgb[2] / maxchan); 1099 dst[idx++] = (unsigned char)(255.0f * range / maxchan); 1100 } 1101 1102 if(!preview) 1103 gimp_progress_update((gdouble)y / (gdouble)drawable->height); 1104 } 1105 1106 1107 gimp_pixel_rgn_init(&dstrgn, drawable, sx, sy, w, h, 1108 preview == NULL, 1); 1109 gimp_pixel_rgn_set_rect(&dstrgn, dst, sx, sy, w, h); 1110 1111 if(preview) 1112 { 1113 gimp_drawable_preview_draw_region(GIMP_DRAWABLE_PREVIEW(preview), 1114 &dstrgn); 1115 } 1116 else 1117 { 1118 gimp_progress_update(1.0); 1119 1120 gimp_drawable_flush(drawable); 1121 gimp_drawable_merge_shadow(drawable->drawable_id, 1); 1122 gimp_drawable_update(drawable->drawable_id, 0, 0, w, h); 1123 } 1124 1125 g_free(src); 1126 g_free(dst); 1127 } 1128 1129 static float compute_log_average_luminance(unsigned char *pixels, 1130 int imgtype, int w, int h) 1131 { 1132 int i, n; 1133 float rgb[3], v, lum, sum = 0; 1134 1135 gimp_progress_init("Computing log average luminance..."); 1136 1137 n = w * h; 1138 1139 for(i = 0; i < n; ++i) 1140 { 1141 if((i % w) == 0) 1142 gimp_progress_update((gdouble)i / (gdouble)n); 1143 1144 if(g_tonemap_vals.imgtype == IMAGE_TYPE_RGBE) 1145 { 1146 if(pixels[4 * i + 3]) 1147 { 1148 v = ldexpf(1.0f, pixels[4 * i + 3] - 136); 1149 rgb[0] = (float)pixels[4 * i + 0] * v; 1150 rgb[1] = (float)pixels[4 * i + 1] * v; 1151 rgb[2] = (float)pixels[4 * i + 2] * v; 1152 } 1153 else 1154 rgb[0] = rgb[1] = rgb[2] = 0; 1155 } 1156 else 1157 { 1158 v = (float)pixels[4 * i + 3] / 255.0f; 1159 if(v > 0) 1160 { 1161 rgb[0] = ((float)pixels[4 * i + 0] / 255.0f) / v; 1162 rgb[1] = ((float)pixels[4 * i + 1] / 255.0f) / v; 1163 rgb[2] = ((float)pixels[4 * i + 2] / 255.0f) / v; 1164 } 1165 else 1166 rgb[0] = rgb[1] = rgb[2] = FLT_MAX; 1167 } 1168 1169 lum = rgb[0] * 0.2126f + rgb[1] * 0.7152f + rgb[2] * 0.0722f; 1170 sum += logf(1e-04f + lum); 1171 } 1172 1173 gimp_progress_update(1.0); 1174 1175 return(sum / (float)(w * h)); 1176 } 1177 1178 static void tonemap_image_logavg(GimpPreview *preview, GimpDrawable *drawable) 1179 { 1180 GimpPixelRgn srcrgn, dstrgn; 1181 unsigned char *src, *dst; 1182 float *data; 1183 float log_avg_lum = 0, rgb[3], v, weight, white; 1184 int sx, sy, x, y, w, h, n, idx; 1185 1186 if(preview) 1187 { 1188 gimp_preview_get_position(preview, &sx, &sy); 1189 gimp_preview_get_size(preview, &w, &h); 1190 } 1191 else 1192 { 1193 sx = 0; 1194 sy = 0; 1195 w = drawable->width; 1196 h = drawable->height; 1197 } 1198 1199 if(preview) 1200 { 1201 data = g_object_get_data(G_OBJECT(preview), "logavglum"); 1202 if(!data) 1203 { 1204 data = g_malloc(sizeof(float)); 1205 src = g_malloc(drawable->width * drawable->height * 4); 1206 gimp_pixel_rgn_init(&srcrgn, drawable, 0, 0, drawable->width, 1207 drawable->height, 0, 0); 1208 gimp_pixel_rgn_get_rect(&srcrgn, src, 0, 0, drawable->width, 1209 drawable->height); 1210 log_avg_lum = compute_log_average_luminance(src, 1211 g_tonemap_vals.imgtype, 1212 drawable->width, drawable->height); 1213 data[0] = log_avg_lum; 1214 g_free(src); 1215 g_object_set_data(G_OBJECT(preview), "logavglum", data); 1216 } 1217 else 1218 { 1219 log_avg_lum = data[0]; 1220 } 1221 } 1222 1223 n = w * h; 1224 1225 dst = g_malloc(n * 4); 1226 src = g_malloc(n * 4); 1227 1228 gimp_pixel_rgn_init(&srcrgn, drawable, sx, sy, w, h, 0, 0); 1229 gimp_pixel_rgn_get_rect(&srcrgn, src, sx, sy, w, h); 1230 1231 if(!preview) 1232 { 1233 log_avg_lum = compute_log_average_luminance(src, 1234 g_tonemap_vals.imgtype, 1235 drawable->width, 1236 drawable->height); 1237 } 1238 1239 weight = g_tonemap_vals.midtone / (1e-03f + expf(log_avg_lum)); 1240 white = g_tonemap_vals.white; 1241 1242 if(!preview) 1243 gimp_progress_init("Tone mapping image..."); 1244 1245 for(y = 0; y < h; ++y) 1246 { 1247 for(x = 0; x < w; ++x) 1248 { 1249 idx = (y * (w * 4)) + (x * 4); 1250 1251 if(g_tonemap_vals.imgtype == IMAGE_TYPE_RGBE) 1252 { 1253 if(src[idx + 3]) 1254 { 1255 v = ldexpf(1.0f, src[idx + 3] - 136); 1256 rgb[0] = (float)src[idx + 0] * v; 1257 rgb[1] = (float)src[idx + 1] * v; 1258 rgb[2] = (float)src[idx + 2] * v; 1259 } 1260 else 1261 rgb[0] = rgb[1] = rgb[2] = 0; 1262 } 1263 else 1264 { 1265 v = (float)src[idx + 3] / 255.0f; 1266 if(v > 0) 1267 { 1268 rgb[0] = ((float)src[idx + 0] / 255.0f) / v; 1269 rgb[1] = ((float)src[idx + 1] / 255.0f) / v; 1270 rgb[2] = ((float)src[idx + 2] / 255.0f) / v; 1271 } 1272 else 1273 rgb[0] = rgb[1] = rgb[2] = FLT_MAX; 1274 } 1275 1276 rgb[0] *= weight; 1277 rgb[1] *= weight; 1278 rgb[2] *= weight; 1279 1280 rgb[0] = (rgb[0] * (1.0f + (rgb[0] / white))) / (1.0f + rgb[0]); 1281 rgb[1] = (rgb[1] * (1.0f + (rgb[1] / white))) / (1.0f + rgb[1]); 1282 rgb[2] = (rgb[2] * (1.0f + (rgb[2] / white))) / (1.0f + rgb[2]); 1283 1284 //rgb[0] = rgb[0] / (1.0f + rgb[0]); 1285 //rgb[1] = rgb[1] / (1.0f + rgb[1]); 1286 //rgb[2] = rgb[2] / (1.0f + rgb[2]); 1287 1288 rgb[0] = powf(rgb[0], 1.0f / g_tonemap_vals.gamma); 1289 rgb[1] = powf(rgb[1], 1.0f / g_tonemap_vals.gamma); 1290 rgb[2] = powf(rgb[2], 1.0f / g_tonemap_vals.gamma); 1291 1292 dst[idx + 0] = (unsigned char)(255.0f * min(rgb[0], 1.0f)); 1293 dst[idx + 1] = (unsigned char)(255.0f * min(rgb[1], 1.0f)); 1294 dst[idx + 2] = (unsigned char)(255.0f * min(rgb[2], 1.0f)); 1295 dst[idx + 3] = 255; 1296 } 1297 1298 if(!preview) 1299 gimp_progress_update((gdouble)y / (gdouble)h); 1300 } 1301 1302 gimp_pixel_rgn_init(&dstrgn, drawable, sx, sy, w, h, 1303 preview == NULL, 1); 1304 gimp_pixel_rgn_set_rect(&dstrgn, dst, sx, sy, w, h); 1305 1306 if(preview) 1307 { 1308 gimp_drawable_preview_draw_region(GIMP_DRAWABLE_PREVIEW(preview), 1309 &dstrgn); 1310 } 1311 else 1312 { 1313 gimp_progress_update(1.0); 1314 1315 gimp_drawable_flush(drawable); 1316 gimp_drawable_merge_shadow(drawable->drawable_id, 1); 1317 gimp_drawable_update(drawable->drawable_id, 0, 0, w, h); 1318 } 1319 1320 g_free(src); 1321 g_free(dst); 1322 } 1323 1324 static void tonemap_image(GimpPreview *preview, GimpDrawable *drawable) 1325 { 1326 GimpPixelRgn srcrgn, dstrgn; 1327 unsigned char *src, *dst; 1328 float rgb[3], v; 1329 int sx, sy, x, y, w, h, n, idx = 0; 1330 1331 if(preview) 1332 { 1333 gimp_preview_get_position(preview, &sx, &sy); 1334 gimp_preview_get_size(preview, &w, &h); 1335 } 1336 else 1337 { 1338 sx = 0; 1339 sy = 0; 1340 w = drawable->width; 1341 h = drawable->height; 1342 } 1343 1344 n = w * h; 1345 1346 dst = g_malloc(n * 4); 1347 src = g_malloc(n * 4); 1348 1349 gimp_pixel_rgn_init(&srcrgn, drawable, sx, sy, w, h, 0, 0); 1350 gimp_pixel_rgn_get_rect(&srcrgn, src, sx, sy, w, h); 1351 1352 if(!preview) 1353 gimp_progress_init("Tone mapping image..."); 1354 1355 for(y = 0; y < h; ++y) 1356 { 1357 for(x = 0; x < w; ++x) 1358 { 1359 if(g_tonemap_vals.imgtype == IMAGE_TYPE_RGBE) 1360 { 1361 if(src[idx + 3]) 1362 { 1363 v = ldexpf(1.0f, src[idx + 3] - 136); 1364 rgb[0] = (float)src[idx + 0] * v; 1365 rgb[1] = (float)src[idx + 1] * v; 1366 rgb[2] = (float)src[idx + 2] * v; 1367 } 1368 else 1369 rgb[0] = rgb[1] = rgb[2] = 0; 1370 } 1371 else 1372 { 1373 v = (float)src[idx + 3] / 255.0f; 1374 if(v > 0) 1375 { 1376 rgb[0] = ((float)src[idx + 0] / 255.0f) / v; 1377 rgb[1] = ((float)src[idx + 1] / 255.0f) / v; 1378 rgb[2] = ((float)src[idx + 2] / 255.0f) / v; 1379 } 1380 else 1381 rgb[0] = rgb[1] = rgb[2] = FLT_MAX; 1382 } 1383 1384 /* exposure */ 1385 rgb[0] = 1.0f - expf(-rgb[0] * g_tonemap_vals.exposure); 1386 rgb[1] = 1.0f - expf(-rgb[1] * g_tonemap_vals.exposure); 1387 rgb[2] = 1.0f - expf(-rgb[2] * g_tonemap_vals.exposure); 1388 1389 /* gamma correction */ 1390 rgb[0] = powf(rgb[0], 1.0f / g_tonemap_vals.gamma); 1391 rgb[1] = powf(rgb[1], 1.0f / g_tonemap_vals.gamma); 1392 rgb[2] = powf(rgb[2], 1.0f / g_tonemap_vals.gamma); 1393 1394 rgb[0] = clamp(rgb[0], 0, 1); 1395 rgb[1] = clamp(rgb[1], 0, 1); 1396 rgb[2] = clamp(rgb[2], 0, 1); 1397 1398 dst[idx++] = (unsigned char)(255.0f * rgb[0]); 1399 dst[idx++] = (unsigned char)(255.0f * rgb[1]); 1400 dst[idx++] = (unsigned char)(255.0f * rgb[2]); 1401 dst[idx++] = 255; 1402 } 1403 1404 if(!preview) 1405 gimp_progress_update((gdouble)y / (gdouble)h); 1406 } 1407 1408 gimp_pixel_rgn_init(&dstrgn, drawable, sx, sy, w, h, 1409 preview == NULL, 1); 1410 gimp_pixel_rgn_set_rect(&dstrgn, dst, sx, sy, w, h); 1411 1412 if(preview) 1413 { 1414 gimp_drawable_preview_draw_region(GIMP_DRAWABLE_PREVIEW(preview), 1415 &dstrgn); 1416 } 1417 else 1418 { 1419 gimp_progress_update(1.0); 1420 1421 gimp_drawable_flush(drawable); 1422 gimp_drawable_merge_shadow(drawable->drawable_id, 1); 1423 gimp_drawable_update(drawable->drawable_id, 0, 0, w, h); 1424 } 1425 1426 g_free(src); 1427 g_free(dst); 1428 } 1429 1430 static void on_spin_changed(GtkWidget *widget, gpointer data) 1431 { 1432 float *val = (float*)data; 1433 *val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); 1434 GimpPreview *preview = g_object_get_data(G_OBJECT(widget), "preview"); 1435 if(preview) 1436 gimp_preview_invalidate(preview); 1437 } 1438 1439 static void on_slider_changed(GtkWidget *widget, gpointer data) 1440 { 1441 float *val = (float*)data; 1442 *val = gtk_range_get_value(GTK_RANGE(widget)); 1443 GimpPreview *preview = g_object_get_data(G_OBJECT(widget), "preview"); 1444 if(preview) 1445 gimp_preview_invalidate(preview); 1446 } 1447 1448 static void on_checkbox_clicked(GtkWidget *widget, gpointer data) 1449 { 1450 int *val = (int*)data; 1451 *val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); 1452 } 1453 1454 static void on_preview_destroy(GtkWidget *widget, gpointer data) 1455 { 1456 void *ptr = g_object_get_data(G_OBJECT(widget), "logavglum"); 1457 if(ptr) 1458 g_free(ptr); 1459 } 1460 1461 static void dialog_response(GtkWidget *widget, gint response_id, 1462 gpointer data) 1463 { 1464 switch(response_id) 1465 { 1466 case GTK_RESPONSE_OK: 1467 g_runme = 1; 1468 default: 1469 gtk_widget_destroy(widget); 1470 break; 1471 } 1472 } 1473 1474 static int tonemap_logavg_dialog(GimpDrawable *drawable) 1475 { 1476 GtkWidget *dlg; 1477 GtkWidget *table; 1478 GtkWidget *label; 1479 GtkObject *adj; 1480 GtkWidget *hbox; 1481 GtkWidget *preview, *midtone_spin, *white_spin, *gamma_spin; 1482 1483 dlg = gimp_dialog_new("Tone map image (Log average luminance)", PROG_NAME, 1484 0, 0, 0, 0, 1485 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 1486 GTK_STOCK_OK, GTK_RESPONSE_OK, 1487 NULL); 1488 1489 hbox = gtk_hbox_new(0, 8); 1490 gtk_widget_show(hbox); 1491 gtk_container_set_border_width(GTK_CONTAINER(hbox), 8); 1492 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), hbox, 1, 1, 0); 1493 1494 preview = gimp_drawable_preview_new(drawable, &g_tonemap_vals.preview); 1495 gtk_widget_show(preview); 1496 gtk_box_pack_start(GTK_BOX(hbox), preview, 1, 1, 0); 1497 1498 table = gtk_table_new(3, 2, 0); 1499 gtk_widget_show(table); 1500 gtk_box_pack_start(GTK_BOX(hbox), table, 1, 1, 0); 1501 gtk_table_set_row_spacings(GTK_TABLE(table), 8); 1502 gtk_table_set_col_spacings(GTK_TABLE(table), 8); 1503 1504 label = gtk_label_new("Midtone:"); 1505 gtk_widget_show(label); 1506 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 1507 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); 1508 1509 adj = gtk_adjustment_new(g_tonemap_vals.midtone, 0, 65536, 0.01, 0.05, 1); 1510 midtone_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.01, 2); 1511 gtk_widget_show(midtone_spin); 1512 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(midtone_spin), 1513 GTK_UPDATE_IF_VALID); 1514 gtk_table_attach(GTK_TABLE(table), midtone_spin, 1, 2, 0, 1, 1515 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1516 g_object_set_data(G_OBJECT(midtone_spin), "preview", preview); 1517 1518 1519 label = gtk_label_new("White point:"); 1520 gtk_widget_show(label); 1521 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 1522 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); 1523 1524 adj = gtk_adjustment_new(g_tonemap_vals.white, 0, FLT_MAX, 0.01, 0.05, 1); 1525 white_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.01, 2); 1526 gtk_widget_show(white_spin); 1527 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(white_spin), 1528 GTK_UPDATE_IF_VALID); 1529 gtk_table_attach(GTK_TABLE(table), white_spin, 1, 2, 1, 2, 1530 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1531 g_object_set_data(G_OBJECT(white_spin), "preview", preview); 1532 1533 label = gtk_label_new("Gamma:"); 1534 gtk_widget_show(label); 1535 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 1536 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0); 1537 1538 adj = gtk_adjustment_new(g_tonemap_vals.gamma, 0, 100, 0.1, 0.5, 1); 1539 gamma_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1); 1540 gtk_widget_show(gamma_spin); 1541 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(gamma_spin), 1542 GTK_UPDATE_IF_VALID); 1543 gtk_table_attach(GTK_TABLE(table), gamma_spin, 1, 2, 2, 3, 1544 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1545 g_object_set_data(G_OBJECT(gamma_spin), "preview", preview); 1546 1547 1548 gtk_signal_connect(GTK_OBJECT(dlg), "response", 1549 GTK_SIGNAL_FUNC(dialog_response), 0); 1550 gtk_signal_connect(GTK_OBJECT(dlg), "destroy", 1551 GTK_SIGNAL_FUNC(gtk_main_quit), 0); 1552 gtk_signal_connect(GTK_OBJECT(preview), "invalidated", 1553 GTK_SIGNAL_FUNC(tonemap_image_logavg), 1554 drawable); 1555 gtk_signal_connect(GTK_OBJECT(preview), "destroy", 1556 GTK_SIGNAL_FUNC(on_preview_destroy), 0); 1557 gtk_signal_connect(GTK_OBJECT(midtone_spin), "value_changed", 1558 GTK_SIGNAL_FUNC(on_spin_changed), 1559 &g_tonemap_vals.midtone); 1560 gtk_signal_connect(GTK_OBJECT(white_spin), "value_changed", 1561 GTK_SIGNAL_FUNC(on_spin_changed), 1562 &g_tonemap_vals.white); 1563 gtk_signal_connect(GTK_OBJECT(gamma_spin), "value_changed", 1564 GTK_SIGNAL_FUNC(on_spin_changed), 1565 &g_tonemap_vals.gamma); 1566 1567 gtk_widget_show(dlg); 1568 1569 g_runme = 0; 1570 1571 gtk_main(); 1572 1573 return(g_runme); 1574 } 1575 1576 static int tonemap_dialog(GimpDrawable *drawable) 1577 { 1578 GtkWidget *dlg; 1579 GtkWidget *table; 1580 GtkWidget *label; 1581 GtkObject *adj; 1582 GtkWidget *hbox; 1583 GtkWidget *preview, *exposure_spin, *gamma_spin; 1584 1585 dlg = gimp_dialog_new("Tone map image", PROG_NAME, 1586 0, 0, 0, 0, 1587 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 1588 GTK_STOCK_OK, GTK_RESPONSE_OK, 1589 NULL); 1590 1591 hbox = gtk_hbox_new(0, 8); 1592 gtk_widget_show(hbox); 1593 gtk_container_set_border_width(GTK_CONTAINER(hbox), 8); 1594 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), hbox, 1, 1, 0); 1595 1596 preview = gimp_drawable_preview_new(drawable, &g_tonemap_vals.preview); 1597 gtk_widget_show(preview); 1598 gtk_box_pack_start(GTK_BOX(hbox), preview, 1, 1, 0); 1599 1600 table = gtk_table_new(2, 2, 0); 1601 gtk_widget_show(table); 1602 gtk_box_pack_start(GTK_BOX(hbox), table, 1, 1, 0); 1603 gtk_table_set_row_spacings(GTK_TABLE(table), 8); 1604 gtk_table_set_col_spacings(GTK_TABLE(table), 8); 1605 1606 label = gtk_label_new("Exposure:"); 1607 gtk_widget_show(label); 1608 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 1609 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); 1610 1611 adj = gtk_adjustment_new(g_tonemap_vals.exposure, 0, 100, 0.1, 0.5, 1); 1612 exposure_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1); 1613 gtk_widget_show(exposure_spin); 1614 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(exposure_spin), 1615 GTK_UPDATE_IF_VALID); 1616 gtk_table_attach(GTK_TABLE(table), exposure_spin, 1, 2, 0, 1, 1617 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1618 g_object_set_data(G_OBJECT(exposure_spin), "preview", preview); 1619 1620 label = gtk_label_new("Gamma:"); 1621 gtk_widget_show(label); 1622 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 1623 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); 1624 1625 adj = gtk_adjustment_new(g_tonemap_vals.gamma, 0, 100, 0.1, 0.5, 1); 1626 gamma_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1); 1627 gtk_widget_show(gamma_spin); 1628 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(gamma_spin), 1629 GTK_UPDATE_IF_VALID); 1630 gtk_table_attach(GTK_TABLE(table), gamma_spin, 1, 2, 1, 2, 1631 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1632 g_object_set_data(G_OBJECT(gamma_spin), "preview", preview); 1633 1634 1635 gtk_signal_connect(GTK_OBJECT(dlg), "response", 1636 GTK_SIGNAL_FUNC(dialog_response), 0); 1637 gtk_signal_connect(GTK_OBJECT(dlg), "destroy", 1638 GTK_SIGNAL_FUNC(gtk_main_quit), 0); 1639 gtk_signal_connect(GTK_OBJECT(preview), "invalidated", 1640 GTK_SIGNAL_FUNC(tonemap_image), 1641 drawable); 1642 gtk_signal_connect(GTK_OBJECT(exposure_spin), "value_changed", 1643 GTK_SIGNAL_FUNC(on_spin_changed), 1644 &g_tonemap_vals.exposure); 1645 gtk_signal_connect(GTK_OBJECT(gamma_spin), "value_changed", 1646 GTK_SIGNAL_FUNC(on_spin_changed), 1647 &g_tonemap_vals.gamma); 1648 1649 gtk_widget_show(dlg); 1650 1651 g_runme = 0; 1652 1653 gtk_main(); 1654 1655 return(g_runme); 1656 } 1657 1658 static int rgbd8_dialog(GimpDrawable *drawable) 1659 { 1660 GtkWidget *dlg; 1661 GtkObject *adj; 1662 GtkWidget *slider; 1663 GtkWidget *vbox; 1664 GtkWidget *table; 1665 GtkWidget *preview; 1666 1667 dlg = gimp_dialog_new("Convert Radiance RGBE to RGBdiv8", PROG_NAME, 1668 0, 0, 0, 0, 1669 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 1670 GTK_STOCK_OK, GTK_RESPONSE_OK, 1671 NULL); 1672 1673 vbox = gtk_vbox_new(0, 0); 1674 gtk_widget_show(vbox); 1675 gtk_container_set_border_width(GTK_CONTAINER(vbox), 8); 1676 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), vbox, 1, 1, 0); 1677 1678 table = gtk_table_new(2, 2, 0); 1679 gtk_widget_show(table); 1680 gtk_box_pack_start(GTK_BOX(vbox), table, 1, 1, 0); 1681 gtk_table_set_row_spacings(GTK_TABLE(table), 8); 1682 gtk_table_set_col_spacings(GTK_TABLE(table), 8); 1683 1684 preview = gimp_drawable_preview_new(drawable, &g_rgbd8_vals.preview); 1685 gtk_widget_show(preview); 1686 gtk_table_attach(GTK_TABLE(table), preview, 0, 2, 0, 1, 1687 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1688 1689 adj = gtk_adjustment_new(g_rgbd8_vals.range, 0, 1, 0.01, 0.1, 0); 1690 slider = gtk_hscale_new(GTK_ADJUSTMENT(adj)); 1691 gtk_widget_show(slider); 1692 gtk_scale_set_value_pos(GTK_SCALE(slider), GTK_POS_RIGHT); 1693 gtk_scale_set_digits(GTK_SCALE(slider), 2); 1694 gimp_table_attach_aligned(GTK_TABLE(table), 0, 1, "Range:", 0, 0.5, 1695 slider, 1, 0); 1696 g_object_set_data(G_OBJECT(slider), "preview", preview); 1697 1698 gtk_signal_connect(GTK_OBJECT(dlg), "response", 1699 GTK_SIGNAL_FUNC(dialog_response), 0); 1700 gtk_signal_connect(GTK_OBJECT(dlg), "destroy", 1701 GTK_SIGNAL_FUNC(gtk_main_quit), 0); 1702 gtk_signal_connect(GTK_OBJECT(preview), "invalidated", 1703 GTK_SIGNAL_FUNC(convert_rgbe_to_rgbdiv8), drawable); 1704 gtk_signal_connect(GTK_OBJECT(slider), "value_changed", 1705 GTK_SIGNAL_FUNC(on_slider_changed), 1706 &g_rgbd8_vals.range); 1707 1708 gtk_widget_show(dlg); 1709 1710 g_runme = 0; 1711 1712 gtk_main(); 1713 1714 return(g_runme); 1715 } 1716 1717 static void on_file_levels_checked(GtkWidget *widget, gpointer data) 1718 { 1719 GtkWidget *spin; 1720 int val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); 1721 1722 *((int *)data) = val; 1723 1724 spin = g_object_get_data(G_OBJECT(widget), "exposure_spin"); 1725 gtk_widget_set_sensitive(spin, !val); 1726 spin = g_object_get_data(G_OBJECT(widget), "gamma_spin"); 1727 gtk_widget_set_sensitive(spin, !val); 1728 } 1729 1730 static int read_rgbe_dialog(void) 1731 { 1732 GtkWidget *dlg; 1733 GtkWidget *table; 1734 GtkWidget *label; 1735 GtkObject *adj; 1736 GtkWidget *tmchk, *uflchk, *exposure_spin, *gamma_spin; 1737 1738 dlg = gimp_dialog_new("Load RGBE image", PROG_NAME, 1739 0, 0, 0, 0, 1740 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 1741 GTK_STOCK_OK, GTK_RESPONSE_OK, 1742 NULL); 1743 1744 table = gtk_table_new(4, 2, 0); 1745 gtk_widget_show(table); 1746 gtk_container_set_border_width(GTK_CONTAINER(table), 8); 1747 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), table, 1, 1, 0); 1748 gtk_table_set_row_spacings(GTK_TABLE(table), 8); 1749 gtk_table_set_col_spacings(GTK_TABLE(table), 8); 1750 1751 tmchk = gtk_check_button_new_with_label("Tone map image"); 1752 gtk_widget_show(tmchk); 1753 gtk_table_attach(GTK_TABLE(table), tmchk, 0, 2, 0, 1, 1754 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1755 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmchk), 1756 g_tonemap_vals.tonemap); 1757 1758 uflchk = gtk_check_button_new_with_label("Use file levels"); 1759 gtk_widget_show(uflchk); 1760 gtk_table_attach(GTK_TABLE(table), uflchk, 0, 2, 1, 2, 1761 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1762 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(uflchk), 1763 g_tonemap_vals.usefilelevels); 1764 1765 label = gtk_label_new("Exposure:"); 1766 gtk_widget_show(label); 1767 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0); 1768 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 1769 1770 adj = gtk_adjustment_new(g_tonemap_vals.exposure, 0, 100, 0.1, 0.5, 0.1); 1771 exposure_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1); 1772 gtk_widget_show(exposure_spin); 1773 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(exposure_spin), 1774 GTK_UPDATE_IF_VALID); 1775 gtk_table_attach(GTK_TABLE(table), exposure_spin, 1, 2, 2, 3, 1776 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1777 gtk_widget_set_sensitive(exposure_spin, !g_tonemap_vals.usefilelevels); 1778 1779 label = gtk_label_new("Gamma:"); 1780 gtk_widget_show(label); 1781 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0); 1782 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 1783 1784 adj = gtk_adjustment_new(g_tonemap_vals.gamma, 0, 100, 0.1, 0.5, 0.1); 1785 gamma_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1); 1786 gtk_widget_show(gamma_spin); 1787 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(gamma_spin), 1788 GTK_UPDATE_IF_VALID); 1789 gtk_table_attach(GTK_TABLE(table), gamma_spin, 1, 2, 3, 4, 1790 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1791 gtk_widget_set_sensitive(gamma_spin, !g_tonemap_vals.usefilelevels); 1792 1793 g_object_set_data(G_OBJECT(uflchk), "exposure_spin", exposure_spin); 1794 g_object_set_data(G_OBJECT(uflchk), "gamma_spin", gamma_spin); 1795 1796 gtk_signal_connect(GTK_OBJECT(dlg), "response", 1797 GTK_SIGNAL_FUNC(dialog_response), 0); 1798 gtk_signal_connect(GTK_OBJECT(dlg), "destroy", 1799 GTK_SIGNAL_FUNC(gtk_main_quit), 0); 1800 gtk_signal_connect(GTK_OBJECT(tmchk), "clicked", 1801 GTK_SIGNAL_FUNC(on_checkbox_clicked), 1802 &g_tonemap_vals.tonemap); 1803 gtk_signal_connect(GTK_OBJECT(uflchk), "clicked", 1804 GTK_SIGNAL_FUNC(on_file_levels_checked), 1805 &g_tonemap_vals.usefilelevels); 1806 gtk_signal_connect(GTK_OBJECT(exposure_spin), "value_changed", 1807 GTK_SIGNAL_FUNC(on_spin_changed), 1808 &g_tonemap_vals.exposure); 1809 gtk_signal_connect(GTK_OBJECT(gamma_spin), "value_changed", 1810 GTK_SIGNAL_FUNC(on_spin_changed), 1811 &g_tonemap_vals.gamma); 1812 1813 gtk_widget_show(dlg); 1814 1815 g_runme = 0; 1816 1817 gtk_main(); 1818 1819 return(g_runme); 1820 } 1821 1822 static void on_write_levels_checked(GtkWidget *widget, gpointer data) 1823 { 1824 GtkWidget *spin; 1825 int val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); 1826 1827 *((int *)data) = val; 1828 1829 spin = g_object_get_data(G_OBJECT(widget), "exposure_spin"); 1830 gtk_widget_set_sensitive(spin, val); 1831 spin = g_object_get_data(G_OBJECT(widget), "gamma_spin"); 1832 gtk_widget_set_sensitive(spin, val); 1833 } 1834 1835 static int write_rgbe_dialog(void) 1836 { 1837 GtkWidget *dlg; 1838 GtkWidget *table; 1839 GtkWidget *label; 1840 GtkObject *adj; 1841 GtkWidget *rlechk, *wlchk, *exposure_spin, *gamma_spin; 1842 1843 dlg = gimp_dialog_new("Save RGBE image", PROG_NAME, 1844 0, 0, 0, 0, 1845 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 1846 GTK_STOCK_OK, GTK_RESPONSE_OK, 1847 NULL); 1848 1849 table = gtk_table_new(4, 2, 0); 1850 gtk_widget_show(table); 1851 gtk_container_set_border_width(GTK_CONTAINER(table), 8); 1852 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), table, 1, 1, 0); 1853 gtk_table_set_row_spacings(GTK_TABLE(table), 8); 1854 gtk_table_set_col_spacings(GTK_TABLE(table), 8); 1855 1856 rlechk = gtk_check_button_new_with_label("RLE compression"); 1857 gtk_widget_show(rlechk); 1858 gtk_table_attach(GTK_TABLE(table), rlechk, 0, 2, 0, 1, 1859 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1860 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rlechk), 1861 g_write_vals.rle); 1862 1863 wlchk = gtk_check_button_new_with_label("Write exposure and gamma"); 1864 gtk_widget_show(wlchk); 1865 gtk_table_attach(GTK_TABLE(table), wlchk, 0, 2, 1, 2, 1866 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1867 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wlchk), 1868 g_write_vals.writelevels); 1869 1870 label = gtk_label_new("Exposure:"); 1871 gtk_widget_show(label); 1872 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0); 1873 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 1874 1875 adj = gtk_adjustment_new(g_write_vals.exposure, 0, 100, 0.1, 0.5, 0.1); 1876 exposure_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1); 1877 gtk_widget_show(exposure_spin); 1878 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(exposure_spin), 1879 GTK_UPDATE_IF_VALID); 1880 gtk_table_attach(GTK_TABLE(table), exposure_spin, 1, 2, 2, 3, 1881 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1882 gtk_widget_set_sensitive(exposure_spin, g_write_vals.writelevels); 1883 1884 label = gtk_label_new("Gamma:"); 1885 gtk_widget_show(label); 1886 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0); 1887 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 1888 1889 adj = gtk_adjustment_new(g_write_vals.gamma, 0, 100, 0.1, 0.5, 0.1); 1890 gamma_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1); 1891 gtk_widget_show(gamma_spin); 1892 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(gamma_spin), 1893 GTK_UPDATE_IF_VALID); 1894 gtk_table_attach(GTK_TABLE(table), gamma_spin, 1, 2, 3, 4, 1895 GTK_EXPAND | GTK_FILL, 0, 0, 0); 1896 gtk_widget_set_sensitive(gamma_spin, g_write_vals.writelevels); 1897 1898 g_object_set_data(G_OBJECT(wlchk), "exposure_spin", exposure_spin); 1899 g_object_set_data(G_OBJECT(wlchk), "gamma_spin", gamma_spin); 1900 1901 gtk_signal_connect(GTK_OBJECT(dlg), "response", 1902 GTK_SIGNAL_FUNC(dialog_response), 0); 1903 gtk_signal_connect(GTK_OBJECT(dlg), "destroy", 1904 GTK_SIGNAL_FUNC(gtk_main_quit), 0); 1905 gtk_signal_connect(GTK_OBJECT(rlechk), "clicked", 1906 GTK_SIGNAL_FUNC(on_checkbox_clicked), 1907 &g_write_vals.rle); 1908 gtk_signal_connect(GTK_OBJECT(wlchk), "clicked", 1909 GTK_SIGNAL_FUNC(on_write_levels_checked), 1910 &g_write_vals.writelevels); 1911 gtk_signal_connect(GTK_OBJECT(exposure_spin), "value_changed", 1912 GTK_SIGNAL_FUNC(on_spin_changed), 1913 &g_write_vals.exposure); 1914 gtk_signal_connect(GTK_OBJECT(gamma_spin), "value_changed", 1915 GTK_SIGNAL_FUNC(on_spin_changed), 1916 &g_write_vals.gamma); 1917 1918 gtk_widget_show(dlg); 1919 1920 g_runme = 0; 1921 1922 gtk_main(); 1923 1924 return(g_runme); 1925 }
| ViewVC Help | |
| Powered by ViewVC 1.0.4 |