add fix whitebalance
authorgc <gc>
Mon, 16 May 2005 16:48:48 +0000 (16:48 +0000)
committergc <gc>
Mon, 16 May 2005 16:48:48 +0000 (16:48 +0000)
INSTALL
bin/booh
bin/booh-backend
bin/booh-fix-whitebalance [new file with mode: 0644]
bin/webalbum2booh
data/booh/images/stock-tool-color-balance-16.png [new file with mode: 0644]
ext/extconf.rb [new file with mode: 0644]
ext/rbbooh.c [new file with mode: 0644]
lib/booh/booh-lib.rb

diff --git a/INSTALL b/INSTALL
index 90ae584..d6c147e 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -3,6 +3,7 @@ This software requires:
 - ruby
 - ruby-gettext >= 0.8.0
 - ruby-gtk2
+- devel of ruby-gnome2 (mkmf-gnome2.rb, rbgobject.h)
 
 
         Quick Start
@@ -11,11 +12,9 @@ Type this (You might needs super user previledge):
 
 ($ su)
  # ruby setup.rb
-
-If you want to install the program into your home directory
-($HOME), use following instead:
-
-$ ruby setup.rb all --prefix=$HOME
+ # cd ext
+ # ruby extconf.rb
+ # make install
 
 
         Detailed Installation Process
index fa6c354..d42b71b 100755 (executable)
--- a/bin/booh
+++ b/bin/booh
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby
+#! /usr/bin/ruby
 #
 #                         *  BOOH  *
 #
@@ -23,6 +23,7 @@ require 'getoptlong'
 require 'tempfile'
 
 require 'gtk2'
+require 'booh/gtkadds'
 require 'booh/GtkAutoTable'
 
 require 'gettext'
@@ -299,31 +300,46 @@ def create_editzone(scrolledwindow, pagenum, image)
     return [ frame, textview ]
 end
 
+def update_shown_pixbuf(thumbnail_img, img, desired_x, desired_y)
+
+    if !$modified_pixbufs[thumbnail_img]
+        $modified_pixbufs[thumbnail_img] = { :orig => img.pixbuf }
+    elsif !$modified_pixbufs[thumbnail_img][:orig]
+        $modified_pixbufs[thumbnail_img][:orig] = img.pixbuf
+    end
+
+    pixbuf = $modified_pixbufs[thumbnail_img][:orig].dup
+
+    #- rotate
+    if $modified_pixbufs[thumbnail_img][:angle_to_orig] && $modified_pixbufs[thumbnail_img][:angle_to_orig] != 0
+        pixbuf = rotate_pixbuf(pixbuf, $modified_pixbufs[thumbnail_img][:angle_to_orig])
+        msg 3, "sizes: #{pixbuf.width} #{pixbuf.height} - desired #{desired_x}x#{desired_x}"
+        if pixbuf.height > desired_y
+            pixbuf = pixbuf.scale(pixbuf.width * (desired_y.to_f/pixbuf.height), desired_y, Gdk::Pixbuf::INTERP_BILINEAR)
+        elsif pixbuf.width < desired_x && pixbuf.height < desired_y
+            pixbuf = pixbuf.scale(desired_x, pixbuf.height * (desired_x.to_f/pixbuf.width), Gdk::Pixbuf::INTERP_BILINEAR)
+        end
+    end
+
+    #- fix white balance
+    if $modified_pixbufs[thumbnail_img][:whitebalance]
+        pixbuf.whitebalance!($modified_pixbufs[thumbnail_img][:whitebalance])
+    end
+
+    img.pixbuf = $modified_pixbufs[thumbnail_img][:pixbuf] = pixbuf
+end
+
 def rotate_real(angle, thumbnail_img, img, xmlelem, attributes_prefix, desired_x, desired_y)
     $modified = true
 
     #- update rotate attribute
-    xmlelem.add_attribute("#{attributes_prefix}rotate", current_angle = (xmlelem.attributes["#{attributes_prefix}rotate"].to_i + angle) % 360)
+    xmlelem.add_attribute("#{attributes_prefix}rotate", (xmlelem.attributes["#{attributes_prefix}rotate"].to_i + angle) % 360)
 
