Commit c2fdd646 authored by Allison Barlow's avatar Allison Barlow

batch autoenhance feature (642) added and bug 994 fixed

parent fba1e5ad
......@@ -393,6 +393,7 @@ public class CollectionPage : CheckerboardPage {
private Gtk.HScale slider = null;
private Gtk.ToolButton new_event_button = null;
private Gtk.ToolButton rotate_button = null;
private Gtk.ToolButton enhance_button = null;
private Gtk.ToolButton slideshow_button = null;
private int scale = Thumbnail.DEFAULT_SCALE;
private Gee.ArrayList<File> drag_items = new Gee.ArrayList<File>();
......@@ -439,11 +440,22 @@ public class CollectionPage : CheckerboardPage {
toolbar.insert(rotate_button, -1);
// enhance tool
enhance_button = new Gtk.ToolButton.from_stock(Resources.ENHANCE);
enhance_button.set_label(Resources.ENHANCE_LABEL);
enhance_button.set_tooltip_text(Resources.ENHANCE_TOOLTIP);
enhance_button.sensitive = false;
enhance_button.is_important = true;
enhance_button.clicked += on_enhance;
toolbar.insert(enhance_button, -1);
// create new event
new_event_button = new Gtk.ToolButton.from_stock(Gtk.STOCK_NEW);
new_event_button.set_label(_("New Event"));
new_event_button.set_tooltip_text(_("Create new event from selected photos"));
new_event_button.sensitive = false;
new_event_button.is_important = true;
new_event_button.clicked += on_new_event;
toolbar.insert(new_event_button, -1);
......@@ -557,6 +569,12 @@ public class CollectionPage : CheckerboardPage {
mirror.tooltip = _("Make mirror images of the selected photos");
actions += mirror;
Gtk.ActionEntry enhance = { "Enhance", Resources.ENHANCE, TRANSLATABLE, "<Ctrl>E",
TRANSLATABLE, on_enhance };
enhance.label = Resources.ENHANCE_LABEL;
enhance.tooltip = Resources.ENHANCE_TOOLTIP;
actions += enhance;
Gtk.ActionEntry revert = { "Revert", Gtk.STOCK_REVERT_TO_SAVED, TRANSLATABLE, null,
TRANSLATABLE, on_revert };
revert.label = _("Re_vert to Original");
......@@ -668,6 +686,7 @@ public class CollectionPage : CheckerboardPage {
private void on_selection_changed(Gee.Iterable<DataView> items) {
rotate_button.sensitive = get_view().get_selected_count() > 0;
enhance_button.sensitive = get_view().get_selected_count() > 0;
new_event_button.sensitive = get_view().get_selected_count() > 0;
}
......@@ -689,6 +708,7 @@ public class CollectionPage : CheckerboardPage {
set_item_sensitive("/CollectionContextMenu/ContextRotateClockwise", selected);
set_item_sensitive("/CollectionContextMenu/ContextRotateCounterclockwise", selected);
set_item_sensitive("/CollectionContextMenu/ContextMirror", selected);
set_item_sensitive("/CollectionContextMenu/ContextEnhance", selected);
set_item_sensitive("/CollectionContextMenu/ContextRevert", selected && revert_possible);
return true;
......@@ -938,6 +958,7 @@ public class CollectionPage : CheckerboardPage {
set_item_sensitive("/CollectionMenuBar/PhotosMenu/RotateClockwise", selected);
set_item_sensitive("/CollectionMenuBar/PhotosMenu/RotateCounterclockwise", selected);
set_item_sensitive("/CollectionMenuBar/PhotosMenu/Mirror", selected);
set_item_sensitive("/CollectionMenuBar/PhotosMenu/Enhance", selected);
set_item_sensitive("/CollectionMenuBar/PhotosMenu/Revert", selected && revert_possible);
set_item_sensitive("/CollectionMenuBar/PhotosMenu/Slideshow", get_view().get_count() > 0);
}
......@@ -1085,6 +1106,40 @@ public class CollectionPage : CheckerboardPage {
AppWindow.get_instance().set_normal_cursor();
}
private void on_enhance() {
if (get_view().get_selected_count() == 0)
return;
AppWindow.get_instance().set_busy_cursor();
int count = 0;
int total = get_view().get_selected_count();
Cancellable cancellable = null;
ProgressDialog progress = null;
if (total >= MIN_OPS_FOR_PROGRESS_WINDOW) {
cancellable = new Cancellable();
progress = new ProgressDialog(AppWindow.get_instance(), _("Enhancing..."), cancellable);
}
foreach (DataView view in get_view().get_selected()) {
((TransformablePhoto) view.get_source()).enhance();
if (progress != null) {
progress.set_fraction(++count, total);
spin_event_loop();
if (cancellable.is_cancelled())
break;
}
}
if (progress != null)
progress.close();
AppWindow.get_instance().set_normal_cursor();
}
private void on_slideshow() {
if (get_view().get_count() == 0)
return;
......
......@@ -97,6 +97,26 @@ public class DataCollection {
}
}
protected class ComparatorWrapper : Comparator<DataObject> {
private Comparator<DataObject> comparator;
public ComparatorWrapper(Comparator<DataObject> comparator) {
this.comparator = comparator;
}
public override int64 compare(DataObject a, DataObject b) {
int64 result = comparator.compare(a, b);
if (result == 0)
result = a.internal_get_ordinal() - b.internal_get_ordinal();
if (a != b) {
assert(result != 0);
}
return result;
}
}
private static OrderAddedComparator order_added_comparator = null;
private SortedList<DataObject> list = new SortedList<DataObject>();
......@@ -169,7 +189,7 @@ public class DataCollection {
}
public virtual void set_comparator(Comparator<DataObject> comparator) {
list.resort(comparator);
list.resort(new ComparatorWrapper(comparator));
ordering_changed();
}
......@@ -180,7 +200,7 @@ public class DataCollection {
}
public virtual Gee.Iterable<DataObject> get_all() {
return list;
return list.copy();
}
public virtual int get_count() {
......@@ -752,8 +772,8 @@ public class ViewCollection : DataCollection {
}
public override void set_comparator(Comparator<DataView> comparator) {
selected.resort(comparator);
visible.resort(comparator);
selected.resort(new ComparatorWrapper(comparator));
visible.resort(new ComparatorWrapper(comparator));
base.set_comparator(comparator);
}
......@@ -766,7 +786,7 @@ public class ViewCollection : DataCollection {
}
public override Gee.Iterable<DataObject> get_all() {
return visible;
return visible.copy();
}
public override int get_count() {
......@@ -940,7 +960,7 @@ public class ViewCollection : DataCollection {
}
public Gee.Iterable<DataView> get_selected() {
return selected;
return selected.copy();
}
public DataView? get_selected_at(int index) {
......
......@@ -1590,6 +1590,60 @@ public abstract class TransformablePhoto: PhotoSource {
return raw_rect;
}
public PixelTransformation[]? get_enhance_transformations() {
Gdk.Pixbuf pixbuf = null;
#if MEASURE_ENHANCE
Timer fetch_timer = new Timer();
#endif
try {
pixbuf = get_pixbuf_with_exceptions(Scaling.for_best_fit(360),
TransformablePhoto.Exception.ALL);
#if MEASURE_ENHANCE
fetch_timer.stop();
#endif
} catch (Error e) {
warning("Photo: get_enhance_transformations: couldn't obtain pixbuf to build " +
"transform histogram");
return null;
}
#if MEASURE_ENHANCE
Timer analyze_timer = new Timer();
#endif
PixelTransformation[] transformations = AutoEnhance.create_auto_enhance_adjustments(pixbuf);
#if MEASURE_ENHANCE
analyze_timer.stop();
debug("Auto-Enhance fetch time: %f sec; analyze time: %f sec", fetch_timer.elapsed(),
analyze_timer.elapsed());
#endif
return transformations;
}
public bool enhance() {
PixelTransformation[] transformations = get_enhance_transformations();
if (transformations == null)
return false;
#if MEASURE_ENHANCE
Timer apply_timer = new Timer();
#endif
set_adjustments(transformations);
#if MEASURE_ENHANCE
apply_timer.stop();
debug("Auto-Enhance apply time: %f sec", apply_timer.elapsed());
#endif
return true;
}
}
public class LibraryPhotoSourceCollection : DatabaseSourceCollection {
......
......@@ -98,8 +98,8 @@ public abstract class EditingHostPage : SinglePhotoPage {
// ehance tool
enhance_button = new Gtk.ToolButton.from_stock(Resources.ENHANCE);
enhance_button.set_label(_("Enhance"));
enhance_button.set_tooltip_text(_("Automatically improve the photo's appearance"));
enhance_button.set_label(Resources.ENHANCE_LABEL);
enhance_button.set_tooltip_text(Resources.ENHANCE_TOOLTIP);
enhance_button.clicked += on_enhance;
enhance_button.is_important = true;
toolbar.insert(enhance_button, -1);
......@@ -994,57 +994,32 @@ public abstract class EditingHostPage : SinglePhotoPage {
#if MEASURE_ENHANCE
Timer overall_timer = new Timer();
Timer fetch_timer = new Timer();
#endif
Gdk.Pixbuf pixbuf = null;
try {
pixbuf = get_photo().get_pixbuf_with_exceptions(Scaling.for_best_fit(360),
TransformablePhoto.Exception.ALL);
#if MEASURE_ENHANCE
fetch_timer.stop();
#endif
} catch (Error e) {
warning("PhotoPage: on_enhance: couldn't obtain pixbuf to build " +
"transform histogram");
set_photo_missing(true);
AppWindow.get_instance().set_normal_cursor();
return;
}
#if MEASURE_ENHANCE
Timer analyze_timer = new Timer();
#endif
PixelTransformation[] transformations = AutoEnhance.create_auto_enhance_adjustments(pixbuf);
#if MEASURE_ENHANCE
analyze_timer.stop();
#endif
#if MEASURE_ENHANCE
Timer apply_timer = new Timer();
#endif
/* if the current tool is the adjust tool, then don't commit to the database --
just set the slider values in the adjust dialog and force it to repaint
the canvas */
if (current_tool is AdjustTool) {
((AdjustTool) current_tool).set_adjustments(transformations);
PixelTransformation[] transformations = get_photo().get_enhance_transformations();
if (transformations != null) {
((AdjustTool) current_tool).set_adjustments(transformations);
} else {
set_photo_missing(true);
}
} else {
/* if the current tool isn't the adjust tool then commit the changes
to the database */
get_photo().set_adjustments(transformations);
pixbuf_dirty = true;
update_pixbuf();
#if MEASURE_ENHANCE
apply_timer.stop();
#endif
/* if the current tool isn't the adjust tool then commit the changes
to the database */
if (get_photo().enhance()) {
pixbuf_dirty = true;
update_pixbuf();
} else {
set_photo_missing(true);
}
}
#if MEASURE_ENHANCE
overall_timer.stop();
#endif
#if MEASURE_ENHANCE
debug("Auto-Enhance Performance Statistics = overall time: %f sec; fetch time: %f sec; analyze time: %f sec; apply time: %f sec", overall_timer.elapsed(), fetch_timer.elapsed(), analyze_timer.elapsed(), apply_timer.elapsed());
debug("Auto-Enhance overall time: %f sec", overall_timer.elapsed());
#endif
AppWindow.get_instance().set_normal_cursor();
......@@ -1207,8 +1182,8 @@ public class LibraryPhotoPage : EditingHostPage {
Gtk.ActionEntry enhance = { "Enhance", Resources.ENHANCE, TRANSLATABLE, "<Ctrl>E",
TRANSLATABLE, on_enhance };
enhance.label = _("_Enhance");
enhance.tooltip = _("Automatically improve the photo's appearance");
enhance.label = Resources.ENHANCE_LABEL;
enhance.tooltip = Resources.ENHANCE_TOOLTIP;
actions += enhance;
Gtk.ActionEntry revert = { "Revert", Gtk.STOCK_REVERT_TO_SAVED, TRANSLATABLE,
......
......@@ -75,6 +75,9 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,
public const string ROTATE_CW_TOOLTIP = _("Rotate the photo(s) right");
public const string ROTATE_CCW_TOOLTIP = _("Rotate the photo(s) left");
public const string ENHANCE_LABEL = _("Enhance");
public const string ENHANCE_TOOLTIP = _("Automatically improve the photo's appearance");
private Gtk.IconFactory factory = null;
public void init () {
......
......@@ -141,5 +141,13 @@ public class SortedList<G> : Object, Gee.Iterable<G> {
}
}
public SortedList<G> copy() {
SortedList<G> copy = new SortedList<G>(cmp);
copy.list.add_all(list);
return copy;
}
}
......@@ -41,6 +41,7 @@
<menuitem name="Mirror" action="Mirror" />
<separator />
<menuitem name="Revert" action="Revert" />
<menuitem name="Enhance" action="Enhance" />
<separator />
<menuitem name="Slideshow" action="Slideshow" />
</menu>
......@@ -63,6 +64,7 @@
<menuitem name="ContextRotateCounterclockwise" action="RotateCounterclockwise" />
<menuitem name="ContextMirror" action="Mirror" />
<separator />
<menuitem name="ContextEnhance" action="Enhance" />
<menuitem name="ContextRevert" action="Revert" />
<separator />
<menuitem name="ContextNewEvent" action="NewEvent" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment