Logo Search packages:      
Sourcecode: f-spot version File versions  Download package

ColorDialog.cs

using System;
using Gtk;
using Cms;
using Mono.Unix;
using System.Threading;
using FSpot.Widgets;
using FSpot.UI.Dialog;

namespace FSpot {
      public class ColorDialog : GladeDialog {
            protected static ColorDialog instance = null;
            
            Gdk.Pixbuf ScaledPixbuf;
            Gdk.Pixbuf AdjustedPixbuf;
            
#if USE_THREAD          
            Delay expose_timeout;
#endif
            [Glade.Widget] private Gtk.HScale exposure_scale;
            [Glade.Widget] private Gtk.HScale temp_scale;
            [Glade.Widget] private Gtk.HScale temptint_scale;
            [Glade.Widget] private Gtk.HScale brightness_scale;
            [Glade.Widget] private Gtk.HScale contrast_scale;
            [Glade.Widget] private Gtk.HScale hue_scale;
            [Glade.Widget] private Gtk.HScale sat_scale;
            
            [Glade.Widget] private Gtk.SpinButton exposure_spinbutton;
            [Glade.Widget] private Gtk.SpinButton temp_spinbutton;
            [Glade.Widget] private Gtk.SpinButton temptint_spinbutton;
            [Glade.Widget] private Gtk.SpinButton brightness_spinbutton;
            [Glade.Widget] private Gtk.SpinButton contrast_spinbutton;
            [Glade.Widget] private Gtk.SpinButton hue_spinbutton;
            [Glade.Widget] private Gtk.SpinButton sat_spinbutton;
            
            [Glade.Widget] private Gtk.ScrolledWindow view_scrolled;
            [Glade.Widget] private Gtk.Image histogram_image;
            
            [Glade.Widget] private Gtk.CheckButton white_check;
            [Glade.Widget] private Gtk.CheckButton exposure_check;
            
            [Glade.Widget] Gtk.Button ok_button;
            [Glade.Widget] Gtk.VBox   control_vbox;
            
            private FSpot.PhotoImageView view;

            Cms.Transform next_transform;
            Cms.Profile image_profile = Cms.Profile.CreateStandardRgb ();
            Cms.Profile adjustment_profile;

#if USE_THREAD
            Thread thread;
#endif
            
            FSpot.Histogram hist;
            

            private void Adjust ()
            {

                  if (brightness_scale == null)
                        return;
                  
                  if (AdjustedPixbuf == null)
                        return;

                  Cms.Profile display_profile = Cms.Profile.GetScreenProfile (view.Screen);
                  Cms.Profile [] list;
                  
                  if (display_profile == null)
                        display_profile = Cms.Profile.CreateStandardRgb ();
                  
                  if (!Changed || AdjustedPixbuf.HasAlpha) {
                        if (AdjustedPixbuf.HasAlpha)
                              System.Console.WriteLine ("Cannot currently adjust images with an alpha channel");

                        list = new Cms.Profile [] { image_profile, display_profile };

                        next_transform = new Cms.Transform (list, 
                                                    PixbufUtils.PixbufCmsFormat (AdjustedPixbuf),
                                                    PixbufUtils.PixbufCmsFormat (AdjustedPixbuf),
                                                    Cms.Intent.Perceptual, 0x0000);
                  } else {
                              
                        using (adjustment_profile = AdjustmentProfile ()) {
                              list = new Cms.Profile [] { image_profile, adjustment_profile, display_profile };
                              
                              next_transform = new Cms.Transform (list, 
                                                          PixbufUtils.PixbufCmsFormat (AdjustedPixbuf),
                                                          PixbufUtils.PixbufCmsFormat (AdjustedPixbuf),
                                                          Cms.Intent.Perceptual, 0x0000);
                        }
                  }
                  
                  lock (AdjustedPixbuf) {
                        PixbufUtils.ColorAdjust (ScaledPixbuf,
                                           AdjustedPixbuf,
                                           next_transform);
#if USE_THREAD
                        expose_timeout.Start ();
#else
                        this.QueueDraw ();
#endif
                  }
            }

            public static ColorDialog Instance {
                  get { return instance; }
            }
            
            public bool UseWhiteSettings {
                  get {
                        if (white_check != null)
                              return white_check.Active;
                        else
                              return true;
                  }
            }

