Browse Source

Uncommitted changed from the last few months

Billy Barrow 7 years ago
parent
commit
a308d04de9
3 changed files with 86 additions and 58 deletions
  1. 6 4
      PF2/Layer.py
  2. 17 0
      PF2/Tools/Contrast.py
  3. 63 54
      PF2/__init__.py

+ 6 - 4
PF2/Layer.py

@@ -1,6 +1,6 @@
 from gi.repository import Gtk, GLib
 import PF2.VectorMask as VectorMask
-import cv2
+import cv2, numpy
 
 class Layer:
     def __init__(self, base, name, on_change):
@@ -124,6 +124,7 @@ class Layer:
 
                 # Call the tool's image processing function
                 layer = tool.on_update(layer)
+                assert type(layer) == numpy.ndarray
                 count += 1
 
 
@@ -134,9 +135,10 @@ class Layer:
             # Here we would blend with the mask
             else:
                 mask_map = self.mask.get_mask_map()
-                if(mask_map != None):
+                if(type(mask_map) == numpy.ndarray):
                     # Only process if there is actually an existing mask
                     height, width = layer.shape[:2]
+
                     mask_map = cv2.resize(mask_map, (width, height), interpolation=cv2.INTER_AREA)
                     mask_map = mask_map * self.opacity
 
@@ -151,7 +153,7 @@ class Layer:
     def get_layer_mask_preview(self, image):
         mask =  self.mask.get_mask_map()
 
-        if(mask != None):
+        if(type(mask) == numpy.ndarray):
             w, h = image.shape[:2]
 
             # Bits per pixel
@@ -199,4 +201,4 @@ class Layer:
 
     def set_blending_mode(self, mode):
         self.blend_mode = mode
-        self.on_tool_change(None, None)
+        self.on_tool_change(None, None)

+ 17 - 0
PF2/Tools/Contrast.py

@@ -12,6 +12,9 @@ class Contrast(Tool.Tool):
             Tool.Property("header", "Brightness and Contrast", "Header", None, has_toggle=False, has_button=False),
             Tool.Property("overall_brightness", "Brightness", "Slider", 0, max=50, min=-50),
             Tool.Property("overall_contrast", "Contrast", "Slider", 0, max=50, min=-50),
+            Tool.Property("hist_stretch", "Histogram Strecthing", "Header", None, has_toggle=False, has_button=False),
+            Tool.Property("left_stretch", "Left Stretch", "Slider", 0, max=50, min=-50),
+            Tool.Property("right_stretch", "Right Stretch", "Slider", 0, max=50, min=-50),
             Tool.Property("tonal_header", "Tonal Brightness and Contrast", "Header", None, has_toggle=False, has_button=False),
             Tool.Property("highlight_brightness", "Highlight Brightness", "Slider", 0, max=50, min=-50),
             Tool.Property("highlight_contrast", "Highlight Contrast", "Slider", 0, max=50, min=-50),
@@ -32,6 +35,9 @@ class Contrast(Tool.Tool):
             ob = self.props["overall_brightness"].get_value()
             oc = -self.props["overall_contrast"].get_value()
 
+            ls = -self.props["left_stretch"].get_value()
+            rs = -self.props["right_stretch"].get_value()
+
             hb = self.props["highlight_brightness"].get_value()
             hc = self.props["highlight_contrast"].get_value()
             mb = self.props["midtone_brightness"].get_value()
@@ -62,6 +68,17 @@ class Contrast(Tool.Tool):
 
             out = im.astype(numpy.float32)
 
+
+            # Histogram Stretch
+            if(rs != 0 or ls != 0):
+                maxpxv = np + (rs/100.0)*np
+                minpxv = 0 - (ls/100.0)*np
+                
+                out = (out - minpxv) * (np/float(maxpxv))
+                
+            
+
+
             # Highlights
 
             isHr = self._is_highlight(out, (3.0 / hbl))

+ 63 - 54
PF2/__init__.py

@@ -8,6 +8,8 @@ import cv2
 import numpy
 import getpass
 import os
+import traceback
+import uuid
 
 from PF2 import Histogram, Layer
 from PF2.Tools import BlackWhite
@@ -151,6 +153,7 @@ class PF2(Activity.Activity):
         self.is_scaling = False
         self.current_processing_layer_name = "base"
         self.current_processing_layer_index = 0
+        self.update_image_task_id = ""
 
         # Setup Open Dialog
         self.ui["open_window"].set_transient_for(self.root)
