add gamma correction suggested by coni
authorgc <gc>
Mon, 30 Jan 2006 18:56:06 +0000 (18:56 +0000)
committergc <gc>
Mon, 30 Jan 2006 18:56:06 +0000 (18:56 +0000)
bin/booh
bin/booh-gamma-correction [new file with mode: 0755]
data/booh/images/stock-tool-brightness-contrast-16.png [new file with mode: 0644]
data/man/man1/booh-gamma-correction [new file with mode: 0644]
ext/rbbooh.c
lib/booh/booh-lib.rb

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?
diff --git a/bin/booh-gamma-correction b/bin/booh-gamma-correction
new file mode 100755 (executable)
index 0000000..ab92c8f
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/ruby
+#
+#                         *  BOOH  *
+#
+# A.k.a `Best web-album Of the world, Or your money back, Humerus'.
+#
+# The acronyn sucks, however this is a tribute to Dragon Ball by
+# Akira Toriyama, where the last enemy beaten by heroes of Dragon
+# Ball is named "Boo". But there was already a free software project
+# called Boo, so this one will be it "Booh". Or whatever.
+#
+#
+# Copyright (c) 2005 Guillaume Cottenceau <gc3 at bluewin.ch>
+#
+# This software may be freely redistributed under the terms of the GNU
+# public license version 2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+require 'gtk2'
+require 'booh/gtkadds'
+
+if ARGV.size != 3
+    puts "Usage: %s orig_file dest_file_jpeg level" % File.basename($0)
+    exit 1
+
+else
+    Gdk::Pixbuf.new(ARGV[0]).gammacorrect!(ARGV[2].to_f).save(ARGV[1], "jpeg")
+end
diff --git a/data/booh/images/stock-tool-brightness-contrast-16.png b/data/booh/images/stock-tool-brightness-contrast-16.png
new file mode 100644 (file)
index 0000000..b6ca5ea
Binary files /dev/null and b/data/booh/images/stock-tool-brightness-contrast-16.png differ
diff --git a/data/man/man1/booh-gamma-correction b/data/man/man1/booh-gamma-correction
new file mode 100644 (file)
index 0000000..4433734
--- /dev/null
@@ -0,0 +1,44 @@
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License
+.\" along with this program; if not, write to the Free Software
+.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+.\"
+
+.TH BOOH 1 "June 2005" "BOOH" "The booh web-album"
+
+.SH NAME
+booh-gamma-corection \- a booh helper to perform gamma correction on a picture
+
+.SH SYNOPSIS
+\fBbooh-gamma-correction \fIorig_file dest_file.jpg level\fR
+
+.SH DESCRIPTION
+\fBbooh-gamma-correction\fR is normally invoked by \fBbooh\fR or
+\fBbooh-backend\fR to perform gamma correction on pictures in a
+web-album. The \fIlevel\fR indicates the "strength" of the
+correction and is negative to darken pictures or positive to
+brighten pictures.
+
+.SH AUTHOR
+Written by Guillaume Cottenceau.
+.br
+Visit official homepage: http://zarb.org/~gc/html/booh.html
+
+.SH SEE ALSO
+.BR booh(1)
+.BR booh-backend(1)
+
+.SH COPYRIGHT
+Copyright \(co 2005 Guillaume Cottenceau.
+.br
+This is Free Software; this software is licensed under the GPL version 2, as published by the Free Software Foundation.
+There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
index 12285ed5b1020ed4c3ae0b7d4d55352d48454313..2d886888f2ab7b1449518472414486c5afe09b4c 100644 (file)
@@ -59,9 +59,40 @@ whitebalance(self, level)
         return self;
 }
 
+static VALUE
+gammacorrect(self, level)
+    VALUE self, level; 
+{
+        double filter[256];
+        int i, x, y;
+        guchar* pixels = gdk_pixbuf_get_pixels(_SELF(self));
+        int rowstride = gdk_pixbuf_get_rowstride(_SELF(self));
+
+        double factor = 1 + fabs(NUM2DBL(level))/100;
+        if (NUM2DBL(level) > 0) {
+                factor = 1/factor;
+        }
+
+        for (i = 0; i < 256; i++) {
+                filter[i] = pow(((double)i)/255, factor) * 255;
+        }
+    
+        for (y = 0; y < gdk_pixbuf_get_height(_SELF(self)); y++) {
+                guchar* pixline = &(pixels[rowstride*y]);
+                for (x = 0; x < gdk_pixbuf_get_width(_SELF(self)); x++) {
+                        pixline[x*3]   = filter[pixline[x*3]];
+                        pixline[x*3+1] = filter[pixline[x*3+1]];
+                        pixline[x*3+2] = filter[pixline[x*3+2]];
+                }
+        }
+
+        return self;
+}
+
 void 
 Init_gtkadds()
 {
     RGObjClassInfo* cinfo = (RGObjClassInfo*)rbgobj_lookup_class_by_gtype(GDK_TYPE_PIXBUF, Qnil);
     rb_define_method(cinfo->klass, "whitebalance!", whitebalance, 1); 
+    rb_define_method(cinfo->klass, "gammacorrect!", gammacorrect, 1); 
 }
index 1121c956e2098456d562fc12ed26585c0eacf62a..35a3b36df353cad96cf1b9b54104705e25df4a73 100644 (file)
@@ -287,6 +287,14 @@ module Booh
                         orig = neworig
                     end
                 end
+                if gammacorrect = felem.attributes["#{attributes_prefix}gamma-correction"]
+                    neworig = "#{dest_dir}/#{File.basename(orig)}-gammacorrect#{gammacorrect}.jpg"
+                    cmd = "booh-gamma-correction '#{orig}' '#{neworig}' #{gammacorrect}"
+                    sys(cmd)
+                    if File.exists?(neworig)
+                        orig = neworig
+                    end
+                end
                 rotate = felem.attributes["#{attributes_prefix}rotate"]
                 if !rotate
                     felem.add_attribute("#{attributes_prefix}rotate", rotate = guess_rotate(orig).to_i)
@@ -381,6 +389,16 @@ module Booh
                             end
                         end
                     end
+                    if felem && gammacorrect = felem.attributes["#{attributes_prefix}gamma-correction"]
+                        if gammacorrect.to_f != 0
+                            neworig = "#{dest_dir}/#{orig_base}-gammacorrect#{gammacorrect}.jpg"
+                            cmd = "booh-gamma-correction '#{orig_image}' '#{neworig}' #{gammacorrect}"
+                            sys(cmd)
+                            if File.exists?(neworig)
+                                orig_image = neworig
+                            end
+                        end
+                    end
                 end
                 if !File.exists?(dest['filename'])
                     sys("#{$convert} #{convert_options}-size #{dest['size']} -resize #{dest['size']} '#{orig_image}' '#{dest['filename']}'")