            public bool UseExposureSettings {
                  get {
                        if (exposure_check != null)
                              return exposure_check.Active;
                        else 
                              return true;
                  }
            }

            public bool QueueDraw ()
            {
                  lock (AdjustedPixbuf) {
                        if (view.Transform != null)
                              view.Transform.Dispose ();
                        
                        view.Transform = next_transform;
                        view.QueueDraw ();
                        
                        hist.FillValues (AdjustedPixbuf);
                        histogram_image.QueueDraw ();
                  }
                  return false;
            }
            
            public void HandleDestroyed (object sender, EventArgs arg)
            {
                  
                  Cancel ();
#if USE_THREAD
                  expose_timeout.Stop ();
#endif
            }
            
            public void RangeChanged (object sender, EventArgs args)
            {
                  if (!view.Item.IsValid)
                        return;

#if USE_THREAD
                  if (thread != null && thread.IsAlive)
                        thread.Abort ();
                  
                  
                  thread = new Thread (new ThreadStart (Adjust));
                  thread.Start ();
#else
                  Adjust ();
#endif
            }
            
            public void Save ()
            {
                  if (!Changed) {
                        this.Dialog.Destroy ();
                        return;
                  }

                  if (!view.Item.IsValid)
                        return;

                  Console.WriteLine ("Saving....");

                  Photo photo = (Photo)view.Item.Current;
                  try {
                        bool create_version = photo.DefaultVersion.IsProtected;
                        
                        Gdk.Pixbuf orig = view.CompletePixbuf ();
                        Gdk.Pixbuf final = new Gdk.Pixbuf (Gdk.Colorspace.Rgb,
                                                   false, 8,
                                                   orig.Width, 
                                                   orig.Height);
                        
                        Cms.Profile abs = AdjustmentProfile ();
                        
                        // FIXME this shouldn't use the screen as the destination profile.
                        Cms.Profile destination = Cms.Profile.GetScreenProfile (view.Screen);
                        if (destination == null)
                              destination = Cms.Profile.CreateStandardRgb ();
                        
                        Cms.Profile [] list = new Cms.Profile [] { image_profile, abs, destination };
                        Cms.Transform transform = new Cms.Transform (list,
                                                           PixbufUtils.PixbufCmsFormat (orig),
                                                           PixbufUtils.PixbufCmsFormat (final),
                                                           Cms.Intent.Perceptual, 0x0000);
                        
                        PixbufUtils.ColorAdjust (orig,
                                           final,
                                           transform);
                        
                        photo.SaveVersion (final, create_version);
                        ((PhotoQuery)view.Query).Commit (view.Item.Index);
                        final.Dispose ();
                  } catch (System.Exception e) {
                        string msg = Catalog.GetString ("Error saving adjusted photo");
                        string desc = String.Format (Catalog.GetString ("Received exception \"{0}\". Unable to save photo {1}"),
                                               e.Message, photo.Name);
                        
                        HigMessageDialog md = new HigMessageDialog ((Gtk.Window)Dialog.Toplevel,
                                                          DialogFlags.DestroyWithParent, 
                                                          Gtk.MessageType.Error, ButtonsType.Ok, 
                                                          msg,
                                                          desc);
                        md.Run ();
                        md.Destroy ();
                  }

                  this.Dialog.Sensitive = false;
                  this.Dialog.Destroy ();
            }
            
            public void Cancel ()
            {
                  this.Dialog.Destroy ();
                  view.Transform = null;
                  view.PhotoChanged -= HandlePhotoChanged;
                  view.QueueDraw ();
                  System.Console.WriteLine ("clearing window");
                  instance = null;
            }
            
            private void HandleOkClicked (object sender, EventArgs args)
            {
                  Save ();
                  view.Transform = null;
                  view.QueueDraw ();

                  view.PhotoChanged -= HandlePhotoChanged;
            }

            private void HandleProfileSelected (object sender, EventArgs args)
            {
                   
                  
            }

