add gamma correction suggested by coni
[booh] / bin / booh
index 962fd9766d6f1162ec32c51418457d5417ef9313..c9f52c3a9e218668f238b675a869e417379c9c37 100755 (executable)
--- a/bin/booh
+++ b/bin/booh
@@ -442,6 +442,11 @@ def update_shown_pixbuf(thumbnail_img, img, desired_x, desired_y)
         pixbuf.whitebalance!($modified_pixbufs[thumbnail_img][:whitebalance])
     end
 
+    #- fix gamma correction
+    if $modified_pixbufs[thumbnail_img][:gammacorrect]
+        pixbuf.gammacorrect!($modified_pixbufs[thumbnail_img][:gammacorrect])
+    end
+
     img.pixbuf = $modified_pixbufs[thumbnail_img][:pixbuf] = pixbuf
 end
 
@@ -619,14 +624,20 @@ def recalc_whitebalance(level, orig, thumbnail_img, img, xmlelem, attributes_pre
 
     #- in case the white balance was already modified in the config file and thumbnail, we cannot just revert, we need to use original file
     if (!$modified_pixbufs[thumbnail_img] || !$modified_pixbufs[thumbnail_img][:whitebalance]) && xmlelem.attributes["#{attributes_prefix}white-balance"]
+        save_gammacorrect = xmlelem.attributes["#{attributes_prefix}gamma-correction"]
+        xmlelem.delete_attribute("#{attributes_prefix}gamma-correction")
         save_whitebalance = xmlelem.attributes["#{attributes_prefix}white-balance"]
         xmlelem.delete_attribute("#{attributes_prefix}white-balance")
-        destfile = "#{thumbnail_img}-orig-whitebalance.jpg"
+        destfile = "#{thumbnail_img}-orig-gammacorrect-whitebalance.jpg"
         gen_real_thumbnail_core(attributes_prefix == '' ? 'element' : 'subdir', orig, destfile,
                                 xmlelem, attributes_prefix == '' ? $default_size['thumbnails'] : $albums_thumbnail_size, infotype)
         $modified_pixbufs[thumbnail_img] ||= {}
         $modified_pixbufs[thumbnail_img][:orig] = pixbuf_or_nil(destfile)
         xmlelem.add_attribute("#{attributes_prefix}white-balance", save_whitebalance)
+        if save_gammacorrect
+            xmlelem.add_attribute("#{attributes_prefix}gamma-correction", save_gammacorrect)
+            $modified_pixbufs[thumbnail_img][:gammacorrect] = save_gammacorrect.to_f
+        end
         $modified_pixbufs[thumbnail_img][:angle_to_orig] = 0
     end
 
@@ -694,6 +705,95 @@ slider below the image to the left for more blue, to the right for more yellow.
     }
 end
 