@@ -211,9 +214,6 @@ class PF2(Activity.Activity):
         else:
             self.image_path = path
 
-        w = (self.ui["scroll_window"].get_allocated_width() - 12) * self.ui["zoom"].get_value()
-        h = (self.ui["scroll_window"].get_allocated_height() - 12) * self.ui["zoom"].get_value()
-
         self.show_message("Loading Photo…", "Please wait while PhotoFiddle loads your photo", True)
         self.root.get_titlebar().set_subtitle("%s…" % (self.image_path))
 
@@ -226,6 +226,9 @@ class PF2(Activity.Activity):
 
         self.select_layer(self.base_layer)
 
+        w = (self.ui["scroll_window"].get_allocated_width() - 12) * self.ui["zoom"].get_value()
+        h = (self.ui["scroll_window"].get_allocated_height() - 12) * self.ui["zoom"].get_value()
+        
         thread = threading.Thread(target=self.open_image,
                                   args=(w, h))
         thread.start()
@@ -290,7 +293,7 @@ class PF2(Activity.Activity):
         if(self.is_exporting):
             return False
         else:
-            fname = "/tmp/phf2-preview-%s.png" % getpass.getuser()
+            fname = "/dev/shm/phf2-preview-%s.png" % getpass.getuser()
             if (os.path.exists(fname)):
                 os.unlink(fname)
 
@@ -414,13 +417,17 @@ class PF2(Activity.Activity):
 
             # Read the 8Bit Preview
             self.source_image = cv2.imread(self.image_path).astype(numpy.uint8)
-
+            
             # Load the image
             self.resize_preview(w, h)
         except:
             pass
-        while(self.image == None):
+        while(type(self.image) != numpy.ndarray):
             time.sleep(1)
+            
+        self.pwidth = 0
+        self.pheight = 0
+           
         GLib.idle_add(self.image_opened)
         time.sleep(1)
         self.has_loaded = True
@@ -428,7 +435,8 @@ class PF2(Activity.Activity):
 
 
     def resize_preview(self, w, h):
-        if(self.source_image != None):
+        print(w, h)
+        if(type(self.source_image) == numpy.ndarray):
             # Inhibit undo stack to prevent
             # Adding an action on resize
             self.undoing = True
@@ -462,7 +470,7 @@ class PF2(Activity.Activity):
             #     self.pimage = self.pimage = self.create_pixbuf(image)
             #     GLib.idle_add(self.show_current)
 
-            if(self.pimage != None and not self.is_scaling):
+            if(type(self.pimage) == numpy.ndarray and not self.is_scaling):
                 self.is_scaling = True
                 # If we have an edited version, show that
                 image = self.pimage.scale_simple(int(nw), int(nh), GdkPixbuf.InterpType.NEAREST)
@@ -472,7 +480,7 @@ class PF2(Activity.Activity):
 
             self.poriginal = GdkPixbuf.Pixbuf.new_from_file_at_scale(self.image_path,
                                                                 int(nw), int(nh), True)
-            if(self.pimage == None):
+            if(type(self.pimage) != numpy.ndarray):
                 # Otherwise show the original
                 GLib.idle_add(self.show_original)
 
@@ -502,31 +510,36 @@ class PF2(Activity.Activity):
         GLib.idle_add(self.start_work)
         image = numpy.copy(self.original_image)
         rst = time.time()
-        self.image = self.run_stack(image, changed_layer=changed_layer)
-        if(self.image == None):
-            GLib.idle_add(self.stop_work)
-            self.is_working = False
-            self.change_occurred = False
-            GLib.idle_add(self.update_undo_state)
-            print("self.image == None")
-            GLib.idle_add(self.show_message, "Image Render Failed…",
-                          "PhotoFiddle encountered an internal error and was unable to render the image… Please try again.")
-            raise Exception()
-
-        self.process_mask()
-        self.image_is_dirty = False
-        if(self.additional_change_occurred):
-            self.update_image()
-        else:
-            self.save_image_data()
-            threading.Thread(target=self.draw_hist, args=(self.image,)).start()
-            self.process_peaks()
-            self.update_preview()
-            GLib.idle_add(self.stop_work)
-            self.is_working = False
-            GLib.idle_add(self.update_undo_state)
-            self.change_occurred = False
-            self.undoing = False
+        task_id = uuid.uuid4()
+        self.update_image_task_id = task_id
+        image = self.run_stack(image, changed_layer=changed_layer)
+        if(task_id == self.update_image_task_id):
+            self.image = image
+            if(type(self.image) != numpy.ndarray):
+                GLib.idle_add(self.stop_work)
+                self.is_working = False
+                self.change_occurred = False
+                GLib.idle_add(self.update_undo_state)
+                print("self.image == None")
+                GLib.idle_add(self.show_message, "Image Render Failed…",
+                              "PhotoFiddle encountered an internal error and was unable to render the image… Please try again.")
+                raise Exception()
+
+            self.process_mask()
+            self.image_is_dirty = False
+            if(self.additional_change_occurred):
+                self.update_image()
+            else:
+                self.save_image_data()
+                threading.Thread(target=self.draw_hist, args=(self.image,)).start()
+
+                self.process_peaks()
+                self.update_preview()
+                GLib.idle_add(self.stop_work)
+                self.is_working = False
+                GLib.idle_add(self.update_undo_state)
+                self.change_occurred = False
+                self.undoing = False
 
 
 
