[gimp-hdrtools] / tags / release-0.1 / hdrtools.c Repository:
ViewVC logotype

View of /tags/release-0.1/hdrtools.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (download) (as text) (annotate)
Fri Jan 19 19:17:55 2007 UTC (2 years, 10 months ago) by cocidius
File size: 44549 byte(s)
0.1 release
    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 void tonemap_image(GimpPreview *preview, GimpDrawable *drawable);
   84 static int tonemap_dialog(GimpDrawable *drawable);
   85 static int rgbd8_dialog(GimpDrawable *drawable);
   86 static int read_rgbe_dialog(void);
   87 static int write_rgbe_dialog(void);
   88 
   89 GimpPlugInInfo PLUG_IN_INFO =
   90 {
   91    0, 0, query, run
   92 };
   93 
   94 enum
   95 {
   96    IMAGE_TYPE_RGBE,
   97    IMAGE_TYPE_RGBDIV8
   98 };
   99 
  100 /* plug-in data storage structures */
  101 
  102 static struct
  103 {
  104    gboolean preview;
  105    int imgtype;
  106    int tonemap;
  107    int usefilelevels;
  108    float exposure;
  109    float gamma;
  110 } g_tonemap_vals = { 1, IMAGE_TYPE_RGBE, 0, 1, 1.0f, 2.2f };
  111 
  112 static struct
  113 {
  114    int rle;
  115    int writelevels;
  116    float exposure;
  117    float gamma;
  118 } g_write_vals = { 1, 0, 1.0f, 2.2f };
  119 
  120 static struct
  121 {
  122    gboolean preview;
  123    float range;
  124 } g_rgbd8_vals = { 1, 1.0f };
  125 
  126 MAIN()
  127 
  128 static void query(void)
  129 {
  130    static GimpParamDef load_args[]=
  131    {
  132       {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"},
  133       {GIMP_PDB_STRING, "filename", "The name of the file to load"},
  134       {GIMP_PDB_STRING, "raw_filename", "The name entered"},
  135       {GIMP_PDB_INT32, "tonemap", "Tone map the loaded image"},
  136       {GIMP_PDB_INT32, "use_file_levels", "Use exposure and gamma levels in file for tone mapping"},
  137       {GIMP_PDB_FLOAT, "exposure", "Exposure level (default 1.0)"},
  138       {GIMP_PDB_FLOAT, "gamma", "Gamma level (default 2.2)"}
  139    };
  140 
  141    static GimpParamDef load_return_vals[]=
  142    {
  143       {GIMP_PDB_IMAGE, "image", "Output image"}
  144    };
  145 
  146    static GimpParamDef save_args[]=
  147    {
  148       {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"},
  149       {GIMP_PDB_IMAGE, "image", "Input image"},
  150       {GIMP_PDB_DRAWABLE, "drawable", "Drawable to save"},
  151       {GIMP_PDB_STRING, "filename", "The name of the file to save the image as"},
  152       {GIMP_PDB_STRING, "raw_filename", "The name entered"}
  153    };
  154 
  155    static GimpParamDef rgbd8_args[] =
  156    {
  157       {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"},
  158       {GIMP_PDB_IMAGE, "image", "Input image (unused)"},
  159       {GIMP_PDB_DRAWABLE, "drawable", "Input drawable"},
  160       {GIMP_PDB_FLOAT, "range", "Map values [0..1] to [0..range] (default 1.0)"}
  161    };
  162 
  163    static GimpParamDef tonemap_args[] =
  164    {
  165       {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"},
  166       {GIMP_PDB_IMAGE, "image", "Input image (unused)"},
  167       {GIMP_PDB_DRAWABLE, "drawable", "Input drawable"},
  168       {GIMP_PDB_FLOAT, "exposure", "Exposure"},
  169       {GIMP_PDB_FLOAT, "gamma", "Gamma"},
  170    };
  171 
  172    gimp_install_procedure(LOAD_PROC,
  173                           "Loads files in Radiance RGBE format",
  174                           "Loads files in Radiance RGBE format",
  175                           "Shawn Kirst",
  176                           "Shawn Kirst",
  177                           "2007",
  178                           "<Load>/Radiance RGBE",
  179                           0,
  180                           GIMP_PLUGIN,
  181                           G_N_ELEMENTS(load_args),
  182                           G_N_ELEMENTS(load_return_vals),
  183                           load_args, load_return_vals);
  184 
  185    gimp_register_magic_load_handler(LOAD_PROC,
  186                                     "hdr",
  187                                     "",
  188                                     "0,string,#?RADIANCE");
  189 
  190    gimp_install_procedure(SAVE_PROC,
  191                           "Saves files in Radiance RGBE format",
  192                           "Saves files in Radiance RGBE format",
  193                           "Shawn Kirst",
  194                           "Copyright 2007 Shawn Kirst",
  195                           "2007",
  196                           "<Save>/Radiance RGBE",
  197                           "RGBA",
  198                           GIMP_PLUGIN,
  199                           G_N_ELEMENTS(save_args), 0,
  200                           save_args, 0);
  201 
  202    gimp_register_save_handler(SAVE_PROC, "hdr", "");
  203 
  204    gimp_install_procedure("convert_rgbe_to_rgbdiv8",
  205                           "Converts image from Radiance RGBE to RGBdiv8 format",
  206                           "foo!",
  207                           "Shawn Kirst",
  208                           "Copyright 2007 Shawn Kirst",
  209                           "2007",
  210                           "<Image>/Filters/Colors/HDR Tools/Convert Radiance RGBE to RGBdiv8...",
  211                           "RGBA",
  212                           GIMP_PLUGIN,
  213                           G_N_ELEMENTS(rgbd8_args), 0,
  214                           rgbd8_args, NULL);
  215 
  216    gimp_install_procedure("plug_in_tonemap_rgbe",
  217                           "Converts Radiance RGBE data to LDR RGB",
  218                           "foo!",
  219                           "Shawn Kirst",
  220                           "Copyright 2007 Shawn Kirst",
  221                           "2007",
  222                           "<Image>/Filters/Colors/HDR Tools/Tone map Radiance RGBE image",
  223                           "RGBA",
  224                           GIMP_PLUGIN,
  225                           G_N_ELEMENTS(tonemap_args), 0,
  226                           tonemap_args, NULL);
  227 
  228    gimp_install_procedure("plug_in_tonemap_rgbdiv8",
  229                           "Converts HDR RGBdiv8 data to LDR RGB",
  230                           "foo!",
  231                           "Shawn Kirst",
  232                           "Copyright 2007 Shawn Kirst",
  233                           "2007",
  234                           "<Image>/Filters/Colors/HDR Tools/Tone map RGBdiv8 image",
  235                           "RGBA",
  236                           GIMP_PLUGIN,
  237                           G_N_ELEMENTS(tonemap_args), 0,
  238                           tonemap_args, NULL);
  239 }
  240 
  241 static void run(const gchar *name, gint nparams, const GimpParam *param,
  242                 gint *nreturn_vals, GimpParam **return_vals)
  243 {
  244    static GimpParam values[2];
  245    GimpRunMode run_mode;
  246    GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  247    gint32 imageID, drawableID;
  248    GimpDrawable *drawable;
  249    GimpExportReturn export = GIMP_EXPORT_CANCEL;
  250 
  251    run_mode = param[0].data.d_int32;
  252 
  253    *nreturn_vals = 1;
  254    *return_vals = values;
  255 
  256    values[0].type = GIMP_PDB_STATUS;
  257    values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  258 
  259    if(!strcmp(name, LOAD_PROC))
  260    {
  261       switch(run_mode)
  262       {
  263          case GIMP_RUN_INTERACTIVE:
  264             g_run_interactive = 1;
  265             gimp_ui_init(PROG_NAME, 1);
  266 
  267             if(!gimp_get_data(name, &g_tonemap_vals))
  268             {
  269                g_tonemap_vals.tonemap = 0;
  270                g_tonemap_vals.usefilelevels = 1;
  271                g_tonemap_vals.exposure = 1.0f;
  272                g_tonemap_vals.gamma = 2.2f;
  273             }
  274 
  275             if(!read_rgbe_dialog())
  276             {
  277                status = GIMP_PDB_CANCEL;
  278             }
  279             break;
  280          case GIMP_RUN_NONINTERACTIVE:
  281             g_run_interactive = 0;
  282             if(nparams != 7)
  283                status = GIMP_PDB_CALLING_ERROR;
  284             else
  285             {
  286                g_tonemap_vals.tonemap = param[3].data.d_int32;
  287                g_tonemap_vals.usefilelevels = param[4].data.d_int32;
  288                g_tonemap_vals.exposure = param[5].data.d_float;
  289                g_tonemap_vals.gamma = param[6].data.d_float;
  290             }
  291             break;
  292          default:
  293             break;
  294       }
  295 
  296       if(status == GIMP_PDB_SUCCESS)
  297       {
  298          imageID = read_rgbe_image(param[1].data.d_string);
  299          if(imageID != -1)
  300          {
  301             *nreturn_vals = 2;
  302             values[1].type = GIMP_PDB_IMAGE;
  303             values[1].data.d_image = imageID;
  304 
  305             if(g_run_interactive)
  306                gimp_set_data(name, &g_tonemap_vals, sizeof(g_tonemap_vals));
  307          }
  308          else
  309             status = GIMP_PDB_EXECUTION_ERROR;
  310       }
  311    }
  312    else if(!strcmp(name, SAVE_PROC))
  313    {
  314       imageID = param[1].data.d_int32;
  315       drawableID = param[2].data.d_int32;
  316 
  317       switch(run_mode)
  318       {
  319          case GIMP_RUN_INTERACTIVE:
  320          case GIMP_RUN_WITH_LAST_VALS:
  321             gimp_ui_init(PROG_NAME, 0);
  322             export = gimp_export_image(&imageID, &drawableID,
  323                                        "Radiance RGBE",
  324                                        (GIMP_EXPORT_CAN_HANDLE_RGB |
  325                                         GIMP_EXPORT_CAN_HANDLE_ALPHA));
  326             if(export == GIMP_EXPORT_CANCEL)
  327             {
  328                values[0].data.d_status = GIMP_PDB_CANCEL;
  329                return;
  330             }
  331          default:
  332             break;
  333       }
  334 
  335       switch(run_mode)
  336       {
  337          case GIMP_RUN_INTERACTIVE:
  338             g_run_interactive = 1;
  339             if(!gimp_get_data(name, &g_write_vals))
  340             {
  341                g_write_vals.rle = 1;
  342                g_write_vals.writelevels = 0;
  343                g_write_vals.exposure = 1.0f;
  344                g_write_vals.gamma = 2.2f;
  345             }
  346             if(!write_rgbe_dialog())
  347             {
  348                values[0].data.d_status = GIMP_PDB_CANCEL;
  349                return;
  350             }
  351             break;
  352          case GIMP_RUN_NONINTERACTIVE:
  353             g_run_interactive = 0;
  354             if(nparams != 5)
  355                status = GIMP_PDB_CALLING_ERROR;
  356             break;
  357          case GIMP_RUN_WITH_LAST_VALS:
  358             g_run_interactive = 1;
  359             gimp_get_data(name, &g_write_vals);
  360             break;
  361          default:
  362             break;
  363       }
  364 
  365       if(status == GIMP_PDB_SUCCESS)
  366       {
  367          status = write_rgbe_image(param[3].data.d_string, imageID,
  368                                    drawableID);
  369          if(g_run_interactive)
  370             gimp_set_data(name, &g_write_vals, sizeof(g_write_vals));
  371       }
  372 
  373       if(export == GIMP_EXPORT_EXPORT)
  374          gimp_image_delete(imageID);
  375    }
  376    else if(!strcmp(name, "convert_rgbe_to_rgbdiv8"))
  377    {
  378       *nreturn_vals = 1;
  379 
  380       drawable = gimp_drawable_get(param[2].data.d_drawable);
  381 
  382       switch(run_mode)
  383       {
  384          case GIMP_RUN_NONINTERACTIVE:
  385             g_run_interactive = 0;
  386             if(nparams != 4)
  387                status = GIMP_PDB_CALLING_ERROR;
  388             g_rgbd8_vals.range = clamp(param[3].data.d_float, 0, 1);
  389             break;
  390          case GIMP_RUN_WITH_LAST_VALS:
  391             g_run_interactive = 1;
  392             gimp_get_data(name, &g_rgbd8_vals);
  393             break;
  394          case GIMP_RUN_INTERACTIVE:
  395             g_run_interactive = 1;
  396             gimp_ui_init(PROG_NAME, 1);
  397             gimp_get_data(name, &g_rgbd8_vals);
  398             if(!rgbd8_dialog(drawable))
  399             {
  400                status = GIMP_PDB_CANCEL;
  401             }
  402             break;
  403       }
  404 
  405       if(status == GIMP_PDB_SUCCESS)
  406       {
  407          convert_rgbe_to_rgbdiv8(NULL, drawable);
  408          if(g_run_interactive)
  409             gimp_set_data(name, &g_rgbd8_vals, sizeof(g_rgbd8_vals));
  410          gimp_displays_flush();
  411          gimp_drawable_detach(drawable);
  412       }
  413    }
  414    else if(!strcmp(name, "plug_in_tonemap_rgbe") ||
  415            !strcmp(name, "plug_in_tonemap_rgbdiv8"))
  416    {
  417       int imgtype = !strcmp(name, "plug_in_tonemap_rgbe") ? IMAGE_TYPE_RGBE : IMAGE_TYPE_RGBDIV8;
  418 
  419       *nreturn_vals = 1;
  420 
  421       drawable = gimp_drawable_get(param[2].data.d_drawable);
  422 
  423       switch(run_mode)
  424       {
  425          case GIMP_RUN_INTERACTIVE:
  426             gimp_ui_init(PROG_NAME, 1);
  427 
  428             if(!gimp_get_data(name, &g_tonemap_vals))
  429             {
  430                g_tonemap_vals.preview = 1;
  431                g_tonemap_vals.exposure = 1.0f;
  432                g_tonemap_vals.gamma = 2.2f;
  433             }
  434 
  435             g_tonemap_vals.imgtype = imgtype;
  436 
  437             if(!tonemap_dialog(drawable))
  438             {
  439                gimp_drawable_detach(drawable);
  440                return;
  441             }
  442             break;
  443          case GIMP_RUN_NONINTERACTIVE:
  444             if(nparams != 5)
  445                status = GIMP_PDB_CALLING_ERROR;
  446             else
  447             {
  448                g_tonemap_vals.exposure = param[3].data.d_float;
  449                g_tonemap_vals.gamma = param[4].data.d_float;
  450             }
  451             break;
  452          case GIMP_RUN_WITH_LAST_VALS:
  453             gimp_get_data(name, &g_tonemap_vals);
  454             g_tonemap_vals.imgtype = imgtype;
  455             break;
  456          default:
  457             break;
  458       }
  459 
  460       tonemap_image(NULL, drawable);
  461 
  462       if(run_mode != GIMP_RUN_NONINTERACTIVE)
  463          gimp_displays_flush();
  464 
  465       if(run_mode == GIMP_RUN_INTERACTIVE)
  466          gimp_set_data(name, &g_tonemap_vals, sizeof(g_tonemap_vals));
  467 
  468       gimp_drawable_detach(drawable);
  469    }
  470    else
  471       status = GIMP_PDB_CALLING_ERROR;
  472 
  473    values[0].data.d_status = status;
  474 }
  475 
  476 static int rgbe_read_header(rgbe_header_t *hdr, FILE *fp)
  477 {
  478    char buf[128];
  479    float val;
  480 
  481    hdr->flags = 0;
  482 
  483    if(fgets(buf, sizeof(buf), fp) == 0)
  484       return(-1);
  485 
  486    if(strncmp(buf, "#?RADIANCE", 10))
  487       return(-2);
  488 
  489    while(fgets(buf, sizeof(buf), fp))
  490    {
  491       if(buf[0] == '#')
  492       {
  493          // eat comment
  494       }
  495       else if(strncmp(buf, "FORMAT=", 7) == 0)
  496       {
  497          // eat format
  498       }
  499       else if(strncmp(buf, "SOFTWARE=", 9) == 0)
  500       {
  501          // eat creator
  502       }
  503       else if(sscanf(buf, "GAMMA=%g", &val) == 1)
  504       {
  505          hdr->gamma = val;
  506          hdr->flags |= RGBE_HAS_GAMMA;
  507       }
  508       else if(sscanf(buf, "EXPOSURE=%g", &val) == 1)
  509       {
  510          hdr->exposure = val;
  511          hdr->flags |= RGBE_HAS_EXPOSURE;
  512       }
  513       else
  514          break;
  515    }
  516 
  517    if(strcmp(buf, "\n") != 0)
  518    {
  519       printf("\"%s\"\n", buf);
  520       return(-3);
  521    }
  522 
  523    if(fgets(buf, sizeof(buf), fp) == 0)
  524       return(-4);
  525 
  526    if(sscanf(buf, "-Y %d +X %d", &hdr->height, &hdr->width) < 2)
  527       return(-5);
  528 
  529    return(0);
  530 }
  531 
  532 static int rgbe_read_pixels(FILE *fp, unsigned char *data, int num)
  533 {
  534    int n = num * 4;
  535    int r = fread(data, 1, n, fp);
  536    return(-(n != r));
  537 }
  538 
  539 static int rgbe_read_pixels_RLE(FILE *fp, unsigned char *data,
  540                                 int width, int height)
  541 {
  542    unsigned char rgbe[4], *buffer, *ptr, *end, *dst;
  543    int i, count, rc = 0, h = height;
  544    unsigned char buf[2];
  545 
  546    dst = data;
  547 
  548    if((width < 8) || (width > 0x7fff))
  549       return(rgbe_read_pixels(fp, data, width * height));
  550 
  551    buffer = 0;
  552 
  553    while(h > 0)
  554    {
  555       if(fread(rgbe, 1, 4, fp) != 4)
  556       {
  557          rc = -1;
  558          goto read_error;
  559       }
  560 
  561       if((rgbe[0] != 2) || (rgbe[1] != 2) || (rgbe[2] & 0x80))
  562       {
  563          data[0] = rgbe[0];
  564          data[1] = rgbe[1];
  565          data[2] = rgbe[2];
  566          data[3] = rgbe[3];
  567 
  568          if(buffer)
  569             g_free(buffer);
  570 
  571          rc = rgbe_read_pixels(fp, &data[4], (width * h) - 1);
  572 
  573          return(rc ? -2 : 0);
  574       }
  575 
  576       if((((int)rgbe[2]) << 8 | rgbe[3]) != width)
  577       {
  578          rc = -3;
  579          goto read_error;
  580       }
  581 
  582       if(buffer == 0)
  583          buffer = g_malloc(4 * width);
  584 
  585       ptr = buffer;
  586 
  587       for(i = 0; i < 4; ++i)
  588       {
  589          end = &buffer[(i + 1) * width];
  590          while(ptr < end)
  591          {
  592             if(fread(buf, 1, 2, fp) != 2)
  593             {
  594                rc = -4;
  595                goto read_error;
  596             }
  597 
  598             if(buf[0] > 128)
  599             {
  600                count = buf[0] - 128;
  601                if((count == 0) || (count > (end - ptr)))
  602                {
  603                   rc = -5;
  604                   goto read_error;
  605                }
  606 
  607                while(count-- > 0)
  608                   *ptr++ = buf[1];
  609             }
  610             else
  611             {
  612                count = buf[0];
  613                if((count == 0) || (count > (end - ptr)))
  614                {
  615                   rc = -6;
  616                   goto read_error;
  617                }
  618 
  619                *ptr++ = buf[1];
  620 
  621                if(--count > 0)
  622                {
  623                   if(fread(ptr, 1, count, fp) != count)
  624                   {
  625                      rc = -7;
  626                      goto read_error;
  627                   }
  628 
  629                   ptr += count;
  630                }
  631             }
  632          }
  633       }
  634 
  635       for(i = 0; i < width; ++i)
  636       {
  637          dst[4 * i + 0] = buffer[i];
  638          dst[4 * i + 1] = buffer[i + width];
  639          dst[4 * i + 2] = buffer[i + 2 * width];
  640          dst[4 * i + 3] = buffer[i + 3 * width];
  641       }
  642 
  643       dst += 4 * width;
  644 
  645       --h;
  646 
  647       if(g_run_interactive)
  648          gimp_progress_update((gdouble)(height - h) / (gdouble)height);
  649    }
  650 
  651 read_error:
  652 
  653    if(buffer)
  654       g_free(buffer);
  655 
  656    return(rc);
  657 }
  658 
  659 static gint32 read_rgbe_image(gchar *filename)
  660 {
  661    FILE *fp;
  662    int rc;
  663    rgbe_header_t hdr;
  664    unsigned char *pixels;
  665    gchar *tmp;
  666    GimpPixelRgn pixel_rgn;
  667    gint32 image, layer;
  668    GimpDrawable *drawable;
  669 
  670    if(g_run_interactive)
  671    {
  672       tmp = g_strdup_printf("Loading %s:", filename);
  673       gimp_progress_init(tmp);
  674       g_free(tmp);
  675    }
  676 
  677    fp = fopen(filename, "rb");
  678    if(fp == 0)
  679    {
  680       g_message("%s: can't open \"%s\"", PROG_NAME, filename);
  681       return(-1);
  682    }
  683 
  684    rc = rgbe_read_header(&hdr, fp);
  685 
  686    if(rc != 0)
  687    {
  688       g_message("rgbe_read_header() = %d\n", rc);
  689       fclose(fp);
  690       return(-1);
  691    }
  692 
  693    if(g_tonemap_vals.usefilelevels)
  694    {
  695       if(hdr.flags & RGBE_HAS_EXPOSURE)
  696          g_tonemap_vals.exposure = hdr.exposure;
  697       else
  698          g_tonemap_vals.exposure = 1.0f;
  699 
  700       if(hdr.flags & RGBE_HAS_GAMMA)
  701          g_tonemap_vals.gamma = hdr.gamma;
  702       else
  703          g_tonemap_vals.gamma = 2.2f;
  704    }
  705 
  706    pixels = g_malloc(4 * hdr.width * hdr.height);
  707    if(pixels == 0)
  708    {
  709       g_message("Can't allocate pixel buffer\n%s", filename);
  710       fclose(fp);
  711       return(-1);
  712    }
  713 
  714    image = gimp_image_new(hdr.width, hdr.height, GIMP_RGB);
  715    if(image == -1)
  716    {
  717       g_message("Can't allocate new image\n%s", filename);
  718       fclose(fp);
  719       g_free(pixels);
  720       return(-1);
  721    }
  722 
  723    layer = gimp_layer_new(image, "Background", hdr.width, hdr.height,
  724                           GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE);
  725 
  726    gimp_image_set_filename(image, filename);
  727    gimp_image_add_layer(image, layer, 0);
  728    drawable = gimp_drawable_get(layer);
  729 
  730    rc = rgbe_read_pixels_RLE(fp, pixels, hdr.width, hdr.height);
  731    if(rc != 0)
  732    {
  733       g_message("rgbe_read_pixels_RLE() = %d\n", rc);
  734       fclose(fp);
  735       g_free(pixels);
  736       return(-1);
  737    }
  738 
  739    fclose(fp);
  740 
  741    if(g_run_interactive)
  742       gimp_progress_update(1.0);
  743 
  744    gimp_pixel_rgn_init(&pixel_rgn, drawable, 0, 0, drawable->width,
  745                        drawable->height, 1, 0);
  746    gimp_pixel_rgn_set_rect(&pixel_rgn, pixels, 0, 0, drawable->width,
  747                            drawable->height);
  748 
  749    gimp_drawable_flush(drawable);
  750 
  751    if(g_tonemap_vals.tonemap)
  752    {
  753       g_tonemap_vals.imgtype = IMAGE_TYPE_RGBE;
  754       tonemap_image(NULL, drawable);
  755    }
  756 
  757    gimp_drawable_detach(drawable);
  758 
  759    g_free(pixels);
  760 
  761    return(image);
  762 }
  763 
  764 static int rgbe_write_pixels(FILE *fp, unsigned char *data, int num)
  765 {
  766    int n = 4 * num;
  767    int w = fwrite(data, 1, n, fp);
  768    return(-(w != n));
  769 }
  770 
  771 static int rgbe_write_bytes_RLE(FILE *fp, unsigned char *data, int num)
  772 {
  773 #define MIN_RUN_LENGTH 4
  774 
  775    int cur, beg_run, run_count, old_run_count, nonrun_count;
  776    unsigned char buf[2];
  777 
  778    cur = 0;
  779    while(cur < num)
  780    {
  781       beg_run = cur;
  782 
  783       run_count = old_run_count = 0;
  784       while((run_count < MIN_RUN_LENGTH) && (beg_run < num))
  785       {
  786          beg_run += run_count;
  787          old_run_count = run_count;
  788          run_count = 1;
  789          while((beg_run + run_count < num) && (run_count < 127) &&
  790                (data[beg_run] == data[beg_run + run_count]))
  791             run_count++;
  792       }
  793 
  794       if((old_run_count > 1) && (old_run_count == beg_run - cur))
  795       {
  796          buf[0] = 128 + old_run_count;
  797          buf[1] = data[cur];
  798          if(fwrite(buf, 2, 1, fp) < 1)
  799             return(-1);
  800          cur = beg_run;
  801       }
  802 
  803       while(cur < beg_run)
  804       {
  805          nonrun_count = beg_run - cur;
  806          if(nonrun_count > 128)
  807             nonrun_count = 128;
  808          buf[0] = nonrun_count;
  809          if(fwrite(buf, 1, 1, fp) < 1)
  810             return(-1);
  811          if(fwrite(&data[cur], nonrun_count, 1, fp) < 1)
  812             return(-1);
  813          cur += nonrun_count;
  814       }
  815 
  816       if (run_count >= MIN_RUN_LENGTH)
  817       {
  818          buf[0] = 128 + run_count;
  819          buf[1] = data[beg_run];
  820          if(fwrite(buf, 2, 1, fp) < 1)
  821             return(-1);
  822          cur += run_count;
  823       }
  824    }
  825 
  826    return(0);
  827 
  828 #undef MINRUNLENGTH
  829 }
  830 
  831 static int rgbe_write_pixels_RLE(FILE *fp, unsigned char *data,
  832                                  int rle, int width, int height)
  833 {
  834    unsigned char rgbe[4], *buffer;
  835    int i, rc = 0;
  836 
  837    if(!rle || ((width < 8) || (width > 0x7fff)))
  838       return(rgbe_write_pixels(fp, data, width * height));
  839 
  840    buffer = (unsigned char *)g_malloc(4 * width);
  841 
  842    while(height-- > 0)
  843    {
  844       rgbe[0] = 2;
  845       rgbe[1] = 2;
  846       rgbe[2] = width >> 8;
  847       rgbe[3] = width & 0xff;
  848 
  849       if(fwrite(rgbe, sizeof(rgbe), 1, fp) < 1)
  850       {
  851          g_free(buffer);
  852          return(-1);
  853       }
  854 
  855       for(i = 0; i < width; ++i)
  856       {
  857          buffer[i] = data[4 * i];
  858          buffer[i + width] = data[4 * i + 1];
  859          buffer[i + 2 * width] = data[4 * i + 2];
  860          buffer[i + 3 * width] = data[4 * i + 3];
  861       }
  862 
  863       data += 4 * width;
  864 
  865       /* write out each of the four channels separately run length encoded */
  866       /* first red, then green, then blue, then exponent */
  867       for(i = 0; i < 4; ++i)
  868       {
  869          if((rc = rgbe_write_bytes_RLE(fp, &buffer[i * width], width)))
  870          {
  871             g_free(buffer);
  872             return(rc);
  873          }
  874       }
  875    }
  876 
  877    g_free(buffer);
  878 
  879    return(rc);
  880 }
  881 
  882 static GimpPDBStatusType write_rgbe_image(gchar *filename, gint32 imageID,
  883                                           gint32 drawableID)
  884 {
  885    FILE *fp;
  886    GimpDrawable *drawable;
  887    GimpImageType drawable_type;
  888    GimpPixelRgn rgn;
  889    int rc;
  890    guchar *pixels;
  891    gchar *tmp;
  892 
  893    drawable = gimp_drawable_get(drawableID);
  894    drawable_type = gimp_drawable_type(drawableID);
  895    gimp_pixel_rgn_init(&rgn, drawable, 0, 0, drawable->width,
  896                        drawable->height, 0, 0);
  897 
  898    fp = fopen(filename, "wb");
  899    if(fp == 0)
  900    {
  901       g_message("Error opening %s", filename);
  902       return(GIMP_PDB_EXECUTION_ERROR);
  903    }
  904 
  905    pixels = g_malloc(drawable->width * drawable->height * 4);
  906    gimp_pixel_rgn_get_rect(&rgn, pixels, 0, 0, drawable->width,
  907                            drawable->height);
  908 
  909    if(g_run_interactive)
  910    {
  911       tmp = g_strdup_printf("Saving %s:", filename);
  912       gimp_progress_init(tmp);
  913       g_free(tmp);
  914    }
  915 
  916    fprintf(fp,
  917            "#?RADIANCE\n"
  918            "# %s\n"
  919            "SOFTWARE=GIMP HDR tools\n"
  920            "FORMAT=32-bit_rle_rgbe\n",
  921            g_write_vals.rle ? "RLE compressed" : "Not RLE compressed");
  922 
  923    if(g_write_vals.writelevels)
  924    {
  925       fprintf(fp,
  926               "EXPOSURE=%f\n"
  927               "GAMMA=%f\n",
  928               g_write_vals.exposure, g_write_vals.gamma);
  929    }
  930 
  931    fprintf(fp,
  932            "\n-Y %d +X %d\n",
  933            drawable->height, drawable->width);
  934 
  935    rc = rgbe_write_pixels_RLE(fp, pixels, g_write_vals.rle,
  936                               drawable->width, drawable->height);
  937    fclose(fp);
  938 
  939    gimp_drawable_detach(drawable);
  940 
  941    g_free(pixels);
  942 
  943    return(rc ? GIMP_PDB_EXECUTION_ERROR : GIMP_PDB_SUCCESS);
  944 }
  945 
  946 static void convert_rgbe_to_rgbdiv8(GimpPreview *preview,
  947                                     GimpDrawable *drawable)
  948 {
  949    GimpPixelRgn srcrgn, dstrgn;
  950    unsigned char *src, *dst, *rgbe;
  951    float rgb[3], maxchan, v, range;
  952    int sx, sy, x, y, w, h, n, idx = 0;
  953 
  954    range = g_rgbd8_vals.range;
  955 
  956    if(preview)
  957    {
  958       gimp_preview_get_position(preview, &sx, &sy);
  959       gimp_preview_get_size(preview, &w, &h);
  960    }
  961    else
  962    {
  963       sx = 0;
  964       sy = 0;
  965       w = drawable->width;
  966       h = drawable->height;
  967    }
  968 
  969    n = w * h;
  970    dst = g_malloc(n * 4);
  971    src = g_malloc(n * 4);
  972 
  973    gimp_pixel_rgn_init(&srcrgn, drawable, sx, sy, w, h, 0, 0);
  974    gimp_pixel_rgn_get_rect(&srcrgn, src, sx, sy, w, h);
  975 
  976    if(!preview)
  977       gimp_progress_init("Converting to RGBdiv8...");
  978 
  979    for(y = 0; y < h; ++y)
  980    {
  981       for(x = 0; x < w; ++x)
  982       {
  983          rgbe = &src[idx];
  984          if(rgbe[3])
  985          {
  986             v = ldexpf(1.0f, rgbe[3] - 136);
  987             rgb[0] = (float)rgbe[0] * v;
  988             rgb[1] = (float)rgbe[1] * v;
  989             rgb[2] = (float)rgbe[2] * v;
  990          }
  991          else
  992             rgb[0] = rgb[1] = rgb[2] = 0;
  993 
  994          maxchan = max(range, max(rgb[0], max(rgb[1], rgb[2])));
  995 
  996          dst[idx++] = (unsigned char)(255.0f * rgb[0] / maxchan);
  997          dst[idx++] = (unsigned char)(255.0f * rgb[1] / maxchan);
  998          dst[idx++] = (unsigned char)(255.0f * rgb[2] / maxchan);
  999          dst[idx++] = (unsigned char)(255.0f * range  / maxchan);
 1000       }
 1001 
 1002       if(!preview)
 1003          gimp_progress_update((gdouble)y / (gdouble)drawable->height);
 1004    }
 1005 
 1006 
 1007    gimp_pixel_rgn_init(&dstrgn, drawable, sx, sy, w, h,
 1008                        preview == NULL, 1);
 1009    gimp_pixel_rgn_set_rect(&dstrgn, dst, sx, sy, w, h);
 1010 
 1011    if(preview)
 1012    {
 1013       gimp_drawable_preview_draw_region(GIMP_DRAWABLE_PREVIEW(preview),
 1014                                         &dstrgn);
 1015    }
 1016    else
 1017    {
 1018       gimp_progress_update(100);
 1019 
 1020       gimp_drawable_flush(drawable);
 1021       gimp_drawable_merge_shadow(drawable->drawable_id, 1);
 1022       gimp_drawable_update(drawable->drawable_id, 0, 0, w, h);
 1023    }
 1024 
 1025    g_free(src);
 1026    g_free(dst);
 1027 }
 1028 
 1029 static void tonemap_image(GimpPreview *preview, GimpDrawable *drawable)
 1030 {
 1031    GimpPixelRgn srcrgn, dstrgn;
 1032    unsigned char *src, *dst;
 1033    float rgb[3], v;
 1034    int sx, sy, x, y, w, h, n, idx = 0;
 1035 
 1036    if(preview)
 1037    {
 1038       gimp_preview_get_position(preview, &sx, &sy);
 1039       gimp_preview_get_size(preview, &w, &h);
 1040    }
 1041    else
 1042    {
 1043       sx = 0;
 1044       sy = 0;
 1045       w = drawable->width;
 1046       h = drawable->height;
 1047    }
 1048 
 1049    n = w * h;
 1050 
 1051    dst = g_malloc(n * 4);
 1052    src = g_malloc(n * 4);
 1053 
 1054    gimp_pixel_rgn_init(&srcrgn, drawable, sx, sy, w, h, 0, 0);
 1055    gimp_pixel_rgn_get_rect(&srcrgn, src, sx, sy, w, h);
 1056 
 1057    if(!preview)
 1058       gimp_progress_init("Tone mapping image...");
 1059 
 1060    for(y = 0; y < h; ++y)
 1061    {
 1062       for(x = 0; x < w; ++x)
 1063       {
 1064          if(g_tonemap_vals.imgtype == IMAGE_TYPE_RGBE)
 1065          {
 1066             if(src[idx + 3])
 1067             {
 1068                v = ldexpf(1.0f, src[idx + 3] - 136);
 1069                rgb[0] = (float)src[idx + 0] * v;
 1070                rgb[1] = (float)src[idx + 1] * v;
 1071                rgb[2] = (float)src[idx + 2] * v;
 1072             }
 1073             else
 1074                rgb[0] = rgb[1] = rgb[2] = 0;
 1075          }
 1076          else
 1077          {
 1078             v = (float)src[idx + 3] / 255.0f;
 1079             if(v > 0)
 1080             {
 1081                rgb[0] = ((float)src[idx + 0] / 255.0f) / v;
 1082                rgb[1] = ((float)src[idx + 1] / 255.0f) / v;
 1083                rgb[2] = ((float)src[idx + 2] / 255.0f) / v;
 1084             }
 1085             else
 1086                rgb[0] = rgb[1] = rgb[2] = FLT_MAX;
 1087          }
 1088 
 1089          /* exposure */
 1090          rgb[0] = 1.0f - expf(-rgb[0] * g_tonemap_vals.exposure);
 1091          rgb[1] = 1.0f - expf(-rgb[1] * g_tonemap_vals.exposure);
 1092          rgb[2] = 1.0f - expf(-rgb[2] * g_tonemap_vals.exposure);
 1093 
 1094          /* gamma correction */
 1095          rgb[0] = powf(rgb[0], 1.0f / g_tonemap_vals.gamma);
 1096          rgb[1] = powf(rgb[1], 1.0f / g_tonemap_vals.gamma);
 1097          rgb[2] = powf(rgb[2], 1.0f / g_tonemap_vals.gamma);
 1098 
 1099          rgb[0] = clamp(rgb[0], 0, 1);
 1100          rgb[1] = clamp(rgb[1], 0, 1);
 1101          rgb[2] = clamp(rgb[2], 0, 1);
 1102 
 1103          dst[idx++] = (unsigned char)(255.0f * rgb[0]);
 1104          dst[idx++] = (unsigned char)(255.0f * rgb[1]);
 1105          dst[idx++] = (unsigned char)(255.0f * rgb[2]);
 1106          dst[idx++] = 255;
 1107       }
 1108 
 1109       if(!preview)
 1110          gimp_progress_update((gdouble)y / (gdouble)h);
 1111    }
 1112 
 1113    gimp_pixel_rgn_init(&dstrgn, drawable, sx, sy, w, h,
 1114                        preview == NULL, 1);
 1115    gimp_pixel_rgn_set_rect(&dstrgn, dst, sx, sy, w, h);
 1116 
 1117    if(preview)
 1118    {
 1119       gimp_drawable_preview_draw_region(GIMP_DRAWABLE_PREVIEW(preview),
 1120                                         &dstrgn);
 1121    }
 1122    else
 1123    {
 1124       gimp_progress_update(100);
 1125 
 1126       gimp_drawable_flush(drawable);
 1127       gimp_drawable_merge_shadow(drawable->drawable_id, 1);
 1128       gimp_drawable_update(drawable->drawable_id, 0, 0, w, h);
 1129    }
 1130 
 1131    g_free(src);
 1132    g_free(dst);
 1133 }
 1134 
 1135 static void on_spin_changed(GtkWidget *widget, gpointer data)
 1136 {
 1137    float *val = (float*)data;
 1138    *val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
 1139    GimpPreview *preview = g_object_get_data(G_OBJECT(widget), "preview");
 1140    if(preview)
 1141       gimp_preview_invalidate(preview);
 1142 }
 1143 
 1144 static void on_slider_changed(GtkWidget *widget, gpointer data)
 1145 {
 1146    float *val = (float*)data;
 1147    *val = gtk_range_get_value(GTK_RANGE(widget));
 1148    GimpPreview *preview = g_object_get_data(G_OBJECT(widget), "preview");
 1149    if(preview)
 1150       gimp_preview_invalidate(preview);
 1151 }
 1152 
 1153 static void on_checkbox_clicked(GtkWidget *widget, gpointer data)
 1154 {
 1155    int *val = (int*)data;
 1156    *val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
 1157 }
 1158 
 1159 static void dialog_response(GtkWidget *widget, gint response_id,
 1160                             gpointer data)
 1161 {
 1162    switch(response_id)
 1163    {
 1164       case GTK_RESPONSE_OK:
 1165          g_runme = 1;
 1166       default:
 1167          gtk_widget_destroy(widget);
 1168          break;
 1169    }
 1170 }
 1171 
 1172 static int tonemap_dialog(GimpDrawable *drawable)
 1173 {
 1174    GtkWidget *dlg;
 1175    GtkWidget *table;
 1176    GtkWidget *label;
 1177    GtkObject *adj;
 1178    GtkWidget *hbox;
 1179    GtkWidget *preview, *exposure_spin, *gamma_spin;
 1180 
 1181    dlg = gimp_dialog_new("Tone map image", PROG_NAME,
 1182                          0, 0, 0, 0,
 1183                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 1184                          GTK_STOCK_OK, GTK_RESPONSE_OK,
 1185                          NULL);
 1186 
 1187    hbox = gtk_hbox_new(0, 8);
 1188    gtk_widget_show(hbox);
 1189    gtk_container_set_border_width(GTK_CONTAINER(hbox), 8);
 1190    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), hbox, 1, 1, 0);
 1191 
 1192    preview = gimp_drawable_preview_new(drawable, &g_tonemap_vals.preview);
 1193    gtk_widget_show(preview);
 1194    gtk_box_pack_start(GTK_BOX(hbox), preview, 1, 1, 0);
 1195 
 1196    table = gtk_table_new(2, 2, 0);
 1197    gtk_widget_show(table);
 1198    gtk_box_pack_start(GTK_BOX(hbox), table, 1, 1, 0);
 1199    gtk_table_set_row_spacings(GTK_TABLE(table), 8);
 1200    gtk_table_set_col_spacings(GTK_TABLE(table), 8);
 1201 
 1202    label = gtk_label_new("Exposure:");
 1203    gtk_widget_show(label);
 1204    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 1205    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
 1206 
 1207    adj = gtk_adjustment_new(g_tonemap_vals.exposure, 0, 100, 0.1, 0.5, 1);
 1208    exposure_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1);
 1209    gtk_widget_show(exposure_spin);
 1210    gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(exposure_spin),
 1211                                      GTK_UPDATE_IF_VALID);
 1212    gtk_table_attach(GTK_TABLE(table), exposure_spin, 1, 2, 0, 1,
 1213                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
 1214    g_object_set_data(G_OBJECT(exposure_spin), "preview", preview);
 1215 
 1216    label = gtk_label_new("Gamma:");
 1217    gtk_widget_show(label);
 1218    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 1219    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
 1220 
 1221    adj = gtk_adjustment_new(g_tonemap_vals.gamma, 0, 100, 0.1, 0.5, 1);
 1222    gamma_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1);
 1223    gtk_widget_show(gamma_spin);
 1224    gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(gamma_spin),
 1225                                      GTK_UPDATE_IF_VALID);
 1226    gtk_table_attach(GTK_TABLE(table), gamma_spin, 1, 2, 1, 2,
 1227                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
 1228    g_object_set_data(G_OBJECT(gamma_spin), "preview", preview);
 1229 
 1230 
 1231    gtk_signal_connect(GTK_OBJECT(dlg), "response",
 1232                       GTK_SIGNAL_FUNC(dialog_response), 0);
 1233    gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
 1234                       GTK_SIGNAL_FUNC(gtk_main_quit), 0);
 1235    gtk_signal_connect(GTK_OBJECT(preview), "invalidated",
 1236                       GTK_SIGNAL_FUNC(tonemap_image),
 1237                       drawable);
 1238    gtk_signal_connect(GTK_OBJECT(exposure_spin), "value_changed",
 1239                       GTK_SIGNAL_FUNC(on_spin_changed),
 1240                       &g_tonemap_vals.exposure);
 1241    gtk_signal_connect(GTK_OBJECT(gamma_spin), "value_changed",
 1242                       GTK_SIGNAL_FUNC(on_spin_changed),
 1243                       &g_tonemap_vals.gamma);
 1244 
 1245    gtk_widget_show(dlg);
 1246 
 1247    g_runme = 0;
 1248 
 1249    gtk_main();
 1250 
 1251    return(g_runme);
 1252 }
 1253 
 1254 static int rgbd8_dialog(GimpDrawable *drawable)
 1255 {
 1256    GtkWidget *dlg;
 1257    GtkObject *adj;
 1258    GtkWidget *slider;
 1259    GtkWidget *vbox;
 1260    GtkWidget *table;
 1261    GtkWidget *preview;
 1262 
 1263    dlg = gimp_dialog_new("Convert Radiance RGBE to RGBdiv8", PROG_NAME,
 1264                          0, 0, 0, 0,
 1265                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 1266                          GTK_STOCK_OK, GTK_RESPONSE_OK,
 1267                          NULL);
 1268 
 1269    vbox = gtk_vbox_new(0, 0);
 1270    gtk_widget_show(vbox);
 1271    gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
 1272    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), vbox, 1, 1, 0);
 1273 
 1274    table = gtk_table_new(2, 2, 0);
 1275    gtk_widget_show(table);
 1276    gtk_box_pack_start(GTK_BOX(vbox), table, 1, 1, 0);
 1277    gtk_table_set_row_spacings(GTK_TABLE(table), 8);
 1278    gtk_table_set_col_spacings(GTK_TABLE(table), 8);
 1279 
 1280    preview = gimp_drawable_preview_new(drawable, &g_rgbd8_vals.preview);
 1281    gtk_widget_show(preview);
 1282    gtk_table_attach(GTK_TABLE(table), preview, 0, 2, 0, 1,
 1283                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
 1284 
 1285    adj = gtk_adjustment_new(g_rgbd8_vals.range, 0, 1, 0.01, 0.1, 0);
 1286    slider = gtk_hscale_new(GTK_ADJUSTMENT(adj));
 1287    gtk_widget_show(slider);
 1288    gtk_scale_set_value_pos(GTK_SCALE(slider), GTK_POS_RIGHT);
 1289    gtk_scale_set_digits(GTK_SCALE(slider), 2);
 1290    gimp_table_attach_aligned(GTK_TABLE(table), 0, 1, "Range:", 0, 0.5,
 1291                              slider, 1, 0);
 1292    g_object_set_data(G_OBJECT(slider), "preview", preview);
 1293 
 1294    gtk_signal_connect(GTK_OBJECT(dlg), "response",
 1295                       GTK_SIGNAL_FUNC(dialog_response), 0);
 1296    gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
 1297                       GTK_SIGNAL_FUNC(gtk_main_quit), 0);
 1298    gtk_signal_connect(GTK_OBJECT(preview), "invalidated",
 1299                       GTK_SIGNAL_FUNC(convert_rgbe_to_rgbdiv8), drawable);
 1300    gtk_signal_connect(GTK_OBJECT(slider), "value_changed",
 1301                       GTK_SIGNAL_FUNC(on_slider_changed),
 1302                       &g_rgbd8_vals.range);
 1303 
 1304    gtk_widget_show(dlg);
 1305 
 1306    g_runme = 0;
 1307 
 1308    gtk_main();
 1309 
 1310    return(g_runme);
 1311 }
 1312 
 1313 static void on_file_levels_checked(GtkWidget *widget, gpointer data)
 1314 {
 1315    GtkWidget *spin;
 1316    int val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
 1317 
 1318    *((int *)data) = val;
 1319 
 1320    spin = g_object_get_data(G_OBJECT(widget), "exposure_spin");
 1321    gtk_widget_set_sensitive(spin, !val);
 1322    spin = g_object_get_data(G_OBJECT(widget), "gamma_spin");
 1323    gtk_widget_set_sensitive(spin, !val);
 1324 }
 1325 
 1326 static int read_rgbe_dialog(void)
 1327 {
 1328    GtkWidget *dlg;
 1329    GtkWidget *table;
 1330    GtkWidget *label;
 1331    GtkObject *adj;
 1332    GtkWidget *tmchk, *uflchk, *exposure_spin, *gamma_spin;
 1333 
 1334    dlg = gimp_dialog_new("Load RGBE image", PROG_NAME,
 1335                          0, 0, 0, 0,
 1336                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 1337                          GTK_STOCK_OK, GTK_RESPONSE_OK,
 1338                          NULL);
 1339 
 1340    table = gtk_table_new(4, 2, 0);
 1341    gtk_widget_show(table);
 1342    gtk_container_set_border_width(GTK_CONTAINER(table), 8);
 1343    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), table, 1, 1, 0);
 1344    gtk_table_set_row_spacings(GTK_TABLE(table), 8);
 1345    gtk_table_set_col_spacings(GTK_TABLE(table), 8);
 1346 
 1347    tmchk = gtk_check_button_new_with_label("Tone map image");
 1348    gtk_widget_show(tmchk);
 1349    gtk_table_attach(GTK_TABLE(table), tmchk, 0, 2, 0, 1,
 1350                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
 1351    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmchk),
 1352                                 g_tonemap_vals.tonemap);
 1353 
 1354    uflchk = gtk_check_button_new_with_label("Use file levels");
 1355    gtk_widget_show(uflchk);
 1356    gtk_table_attach(GTK_TABLE(table), uflchk, 0, 2, 1, 2,
 1357                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
 1358    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(uflchk),
 1359                                 g_tonemap_vals.usefilelevels);
 1360 
 1361    label = gtk_label_new("Exposure:");
 1362    gtk_widget_show(label);
 1363    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0);
 1364    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 1365 
 1366    adj = gtk_adjustment_new(g_tonemap_vals.exposure, 0, 100, 0.1, 0.5, 0.1);
 1367    exposure_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1);
 1368    gtk_widget_show(exposure_spin);
 1369    gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(exposure_spin),
 1370                                      GTK_UPDATE_IF_VALID);
 1371    gtk_table_attach(GTK_TABLE(table), exposure_spin, 1, 2, 2, 3,
 1372                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
 1373    gtk_widget_set_sensitive(exposure_spin, !g_tonemap_vals.usefilelevels);
 1374 
 1375    label = gtk_label_new("Gamma:");
 1376    gtk_widget_show(label);
 1377    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0);
 1378    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 1379 
 1380    adj = gtk_adjustment_new(g_tonemap_vals.gamma, 0, 100, 0.1, 0.5, 0.1);
 1381    gamma_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1);
 1382    gtk_widget_show(gamma_spin);
 1383    gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(gamma_spin),
 1384                                      GTK_UPDATE_IF_VALID);
 1385    gtk_table_attach(GTK_TABLE(table), gamma_spin, 1, 2, 3, 4,
 1386                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
 1387    gtk_widget_set_sensitive(gamma_spin, !g_tonemap_vals.usefilelevels);
 1388 
 1389    g_object_set_data(G_OBJECT(uflchk), "exposure_spin", exposure_spin);
 1390    g_object_set_data(G_OBJECT(uflchk), "gamma_spin", gamma_spin);
 1391 
 1392    gtk_signal_connect(GTK_OBJECT(dlg), "response",
 1393                       GTK_SIGNAL_FUNC(dialog_response), 0);
 1394    gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
 1395                       GTK_SIGNAL_FUNC(gtk_main_quit), 0);
 1396    gtk_signal_connect(GTK_OBJECT(tmchk), "clicked",
 1397                       GTK_SIGNAL_FUNC(on_checkbox_clicked),
 1398                       &g_tonemap_vals.tonemap);
 1399    gtk_signal_connect(GTK_OBJECT(uflchk), "clicked",
 1400                       GTK_SIGNAL_FUNC(on_file_levels_checked),
 1401                       &g_tonemap_vals.usefilelevels);
 1402    gtk_signal_connect(GTK_OBJECT(exposure_spin), "value_changed",
 1403                       GTK_SIGNAL_FUNC(on_spin_changed),
 1404                       &g_tonemap_vals.exposure);
 1405    gtk_signal_connect(GTK_OBJECT(gamma_spin), "value_changed",
 1406                       GTK_SIGNAL_FUNC(on_spin_changed),
 1407                       &g_tonemap_vals.gamma);
 1408 
 1409    gtk_widget_show(dlg);
 1410 
 1411    g_runme = 0;
 1412 
 1413    gtk_main();
 1414 
 1415    return(g_runme);
 1416 }
 1417 
 1418 static void on_write_levels_checked(GtkWidget *widget, gpointer data)
 1419 {
 1420    GtkWidget *spin;
 1421    int val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
 1422 
 1423    *((int *)data) = val;
 1424 
 1425    spin = g_object_get_data(G_OBJECT(widget), "exposure_spin");
 1426    gtk_widget_set_sensitive(spin, val);
 1427    spin = g_object_get_data(G_OBJECT(widget), "gamma_spin");
 1428    gtk_widget_set_sensitive(spin, val);
 1429 }
 1430 
 1431 static int write_rgbe_dialog(void)
 1432 {
 1433    GtkWidget *dlg;
 1434    GtkWidget *table;
 1435    GtkWidget *label;
 1436    GtkObject *adj;
 1437    GtkWidget *rlechk, *wlchk, *exposure_spin, *gamma_spin;
 1438 
 1439    dlg = gimp_dialog_new("Save RGBE image", PROG_NAME,
 1440                          0, 0, 0, 0,
 1441                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 1442                          GTK_STOCK_OK, GTK_RESPONSE_OK,
 1443                          NULL);
 1444 
 1445    table = gtk_table_new(4, 2, 0);
 1446    gtk_widget_show(table);
 1447    gtk_container_set_border_width(GTK_CONTAINER(table), 8);
 1448    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), table, 1, 1, 0);
 1449    gtk_table_set_row_spacings(GTK_TABLE(table), 8);
 1450    gtk_table_set_col_spacings(GTK_TABLE(table), 8);
 1451 
 1452    rlechk = gtk_check_button_new_with_label("RLE compression");
 1453    gtk_widget_show(rlechk);
 1454    gtk_table_attach(GTK_TABLE(table), rlechk, 0, 2, 0, 1,
 1455                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
 1456    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rlechk),
 1457                                 g_write_vals.rle);
 1458 
 1459    wlchk = gtk_check_button_new_with_label("Write exposure and gamma");
 1460    gtk_widget_show(wlchk);
 1461    gtk_table_attach(GTK_TABLE(table), wlchk, 0, 2, 1, 2,
 1462                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
 1463    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wlchk),
 1464                                 g_write_vals.writelevels);
 1465 
 1466    label = gtk_label_new("Exposure:");
 1467    gtk_widget_show(label);
 1468    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0);
 1469    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 1470 
 1471    adj = gtk_adjustment_new(g_write_vals.exposure, 0, 100, 0.1, 0.5, 0.1);
 1472    exposure_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1);
 1473    gtk_widget_show(exposure_spin);
 1474    gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(exposure_spin),
 1475                                      GTK_UPDATE_IF_VALID);
 1476    gtk_table_attach(GTK_TABLE(table), exposure_spin, 1, 2, 2, 3,
 1477                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
 1478    gtk_widget_set_sensitive(exposure_spin, g_write_vals.writelevels);
 1479 
 1480    label = gtk_label_new("Gamma:");
 1481    gtk_widget_show(label);
 1482    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0);
 1483    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 1484 
 1485    adj = gtk_adjustment_new(g_write_vals.gamma, 0, 100, 0.1, 0.5, 0.1);
 1486    gamma_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1);
 1487    gtk_widget_show(gamma_spin);
 1488    gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(gamma_spin),
 1489                                      GTK_UPDATE_IF_VALID);
 1490    gtk_table_attach(GTK_TABLE(table), gamma_spin, 1, 2, 3, 4,
 1491                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
 1492    gtk_widget_set_sensitive(gamma_spin, g_write_vals.writelevels);
 1493 
 1494    g_object_set_data(G_OBJECT(wlchk), "exposure_spin", exposure_spin);
 1495    g_object_set_data(G_OBJECT(wlchk), "gamma_spin", gamma_spin);
 1496 
 1497    gtk_signal_connect(GTK_OBJECT(dlg), "response",
 1498                       GTK_SIGNAL_FUNC(dialog_response), 0);
 1499    gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
 1500                       GTK_SIGNAL_FUNC(gtk_main_quit), 0);
 1501    gtk_signal_connect(GTK_OBJECT(rlechk), "clicked",
 1502                       GTK_SIGNAL_FUNC(on_checkbox_clicked),
 1503                       &g_write_vals.rle);
 1504    gtk_signal_connect(GTK_OBJECT(wlchk), "clicked",
 1505                       GTK_SIGNAL_FUNC(on_write_levels_checked),
 1506                       &g_write_vals.writelevels);
 1507    gtk_signal_connect(GTK_OBJECT(exposure_spin), "value_changed",
 1508                       GTK_SIGNAL_FUNC(on_spin_changed),
 1509                       &g_write_vals.exposure);
 1510    gtk_signal_connect(GTK_OBJECT(gamma_spin), "value_changed",
 1511                       GTK_SIGNAL_FUNC(on_spin_changed),
 1512                       &g_write_vals.gamma);
 1513 
 1514    gtk_widget_show(dlg);
 1515 
 1516    g_runme = 0;
 1517 
 1518    gtk_main();
 1519 
 1520    return(g_runme);
 1521 }

ViewVC Help
Powered by ViewVC 1.0.4