+def change_gammacorrect(xmlelem, attributes_prefix, value)
+    $modified = true
+    xmlelem.add_attribute("#{attributes_prefix}gamma-correction", value)
+end
+
+def recalc_gammacorrect(level, orig, thumbnail_img, img, xmlelem, attributes_prefix, desired_x, desired_y, infotype)
+
+    #- in case the gamma correction was already modified in the config file and thumbnail, we cannot just revert, we need to use original file
+    if (!$modified_pixbufs[thumbnail_img] || !$modified_pixbufs[thumbnail_img][:gammacorrect]) && xmlelem.attributes["#{attributes_prefix}gamma-correction"]
+        save_gammacorrect = xmlelem.attributes["#{attributes_prefix}gamma-correction"]
+        xmlelem.delete_attribute("#{attributes_prefix}gamma-correction")
+        save_whitebalance = xmlelem.attributes["#{attributes_prefix}white-balance"]
+        xmlelem.delete_attribute("#{attributes_prefix}white-balance")
+        destfile = "#{thumbnail_img}-orig-gammacorrect-whitebalance.jpg"
+        gen_real_thumbnail_core(attributes_prefix == '' ? 'element' : 'subdir', orig, destfile,
+                                xmlelem, attributes_prefix == '' ? $default_size['thumbnails'] : $albums_thumbnail_size, infotype)
+        $modified_pixbufs[thumbnail_img] ||= {}
+        $modified_pixbufs[thumbnail_img][:orig] = pixbuf_or_nil(destfile)
+        xmlelem.add_attribute("#{attributes_prefix}gamma-correction", save_gammacorrect)
+        if save_whitebalance
+            xmlelem.add_attribute("#{attributes_prefix}white-balance", save_whitebalance)
+            $modified_pixbufs[thumbnail_img][:whitebalance] = save_whitebalance.to_f
+        end
+        $modified_pixbufs[thumbnail_img][:angle_to_orig] = 0
+    end
+
+    $modified_pixbufs[thumbnail_img] ||= {}
+    $modified_pixbufs[thumbnail_img][:gammacorrect] = level.to_f
+
+    update_shown_pixbuf(thumbnail_img, img, desired_x, desired_y)
+end
+
+def ask_gammacorrect(orig, thumbnail_img, img_, xmlelem, attributes_prefix, desired_x, desired_y, infotype)
+    #- init $modified_pixbufs correctly
+#    update_shown_pixbuf(thumbnail_img, img_, desired_x, desired_y)
+
+    value = xmlelem ? (xmlelem.attributes["#{attributes_prefix}gamma-correction"] || "0") : "0"
+
+    dialog = Gtk::Dialog.new(utf8(_("Gamma correction")),
+                             $main_window,
+                             Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT,
+                             [Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK],
+                             [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL])
+
+    lbl = Gtk::Label.new
+    lbl.markup = utf8(
+_("You can perform <b>gamma correction</b> of the image, if your image is too dark
+or too bright. Drag the slider below the image.
+"))
+    dialog.vbox.add(lbl)
+    if img_
+        dialog.vbox.add(evt = Gtk::EventBox.new.add(img = Gtk::Image.new(img_.pixbuf)))
+    end
+    dialog.vbox.add(hs = Gtk::HScale.new(-200, 200, 1).set_value(value.to_i))
+    
+    dialog.window_position = Gtk::Window::POS_MOUSE
+    dialog.show_all
+
+    lastval = nil
+    timeout = Gtk.timeout_add(100) {
+        if hs.value != lastval
+            lastval = hs.value
+            if img_
+                recalc_gammacorrect(lastval, orig, thumbnail_img, img, xmlelem, attributes_prefix, desired_x, desired_y, infotype)
+            end
+        end
+        true
+    }
+
+    dialog.run { |response|
+        Gtk.timeout_remove(timeout)
+        if response == Gtk::Dialog::RESPONSE_OK
+            $modified = true
+            newval = hs.value.to_s
+            msg 3, "gamma correction to #{newval}"
+            dialog.destroy
+            return { :old => value, :new => newval }
+        else
+            if thumbnail_img
+                $modified_pixbufs[thumbnail_img] ||= {}
+                $modified_pixbufs[thumbnail_img][:gammacorrect] = value.to_f
+                $modified_pixbufs[thumbnail_img][:pixbuf] = img_.pixbuf
+            end
+            dialog.destroy
+            return nil
+        end
+    }
+end
+
 def gen_real_thumbnail_core(type, origfile, destfile, xmldir, size, infotype)
     system("rm -f '#{destfile}'")
     #- type can be 'element' or 'subdir'
@@ -835,6 +935,17 @@ def popup_thumbnail_menu(event, optionals, fullpath, type, xmldir, attributes_pr
         end
     end
     menu.append(               Gtk::SeparatorMenuItem.new)
+    menu.append(gammacorrect = Gtk::ImageMenuItem.new(utf8(_("Gamma correction"))))
+    gammacorrect.image = Gtk::Image.new("#{$FPATH}/images/stock-tool-brightness-contrast-16.png")
+    gammacorrect.signal_connect('activate') { 
+        if possible_actions[:can_multiple] && $selected_elements.length > 0
+            if values = ask_gammacorrect(nil, nil, nil, nil, '', nil, nil, '')
+                distribute_multiple_call.call(:gammacorrect, values)
+            end
+        else
+            closures[:gammacorrect].call
+        end
+    }
     menu.append(whitebalance = Gtk::ImageMenuItem.new(utf8(_("Fix white-balance"))))
     whitebalance.image = Gtk::Image.new("#{$FPATH}/images/stock-tool-color-balance-16.png")
     whitebalance.signal_connect('activate') { 
@@ -1153,6 +1264,37 @@ def add_thumbnail(autotable, filename, type, thumbnail_img, caption)
         end
     }
 
+     gammacorrect_and_cleanup_real = proc { |values|
+         perform_change_gammacorrect_and_cleanup = Proc.new { |val|
+             change_gammacorrect($xmldir.elements["*[@filename='#{filename}']"], '', val)
+             recalc_gammacorrect(val, fullpath, thumbnail_img, img,
+                                 $xmldir.elements["*[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y], '')
+             cleanup_all_thumbnails.call
+         }
+         perform_change_gammacorrect_and_cleanup.call(values[:new])
+         save_undo(_("gamma correction"),
+                   Proc.new {
+                       perform_change_gammacorrect_and_cleanup.call(values[:old])
+                       textview.grab_focus
+                       autoscroll_if_needed($autotable_sw, img, textview)
+                       $notebook.set_page(1)
+                       Proc.new {
+                           perform_change_gammacorrect_and_cleanup.call(values[:new])
+                           textview.grab_focus
+                           autoscroll_if_needed($autotable_sw, img, textview)
+                           $notebook.set_page(1)
+                       }
+                   })
+     }
+     gammacorrect_and_cleanup = Proc.new {
+         if values = ask_gammacorrect(fullpath, thumbnail_img, img,
+                                      $xmldir.elements["*[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y], '')
+             gammacorrect_and_cleanup_real.call(values)
+         end
+     }
+
     enhance_and_cleanup = proc {
         perform_enhance_and_cleanup = proc {
             enhance($xmldir.elements["*[@filename='#{filename}']"], '')
@@ -1253,7 +1395,8 @@ def add_thumbnail(autotable, filename, type, thumbnail_img, caption)
 
     $name2closures[filename] = { :rotate => rotate_and_cleanup, :enhance => enhance_and_cleanup, :delete => delete, :cut => cut,
                                  :color_swap => color_swap_and_cleanup, :frame_offset => change_frame_offset_and_cleanup_real,
-                                 :whitebalance => whitebalance_and_cleanup_real, :pano => change_pano_amount_and_cleanup_real, :refresh => refresh }
+                                 :whitebalance => whitebalance_and_cleanup_real, :gammacorrect => gammacorrect_and_cleanup_real,
+                                 :pano => change_pano_amount_and_cleanup_real, :refresh => refresh }
 
     textview.signal_connect('key-press-event') { |w, event|
         propagate = true
@@ -1372,7 +1515,7 @@ def add_thumbnail(autotable, filename, type, thumbnail_img, caption)
                                      { :rotate => rotate_and_cleanup, :move => move, :color_swap => color_swap_and_cleanup, :enhance => enhance_and_cleanup,
                                        :frame_offset => change_frame_offset_and_cleanup, :delete => delete, :whitebalance => whitebalance_and_cleanup,
                                        :cut => cut, :paste => paste, :view => proc { view_element(filename, { :delete => delete }) },
-                                       :pano => change_pano_amount_and_cleanup, :refresh => refresh })
+                                       :pano => change_pano_amount_and_cleanup, :refresh => refresh, :gammacorrect => gammacorrect_and_cleanup })
             end
             $ignore_next_release = false
             $gesture_press = nil
@@ -2302,6 +2445,29 @@ def change_dir
             end
         }
 
+        gammacorrect_and_cleanup = proc {
+            if values = ask_gammacorrect(captionfile, thumbnail_file, img, xmldir, "#{infotype}-",
+                                         $default_albums_thumbnails[:x], $default_albums_thumbnails[:y], infotype)
+                perform_change_gammacorrect_and_cleanup = proc { |val|
+                    change_gammacorrect(xmldir, "#{infotype}-", val)
+                    recalc_gammacorrect(val, captionfile, thumbnail_file, img, xmldir, "#{infotype}-",
+                                        $default_albums_thumbnails[:x], $default_albums_thumbnails[:y], infotype)
+                    system("rm -f '#{thumbnail_file}'")
+                }
+                perform_change_gammacorrect_and_cleanup.call(values[:new])
+                
+                save_undo(_("gamma correction"),
+                          proc {
+                              perform_change_gammacorrect_and_cleanup.call(values[:old])
+                              $notebook.set_page(0)
+                              proc {
+                                  perform_change_gammacorrect_and_cleanup.call(values[:new])
+                                  $notebook.set_page(0)
+                              }
+                          })
+            end
+        }
+
         enhance_and_cleanup = proc {
             perform_enhance_and_cleanup = proc {
                 enhance(xmldir, "#{infotype}-")
@@ -2338,7 +2504,7 @@ def change_dir
                                        :can_top => counter > 1, :can_bottom => counter > 0 && counter < subalbums_counter },
                                      { :change => change_image, :move => move, :rotate => rotate_and_cleanup, :enhance => enhance_and_cleanup,
                                        :color_swap => color_swap_and_cleanup, :frame_offset => change_frame_offset_and_cleanup, :whitebalance => whitebalance_and_cleanup,
-                                       :refresh => refresh })
+                                       :gammacorrect => gammacorrect_and_cleanup, :refresh => refresh })
             end
             if event.event_type == Gdk::Event::BUTTON2_PRESS && event.button == 1
                 change_image.call
@@ -3985,6 +4151,7 @@ French: Guillaume Cottenceau')),
                 nothing.sensitive = true
             end
         end
+        true
     }
     $r270.signal_connect('toggled') {
         if $r270.active?