-    if !$rotated_pixbufs[thumbnail_img]
-        $rotated_pixbufs[thumbnail_img] = { :orig => img.pixbuf, :angle_to_orig => angle % 360 }
-    else
-        $rotated_pixbufs[thumbnail_img][:angle_to_orig] = ($rotated_pixbufs[thumbnail_img][:angle_to_orig] + angle) % 360
-    end
-    msg 3, "angle: #{angle}, angle to orig: #{$rotated_pixbufs[thumbnail_img][:angle_to_orig]}"
-
-    #- rotate shown thumbnail
-    pixbuf = rotate_pixbuf($rotated_pixbufs[thumbnail_img][:orig], $rotated_pixbufs[thumbnail_img][:angle_to_orig])
-    msg 3, "sizes: #{pixbuf.width} #{pixbuf.height} - desired #{desired_x}x#{desired_x}"
-    if pixbuf.height > desired_y
-        img.pixbuf = $rotated_pixbufs[thumbnail_img][:pixbuf] = pixbuf.scale(pixbuf.width * (desired_y.to_f/pixbuf.height), desired_y,
-                                                                             Gdk::Pixbuf::INTERP_BILINEAR)
-    elsif pixbuf.width < desired_x && pixbuf.height < desired_y
-        img.pixbuf = $rotated_pixbufs[thumbnail_img][:pixbuf] = pixbuf.scale(desired_x, pixbuf.height * (desired_x.to_f/pixbuf.width),
-                                                                             Gdk::Pixbuf::INTERP_BILINEAR)
-    else
-        img.pixbuf = $rotated_pixbufs[thumbnail_img][:pixbuf] = pixbuf
-    end
+    $modified_pixbufs[thumbnail_img] ||= {}
+    $modified_pixbufs[thumbnail_img][:angle_to_orig] = (($modified_pixbufs[thumbnail_img][:angle_to_orig] || 0) + angle) % 360
+    msg 3, "angle: #{angle}, angle to orig: #{$modified_pixbufs[thumbnail_img][:angle_to_orig]}"
+
+    update_shown_pixbuf(thumbnail_img, img, desired_x, desired_y)
 end
 
 def rotate(angle, thumbnail_img, img, xmlelem, attributes_prefix, desired_x, desired_y)
@@ -398,10 +414,10 @@ from. There are approximately 25 frames per second in a video.
     dialog.show_all
 
     dialog.run { |response|
-        $modified = true
         newval = entry.text
         dialog.destroy
         if response == Gtk::Dialog::RESPONSE_OK
+            $modified = true
             msg 3, "changing frame offset top #{newval}"
             return { :old => value, :new => newval }
         else
@@ -410,18 +426,110 @@ from. There are approximately 25 frames per second in a video.
     }
 end
 