@@ -541,7 +554,7 @@ class PF2(Activity.Activity):
                 image = None
 
                 carry = True
-                if(self.image != None) and (baseImage.shape == self.image.shape) and (changed_layer != None) and (changed_layer in self.layers):
+                if(type(self.image) == numpy.ndarray) and (baseImage.shape == self.image.shape) and (changed_layer != None) and (changed_layer in self.layers):
                     changed_layer_index = self.layers.index(changed_layer)
                     if(changed_layer_index > 0):
                         carry = False
@@ -571,7 +584,9 @@ class PF2(Activity.Activity):
                 self.running_stack = False
                 return image
 
-            except(Exception):
+            except Exception as e:
+                print(e)
+                traceback.print_exc()
                 GLib.idle_add(self.show_message, "Image Render Failed…",
                               "PhotoFiddle encountered an internal error and was unable to render the image.")
 
@@ -583,30 +598,24 @@ class PF2(Activity.Activity):
             return self.run_stack(image, callback)
 
     def update_preview(self):
-        if(not self.is_scaling):
-            image = self.create_pixbuf(self.image)
-            self.pimage = image
-
-            GLib.idle_add(self.show_current)
+        image = self.create_pixbuf(self.image)
+        self.pimage = image
+        GLib.idle_add(self.show_current)
 
 
 
     def create_pixbuf(self, im):
-        image = cv2.cvtColor(im.copy(), cv2.COLOR_BGR2RGB).astype(numpy.uint8)
-
-        pb = GdkPixbuf.Pixbuf.new_from_data(image.tostring(),
-                                            GdkPixbuf.Colorspace.RGB,
-                                            False,
-                                            8,
-                                            self.image.shape[1],
-                                            self.image.shape[0],
-                                            self.image.shape[2] * self.image.shape[1])
+        pb = None
+        write_id = uuid.uuid4()
+        cv2.imwrite("/dev/shm/phf2-preview-%s-update.png" % write_id, im)
+        pb = GdkPixbuf.Pixbuf.new_from_file("/dev/shm/phf2-preview-%s-update.png" % write_id)
+        os.unlink("/dev/shm/phf2-preview-%s-update.png" % write_id)
 
         return pb
 
 
     def draw_hist(self, image):
-        path = "/tmp/phf2-hist-%s.png" % getpass.getuser()
+        path = "/dev/shm/phf2-hist-%s.png" % getpass.getuser()
         Histogram.Histogram.draw_hist(image, path)
         GLib.idle_add(self.update_hist_ui, path)
 
@@ -804,8 +813,8 @@ class PF2(Activity.Activity):
         np = float(2 ** bpp - 1)
 
         self.image[preview == 255] = np
-        cv2.imwrite("/tmp/phf2-preview-%s-drag.png" % getpass.getuser(), self.image)
-        temppbuf = GdkPixbuf.Pixbuf.new_from_file("/tmp/phf2-preview-%s-drag.png" % getpass.getuser())
+        cv2.imwrite("/dev/shm/phf2-preview-%s-drag.png" % getpass.getuser(), self.image)
+        temppbuf = GdkPixbuf.Pixbuf.new_from_file("/dev/shm/phf2-preview-%s-drag.png" % getpass.getuser())
         self.ui["preview"].set_from_pixbuf(temppbuf)
 
 
@@ -1030,4 +1039,4 @@ class PF2(Activity.Activity):
     def layer_blend_mode_changed(self, sender):
         layer = self.get_selected_layer()
         if(layer.blend_mode != sender.get_active_text().lower()):
-            layer.set_blending_mode(sender.get_active_text().lower())
+            layer.set_blending_mode(sender.get_active_text().lower())