            private void HandlePhotoChanged (PhotoImageView view)
            {
                  try {
                        if (!view.Item.IsValid)
                              throw new Exception ("Invalid Image");
                        
                        using (FSpot.ImageFile img = FSpot.ImageFile.Create (((Photo)view.Item.Current).DefaultVersionUri)) {
                              try {
                                    image_profile = img.GetProfile ();
                              } catch (System.Exception e) {
                                    image_profile = null;
                                    System.Console.WriteLine (e);
                              }

                              // FIXME fall back to rgb for now
                              if (image_profile == null)
                                    image_profile = Cms.Profile.CreateStandardRgb ();
                        
                              AdjustedPixbuf = img.Load (256, 256);
                              ScaledPixbuf = AdjustedPixbuf.Copy ();                
                        }

                        if (AdjustedPixbuf.HasAlpha)
                              throw new Exception ("Unsupported Alpha Channel");

                        control_vbox.Sensitive = true;
                        ok_button.Sensitive = true;

                        RangeChanged (null, null);
                  } catch (System.Exception) {
                        control_vbox.Sensitive = false;
                        ok_button.Sensitive = false;
                        AdjustedPixbuf = null;
                        ScaledPixbuf = null;
                        image_profile = null;
                  }     
            }

            private const double e = 0.0;
            private const double b = 0.0;
            private const double c = 0.0;
            private const double h = 0.0;
            private const double s = 0.0;
            private const double t = 5000;
            private const double tt = 0.0;

            private Cms.Profile AdjustmentProfile ()
            {
                  Cms.Profile profile;
                  Cms.ColorCIEXYZ src_wp;
                  Cms.ColorCIEXYZ dest_wp;

                  double exposure = e;
                  double brightness = b;
                  double contrast = c;
                  double hue = h;
                  double saturation = s;
                  
                  if (UseWhiteSettings) {
                        //src_wp = image_profile.MediaWhitePoint;
                        src_wp = Cms.ColorCIExyY.WhitePointFromTemperature ((int)t).ToXYZ ();
                        dest_wp = Cms.ColorCIExyY.WhitePointFromTemperature ((int)temp_scale.Value).ToXYZ ();
                        Cms.ColorCIELab dest_lab = dest_wp.ToLab (src_wp);
                        dest_lab.a += temptint_scale.Value;
                        //System.Console.WriteLine ("after {0}", dest_lab);
                        dest_wp = dest_lab.ToXYZ (src_wp);
                  } else {
                        src_wp = Cms.ColorCIExyY.WhitePointFromTemperature ((int)t).ToXYZ ();
                        dest_wp = src_wp;
                  }

                  if (UseExposureSettings) {
                        exposure = exposure_scale.Value;
                        brightness = brightness_scale.Value;
                        contrast = contrast_scale.Value;
                        hue = hue_scale.Value;
                        saturation = sat_scale.Value;
                  }

                  profile = Cms.Profile.CreateAbstract (20, 
                                                Math.Pow (Math.Sqrt (2.0), exposure),
                                                brightness,
                                                contrast,
                                                hue,
                                                saturation,
                                                null,
                                                src_wp.ToxyY (),
                                                dest_wp.ToxyY ());

                  return profile;
            }

            private bool Changed {
                  get {
                        bool changed = false;
                        changed |= (exposure_scale.Value != e);
                          changed |= (brightness_scale.Value != b);
                          changed |= (contrast_scale.Value != c);
                          changed |= (hue_scale.Value != h);
                          changed |= (sat_scale.Value != s);
                        changed |= (temp_scale.Value != t);
                        changed |= (temptint_scale.Value != tt);

                        return changed;
                  }
            }
            
            private void ResetWhiteBalance ()
            {
                  temp_scale.Adjustment.Value = t;
                  temptint_scale.Adjustment.Value = tt;
            }

            private void ResetCorrections ()
            {
                  exposure_scale.Adjustment.Value = e;
                  brightness_scale.Adjustment.Value = b;
                  contrast_scale.Adjustment.Value = c;
                  hue_scale.Adjustment.Value = h;                 
                  sat_scale.Adjustment.Value = s;
            }

            private void HandleResetClicked (object sender, EventArgs args)
            {
                  ResetCorrections ();
                  ResetWhiteBalance ();
                  //brightness_scale.Adjustment.ChangeValue ();
            }
            
            private void HandleWPResetClicked (object sender, EventArgs args)
            {
                  ResetWhiteBalance ();
                  //brightness_scale.Adjustment.ChangeValue ();
            }

            private void HandleExposureResetClicked (object sender, EventArgs args)
            {
                  ResetCorrections ();
                  //brightness_scale.Adjustment.ChangeValue ();
            }