-def gen_real_thumbnail(type, origfile, destfile, xmldir, size, img)
-    Thread.new {
-        push_mousecursor_wait
+def change_whitebalance(xmlelem, attributes_prefix, value)
+    $modified = true
+    xmlelem.add_attribute("#{attributes_prefix}white-balance", value)
+end
+
+def recalc_whitebalance(level, orig, thumbnail_img, img, xmlelem, attributes_prefix, desired_x, desired_y, infotype)
+
+    #- 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_whitebalance = xmlelem.attributes["#{attributes_prefix}white-balance"]
+        xmlelem.delete_attribute("#{attributes_prefix}white-balance")
+        destfile = "#{thumbnail_img}-orig-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)
         system("rm -f '#{destfile}'")
-        #- type can be 'element' or 'subdir'
-        if type == 'element'
-            gen_thumbnails_element(origfile, xmldir, false, [ { 'filename' => destfile, 'size' => size } ])
+        xmlelem.add_attribute("#{attributes_prefix}white-balance", save_whitebalance)
+        $modified_pixbufs[thumbnail_img][:angle_to_orig] = 0
+        if entry2type(orig) == 'video'
+            #- cleanup temp for videos
+            system("rm -f #{current_dest_dir}/screenshot.jpg000000.jpg")
+        end
+    end
+
+    $modified_pixbufs[thumbnail_img] ||= {}
+    $modified_pixbufs[thumbnail_img][:whitebalance] = level.to_f
+
+    update_shown_pixbuf(thumbnail_img, img, desired_x, desired_y)
+end
+
+def ask_whitebalance(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.attributes["#{attributes_prefix}white-balance"] || "0"
+
+    dialog = Gtk::Dialog.new(utf8(_("Fix white balance")),
+                             $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 fix the <b>white balance</b> of the image, if your image is too blue
+or too yellow because your camera didn't detect the light correctly. Drag the
+slider below the image to the left for more blue, to the right for more yellow.
+"))
+    dialog.vbox.add(lbl)
+    dialog.vbox.add(evt = Gtk::EventBox.new.add(img = Gtk::Image.new(img_.pixbuf)))
+    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
+    thread = nil
+    timeout = Gtk.timeout_add(100) {
+        if hs.value != lastval
+            lastval = hs.value
+            if thread
+                thread.kill
+            end
+            thread = Thread.new {
+                recalc_whitebalance(lastval, orig, thumbnail_img, img, xmlelem, attributes_prefix, desired_x, desired_y, infotype)
+            }
+        end
+        true
+    }
+
+    dialog.run { |response|
+        Gtk.timeout_remove(timeout)
+        if response == Gtk::Dialog::RESPONSE_OK
+            $modified = true
+            newval = hs.value.to_s
+            msg 3, "changing white balance to #{newval}"
+            dialog.destroy
+            return { :old => value, :new => newval }
         else
-            gen_thumbnails_subdir(origfile, xmldir, false, [ { 'filename' => destfile, 'size' => size } ], find_subalbum_info_type(xmldir))
+            $modified_pixbufs[thumbnail_img] ||= {}
+            $modified_pixbufs[thumbnail_img][:whitebalance] = value.to_f
+            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'
+    if type == 'element'
+        gen_thumbnails_element(origfile, xmldir, false, [ { 'filename' => destfile, 'size' => size } ])
+    else
+        gen_thumbnails_subdir(origfile, xmldir, false, [ { 'filename' => destfile, 'size' => size } ], infotype)
+    end
+end
+
+def gen_real_thumbnail(type, origfile, destfile, xmldir, size, img, infotype)
+    Thread.new {
+        push_mousecursor_wait
+        gen_real_thumbnail_core(type, origfile, destfile, xmldir, size, infotype)
         img.set(destfile)
-        $rotated_pixbufs[destfile] = { :orig => img.pixbuf, :pixbuf => img.pixbuf, :angle_to_orig => 0 }
+        $modified_pixbufs[destfile] = { :orig => img.pixbuf, :pixbuf => img.pixbuf, :angle_to_orig => 0 }
         if entry2type(origfile) == 'video'
             #- cleanup temp for videos
             system("rm -f #{current_dest_dir}/screenshot.jpg000000.jpg")
@@ -438,12 +546,15 @@ def popup_thumbnail_menu(event, optionals, type, xmldir, attributes_prefix, clos
         changeimg.signal_connect('activate') { closures[:change].call }
         menu.append(            Gtk::SeparatorMenuItem.new)
     end
-    menu.append(    r90 = Gtk::ImageMenuItem.new(utf8(_("Rotate clockwise"))))
+    menu.append(r90 = Gtk::ImageMenuItem.new(utf8(_("Rotate clockwise"))))
     r90.image = Gtk::Image.new("#{$FPATH}/images/stock-rotate-90-16.png")
     r90.signal_connect('activate') { closures[:rotate].call(90) }
-    menu.append(   r270 = Gtk::ImageMenuItem.new(utf8(_("Rotate counter-clockwise"))))
+    menu.append(r270 = Gtk::ImageMenuItem.new(utf8(_("Rotate counter-clockwise"))))
     r270.image = Gtk::Image.new("#{$FPATH}/images/stock-rotate-270-16.png")
     r270.signal_connect('activate') { closures[:rotate].call(-90) }
+    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') { closures[:whitebalance].call }
     if type == 'video'
         menu.append(               Gtk::SeparatorMenuItem.new)
         menu.append(  color_swap = Gtk::ImageMenuItem.new(utf8(_("Red/blue color swap"))))
@@ -476,15 +587,15 @@ def add_thumbnail(autotable, filename, type, thumbnail_img, caption)
     frame1 = Gtk::Frame.new
 
     my_gen_real_thumbnail = proc {
-        gen_real_thumbnail('element', from_utf8("#{$current_path}/#{filename}"), thumbnail_img, $xmldir, $default_size['thumbnails'], img)
+        gen_real_thumbnail('element', from_utf8("#{$current_path}/#{filename}"), thumbnail_img, $xmldir, $default_size['thumbnails'], img, '')
     }
 
     #- generate the thumbnail if missing (if image was rotated but booh was not relaunched)
-    if !$rotated_pixbufs[thumbnail_img] && !File.exists?(thumbnail_img)
+    if !$modified_pixbufs[thumbnail_img] && !File.exists?(thumbnail_img)
         frame1.add(img = Gtk::Image.new)
         my_gen_real_thumbnail.call
     else
-        frame1.add(img = Gtk::Image.new($rotated_pixbufs[thumbnail_img] ? $rotated_pixbufs[thumbnail_img][:pixbuf] : thumbnail_img))
+        frame1.add(img = Gtk::Image.new($modified_pixbufs[thumbnail_img] ? $modified_pixbufs[thumbnail_img][:pixbuf] : thumbnail_img))
     end
     evtbox = Gtk::EventBox.new.add(Gtk::Alignment.new(0.5, 0.5, 0, 0).add(frame1.set_shadow_type(Gtk::SHADOW_ETCHED_OUT)))
 
@@ -561,6 +672,29 @@ def add_thumbnail(autotable, filename, type, thumbnail_img, caption)
         end
     }
 
+    whitebalance_and_cleanup = Proc.new {
+        if values = ask_whitebalance(from_utf8("#{$current_path}/#{filename}"), thumbnail_img, img,
+                                     $xmldir.elements["[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y], '')
+            perform_change_whitebalance_and_cleanup = Proc.new { |val|
+                change_whitebalance($xmldir.elements["[@filename='#{filename}']"], '', val)
+                recalc_whitebalance(val, from_utf8("#{$current_path}/#{filename}"), thumbnail_img, img,
+                                    $xmldir.elements["[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y], '')
+                cleanup_all_thumbnails.call
+            }
+            perform_change_whitebalance_and_cleanup.call(values[:new])
+
+            save_undo(_("fix white balance"),
+                      Proc.new {
+                          perform_change_whitebalance_and_cleanup.call(values[:old])
+                          $notebook.set_page(1)
+                          Proc.new {
+                              perform_change_whitebalance_and_cleanup.call(values[:new])
+                              $notebook.set_page(1)
+                          }
+                      })
+        end
+    }
+
     enhance_and_cleanup = Proc.new {
         perform_enhance_and_cleanup = Proc.new {
             enhance($xmldir.elements["[@filename='#{filename}']"], '')
@@ -706,7 +840,7 @@ def add_thumbnail(autotable, filename, type, thumbnail_img, caption)
         if event.event_type == Gdk::Event::BUTTON_PRESS && event.button == 3
             popup_thumbnail_menu(event, ['delete'], type, $xmldir.elements["[@filename='#{filename}']"], '',
                                  { :rotate => rotate_and_cleanup, :color_swap => color_swap_and_cleanup, :enhance => enhance_and_cleanup,
-                                   :frame_offset => change_frame_offset_and_cleanup, :delete => delete })
+                                   :frame_offset => change_frame_offset_and_cleanup, :delete => delete, :whitebalance => whitebalance_and_cleanup })
         end
         if event.event_type == Gdk::Event::BUTTON2_PRESS && event.button == 1
             view_element(filename)
@@ -989,14 +1123,14 @@ def change_dir
 
         img = nil
         my_gen_real_thumbnail = proc {
-            gen_real_thumbnail('subdir', captionfile, thumbnail_file, xmldir, $albums_thumbnail_size, img)
+            gen_real_thumbnail('subdir', captionfile, thumbnail_file, xmldir, $albums_thumbnail_size, img, infotype)
         }
 
-        if !$rotated_pixbufs[thumbnail_file] && !File.exists?(thumbnail_file)
+        if !$modified_pixbufs[thumbnail_file] && !File.exists?(thumbnail_file)
             f.add(img = Gtk::Image.new)
             my_gen_real_thumbnail.call
         else
-            f.add(img = Gtk::Image.new($rotated_pixbufs[thumbnail_file] ? $rotated_pixbufs[thumbnail_file][:pixbuf] : thumbnail_file))
+            f.add(img = Gtk::Image.new($modified_pixbufs[thumbnail_file] ? $modified_pixbufs[thumbnail_file][:pixbuf] : thumbnail_file))
         end
         hbox.pack_end(Gtk::Alignment.new(0.5, 0.5, 0, 0).add(evtbox = Gtk::EventBox.new.add(f)), false, false)
         $subalbums.attach(hbox,
@@ -1035,7 +1169,7 @@ def change_dir
                 msg 3, "new captionfile is: #{fc.filename}"
                 perform_changefile = Proc.new {
                     $subalbums_edits[xmldir.attributes['path']][:captionfile] = captionfile = new_file
-                    $rotated_pixbufs.delete(thumbnail_file)
+                    $modified_pixbufs.delete(thumbnail_file)
                     xmldir.delete_attribute("#{infotype}-rotate")
                     xmldir.delete_attribute("#{infotype}-color-swap")
                     xmldir.delete_attribute("#{infotype}-enhance")
@@ -1105,6 +1239,29 @@ def change_dir
             end
         }
 
+        whitebalance_and_cleanup = Proc.new {
+            if values = ask_whitebalance(captionfile, thumbnail_file, img, xmldir, "#{infotype}-",
+                                         $default_albums_thumbnails[:x], $default_albums_thumbnails[:y], infotype)
+                perform_change_whitebalance_and_cleanup = Proc.new { |val|
+                    change_whitebalance(xmldir, "#{infotype}-", val)
+                    recalc_whitebalance(val, captionfile, thumbnail_file, img, xmldir, "#{infotype}-",
+                                        $default_albums_thumbnails[:x], $default_albums_thumbnails[:y], infotype)
+                    system("rm -f '#{thumbnail_file}'")
+                }
+                perform_change_whitebalance_and_cleanup.call(values[:new])
+                
+                save_undo(_("fix white balance"),
+                          Proc.new {
+                              perform_change_whitebalance_and_cleanup.call(values[:old])
+                              $notebook.set_page(0)
+                              Proc.new {
+                                  perform_change_whitebalance_and_cleanup.call(values[:new])
+                                  $notebook.set_page(0)
+                              }
+                          })
+            end
+        }
+
         enhance_and_cleanup = Proc.new {
             perform_enhance_and_cleanup = Proc.new {
                 enhance(xmldir, "#{infotype}-")
@@ -1137,7 +1294,7 @@ def change_dir
             if event.event_type == Gdk::Event::BUTTON_PRESS && event.button == 3
                 popup_thumbnail_menu(event, ['change_image'], entry2type(captionfile), xmldir, "#{infotype}-",
                                      { :change => change_image, :rotate => rotate_and_cleanup, :enhance => enhance_and_cleanup,
-                                       :color_swap => color_swap_and_cleanup, :frame_offset => change_frame_offset_and_cleanup })
+                                       :color_swap => color_swap_and_cleanup, :frame_offset => change_frame_offset_and_cleanup, :whitebalance => whitebalance_and_cleanup })
             end
             if event.event_type == Gdk::Event::BUTTON2_PRESS && event.button == 1
                 change_image.call
@@ -1301,7 +1458,7 @@ def open_file(filename)
     $filename = nil
     $modified = false
     $current_path = nil   #- invalidate
-    $rotated_pixbufs = {}
+    $modified_pixbufs = {}
     $albums_ts.clear
     $autotable.clear
     $subalbums_vb.children.each { |chld|
index 2da7fa3..f079e09 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby
+#! /usr/bin/ruby
 #
 #                         *  BOOH  *
 #
diff --git a/bin/booh-fix-whitebalance b/bin/booh-fix-whitebalance
new file mode 100644 (file)
index 0000000..3358da9
--- /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]).whitebalance!(ARGV[2].to_f).save(ARGV[1], "jpeg")
+end
index ecf35a7..2113a3d 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby
+#! /usr/bin/ruby
 #
 #                         *  BOOH  *
 #
diff --git a/data/booh/images/stock-tool-color-balance-16.png b/data/booh/images/stock-tool-color-balance-16.png
new file mode 100644 (file)
index 0000000..fc22067
Binary files /dev/null and b/data/booh/images/stock-tool-color-balance-16.png differ
diff --git a/ext/extconf.rb b/ext/extconf.rb
new file mode 100644 (file)
index 0000000..9463aa2
--- /dev/null
@@ -0,0 +1,16 @@
+=begin
+extconf.rb for booh additions to Ruby/GdkPixbuf
+=end
+
+PACKAGE_NAME = "booh/gtkadds"
+
+require 'mkmf-gnome2'
+
+PKGConfig.have_package('gdk-pixbuf-2.0') or exit 1
+
+setup_win32(PACKAGE_NAME)
+
+have_func("gdk_pixbuf_set_option")
+have_header("gdk-pixbuf/gdk-pixbuf-io.h")
+
+create_makefile_at_srcdir(PACKAGE_NAME, '.')
diff --git a/ext/rbbooh.c b/ext/rbbooh.c
new file mode 100644 (file)
index 0000000..12285ed
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *                         *  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
+ *
+ * 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.
+ *
+ */
+
+#include <math.h>
+
+#define GDK_PIXBUF_ENABLE_BACKEND
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gdk-pixbuf/gdk-pixdata.h>
+#include "rbgobject.h"
+
+#define _SELF(s) GDK_PIXBUF(RVAL2GOBJ(s)) 
+
+static VALUE
+whitebalance(self, level)
+    VALUE self, level; 
+{
+        double red_filter[256], blue_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++) {
+                red_filter[i]  = pow(((double)i)/255, 1/factor) * 255;
+                blue_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]   = red_filter[pixline[x*3]];
+                        pixline[x*3+2] = blue_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); 
+}
index fbea22f..f5b72fd 100644 (file)
@@ -207,24 +207,37 @@ module Booh
                                             Gdk::Pixbuf::ROTATE_NONE)
     end
 
-    def gen_thumbnails_element(orig, xmldir, allow_background, dests)
-        gen_thumbnails(orig, xmldir, allow_background, dests, xmldir.elements["[@filename='#{utf8(File.basename(orig))}']"], '')
+    def gen_thumbnails_element(orig, xmldirorelem, allow_background, dests)
+        if xmldirorelem.name == 'dir'
+            xmldirorelem = xmldirorelem.elements["[@filename='#{utf8(File.basename(orig))}']"]
+        end
+        gen_thumbnails(orig, allow_background, dests, xmldirorelem, '')
     end
 
-    def gen_thumbnails_subdir(orig, xmldir, allow_background, dests, type)
+    def gen_thumbnails_subdir(orig, xmldirorelem, allow_background, dests, type)
         #- type can be `subdirs' or `thumbnails' 
-        gen_thumbnails(orig, xmldir, allow_background, dests, xmldir, type + '-')
+        gen_thumbnails(orig, allow_background, dests, xmldirorelem, type + '-')
     end
 
-    def gen_thumbnails(orig, xmldir, allow_background, dests, felem, attributes_prefix)
+    def gen_thumbnails(orig, allow_background, dests, felem, attributes_prefix)
         if !dests.detect { |dest| !File.exists?(dest['filename']) } 
             return true
         end
 
         convert_options = ''
+        dest_dir = make_dest_filename(File.dirname(dests[0]['filename']))
 
         if entry2type(orig) == 'image'
             if felem
+                if whitebalance = felem.attributes["#{attributes_prefix}white-balance"]
+                    neworig = "#{dest_dir}/#{File.basename(orig)}-whitebalance#{whitebalance}.jpg"
+                    cmd = "booh-fix-whitebalance '#{orig}' '#{neworig}' #{whitebalance}"
+                    sys(cmd)
+                    if File.exists?(neworig)
+                        orig = neworig
+                        allow_background = false
+                    end
+                end
                 rotate = felem.attributes["#{attributes_prefix}rotate"]
                 if !rotate
                     felem.add_attribute("#{attributes_prefix}rotate", rotate = guess_rotate(orig).to_i)
@@ -240,8 +253,7 @@ module Booh
                     #- don't resize if image is already smaller than destination size
                     if size = get_image_size(orig)
                         dest['size'] =~ /(\d+)x(\d+)/
-                        if (rotate == "90" || rotate == "270") && (size[:x] < $2.to_i || size[:y] < $1.to_i) ||
-                                                                   size[:x] < $1.to_i || size[:y] < $2.to_i
+                        if (rotate == "90" || rotate == "270" || size[:x] < size[:y]) ? size[:y] < $1.to_i : size[:x] < $1.to_i
                             cmd = "#{$convert} #{convert_options} '#{orig}' '#{dest['filename']}'"
                         end
                     end
@@ -253,10 +265,12 @@ module Booh
                     end
                 end
             end
+            if neworig
+                system("rm -f '#{neworig}'")
+            end
             return true
 
         elsif entry2type(orig) == 'video'
-            dest_dir = make_dest_filename(File.dirname(dests[0]['filename']))
             if felem
                 #- frame-offset is an attribute that allows to specify which frame to use for the thumbnail
                 frame_offset = felem.attributes["#{attributes_prefix}frame-offset"]
@@ -271,8 +285,9 @@ module Booh
                     convert_options += ($config['convert-enhance'] || $convert_enhance) + " "
                 end
             end
+            orig = "#{dest_dir}/screenshot.jpg000000.jpg"
             for dest in dests
-                if !File.exists?("#{dest_dir}/screenshot.jpg000000.jpg")
+                if !File.exists?(orig)
                     transcode_options = ''
                     if felem
                         if felem.attributes["#{attributes_prefix}color-swap"]
@@ -309,12 +324,24 @@ module Booh
                             return false
                         end
                     end
-
+                    if felem && whitebalance = felem.attributes["#{attributes_prefix}white-balance"]
+                        if whitebalance.to_f != 0
+                            neworig = "#{dest_dir}/#{File.basename(orig)}-whitebalance#{whitebalance}.jpg"
+                            cmd = "booh-fix-whitebalance '#{orig}' '#{neworig}' #{whitebalance}"
+                            sys(cmd)
+                            if File.exists?(neworig)
+                                orig = neworig
+                            end
+                        end
+                    end
                 end
                 if !File.exists?(dest['filename'])
-                    sys("#{$convert} #{convert_options}-size #{dest['size']} -resize #{dest['size']} #{dest_dir}/screenshot.jpg000000.jpg '#{dest['filename']}'")
+                    sys("#{$convert} #{convert_options}-size #{dest['size']} -resize #{dest['size']} '#{orig}' '#{dest['filename']}'")
                 end
             end
+            if neworig
+                system("rm -f '#{neworig}'")
+            end
             return true
         end
     end
@@ -352,7 +379,6 @@ module Booh
     def max(a, b)
         a > b ? a : b
     end
-
 end
 
 class File