            private void HandleCancelClicked (object sender, EventArgs args)
            {
                  Cancel ();
            }
            
            public static void Close ()
            {
                  if (instance != null) {
                        instance.Cancel ();
                  }
            }
            
            public static void CreateForView (FSpot.PhotoImageView view)
            {
                  Close ();
                  
                  instance = new ColorDialog (view);
            }
            
            // FIXME is this the riht place for this, shouldn't mainwindow
            // treat fullscreen as a mode and handle this part itself?
            public static void SwitchViews (FSpot.PhotoImageView view) {
                  if (instance != null) {
                        if (instance.view.Item.Current == view.Item.Current) {
                              instance.view.Transform = null;
                              instance.SetView (view);
                              instance.Adjust ();
                        } else {
                              CreateForView (view);
                        }
                  }
            }
            
            protected ColorDialog (FSpot.PhotoQuery query, int item)
            {
                  view = new FSpot.PhotoImageView (query);
                  view_scrolled.Add (view);
                  view.Show ();
                  view.Item.Index = item;
                  
                  this.CreateDialog ("external_color_dialog");
                  AttachInterface ();
            }
            
            protected ColorDialog (FSpot.PhotoImageView view)       
            {
                  this.view = view;
                  this.CreateDialog ("inline_color_dialog");

                  AttachInterface ();
            }
            
            private void AttachInterface ()
            {
                  view.PhotoChanged += HandlePhotoChanged;
                  hist = new FSpot.Histogram ();
#if USE_THREAD
                  expose_timeout = new FSpot.Delay (new GLib.IdleHandler (this.QueueDraw));
#endif
                  this.Dialog.Destroyed += HandleDestroyed;

#if true
                  Gdk.Color c = this.Dialog.Style.Backgrounds [(int)Gtk.StateType.Active];
                  hist.Color [0] = (byte) (c.Red / 0xff);
                  hist.Color [1] = (byte) (c.Green / 0xff);
                  hist.Color [2] = (byte) (c.Blue / 0xff);
                  hist.Color [3] = 0xff;
#endif

                  histogram_image.Pixbuf = hist.GeneratePixbuf ();

                  exposure_spinbutton.Adjustment = exposure_scale.Adjustment;
                  temp_spinbutton.Adjustment = temp_scale.Adjustment;
                  temptint_spinbutton.Adjustment = temptint_scale.Adjustment;
                  brightness_spinbutton.Adjustment = brightness_scale.Adjustment;
                  contrast_spinbutton.Adjustment = contrast_scale.Adjustment;
                  hue_spinbutton.Adjustment = hue_scale.Adjustment;
                  sat_spinbutton.Adjustment = sat_scale.Adjustment;
                  
                  temp_spinbutton.Adjustment.ChangeValue ();
                  temptint_spinbutton.Adjustment.ChangeValue ();
                  brightness_spinbutton.Adjustment.ChangeValue ();
                  contrast_spinbutton.Adjustment.ChangeValue ();
                  hue_spinbutton.Adjustment.ChangeValue ();
                  sat_spinbutton.Adjustment.ChangeValue ();
                  hue_spinbutton.Adjustment.ChangeValue ();
                  sat_spinbutton.Adjustment.ChangeValue ();
                  
                  exposure_scale.ValueChanged += RangeChanged;
                  temp_scale.ValueChanged += RangeChanged;
                  temptint_scale.ValueChanged += RangeChanged;
                  brightness_scale.ValueChanged += RangeChanged;
                  contrast_scale.ValueChanged += RangeChanged;
                  hue_scale.ValueChanged += RangeChanged;
                  sat_scale.ValueChanged += RangeChanged;

                  HandlePhotoChanged (view);
            }

            private void SetView (FSpot.PhotoImageView view)
            {
                  this.view.PhotoChanged -= HandlePhotoChanged;
                  this.view = view;
                  this.view.PhotoChanged += HandlePhotoChanged;

                  
                  if (view.Toplevel is FullScreenView && Dialog.IsRealized)
                        CompositeUtils.SetWinOpacity (Dialog, 0.5);
                  else 
                        CompositeUtils.SetWinOpacity (Dialog, 1.0);

            }
      }
}

Generated by  Doxygen 1.6.0   Back to index