From fdce651dad14009690c88324c96e10a61d36831d Mon Sep 17 00:00:00 2001 From: Ayush Goyal Date: Wed, 20 Oct 2010 13:38:25 +0000 Subject: Added Invert Color Effect to Paint Activity (OLPC #2495) Signed-off-by: Ayush Goyal --- diff --git a/Area.py b/Area.py index a0e82d0..a4f744f 100644 --- a/Area.py +++ b/Area.py @@ -69,10 +69,12 @@ import os import tempfile import math import pango +import numpy from fill import * from Desenho import Desenho from urlparse import urlparse + ##Tools and events manipulation are handle with this class. TARGET_URI = 0 @@ -80,7 +82,6 @@ TARGET_URI = 0 class Area(gtk.DrawingArea): - __gsignals__ = { 'undo': (gobject.SIGNAL_ACTION, gobject.TYPE_NONE, ([])), 'redo': (gobject.SIGNAL_ACTION, gobject.TYPE_NONE, ([])), @@ -227,7 +228,7 @@ class Area(gtk.DrawingArea): self.gc = win.new_gc() self.gc_eraser = win.new_gc() colormap = self.get_colormap() - self.white = colormap.alloc_color('#ffffff', True, True) # white + self.white = colormap.alloc_color('#ffffff', True, True) # white self.black = colormap.alloc_color('#000000', True, True) # black self.gc_eraser.set_foreground(self.white) @@ -555,7 +556,7 @@ class Area(gtk.DrawingArea): self.selmove = True self.sel_get_out = False self.emit('select') - elif self.sel_get_out: #get out of the func selection + elif self.sel_get_out: # get out of the func selection self.getout() try: del(self.d.pixbuf_resize) @@ -648,7 +649,7 @@ class Area(gtk.DrawingArea): if self.undo_times > 0: self.undo_times -= 1 self.redo_times += 1 - try: #to not try paint someting wrong + try: # to not try paint someting wrong self.pixmap.draw_drawable(self.gc, self.undo_list[self.undo_times], 0, 0, 0, 0, width, height) except: @@ -663,7 +664,7 @@ class Area(gtk.DrawingArea): #special case for func polygon if self.tool['name'] == 'freeform': - self.polygon_start = True #start the polygon again + self.polygon_start = True # start the polygon again self.emit('undo') @@ -680,7 +681,7 @@ class Area(gtk.DrawingArea): self.redo_times -= 1 self.undo_times += 1 - try: #to not try paint someting wrong + try: # to not try paint someting wrong self.pixmap.draw_drawable(self.gc, self.undo_list[self.undo_times], 0, 0, 0, 0, width, height) @@ -705,11 +706,11 @@ class Area(gtk.DrawingArea): if self.undo_surf: self.undo_times += 1 - self.undo_list.append(None)#alloc memory + self.undo_list.append(None) # alloc memory self.undo_list[self.undo_times] = gtk.gdk.Pixmap(widget.window, - width, height, -1) #define type + width, height, -1) # define type self.undo_list[self.undo_times].draw_drawable(self.gc, self.pixmap, - 0, 0, 0, 0, width, height) #copy workarea + 0, 0, 0, 0, width, height) # copy workarea self.undo_times += 1 self.redo_times = 0 self.first_undo = True @@ -915,6 +916,56 @@ class Area(gtk.DrawingArea): if not self.selmove: self.enableUndo(widget) + def invert_colors(self, widget): + """Apply invert effect. + + @param self -- the Area object (GtkDrawingArea) + @param widget -- the Area object (GtkDrawingArea) + + """ + + width, height = self.window.get_size() + + if self.selmove: + size = self.pixmap_sel.get_size() + pix = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, + size[0], size[1]) + pix.get_from_drawable(self.pixmap_sel, + gtk.gdk.colormap_get_system(), 0, 0, 0, 0, size[0], size[1]) + else: + pix = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, + width, height) + pix.get_from_drawable(self.pixmap, gtk.gdk.colormap_get_system(), + 0, 0, 0, 0, width, height) + + pix_manip2 = pix.get_pixels_array() + pix_manip = numpy.ones(pix_manip2.shape, dtype=numpy.uint8) * 255 + pix_manip2 = pix_manip - pix_manip2 + pix = gtk.gdk.pixbuf_new_from_array(pix_manip2, gtk.gdk.COLORSPACE_RGB, + 8) + + if self.selmove: + self.pixmap_sel.draw_pixbuf(self.gc, pix, 0, 0, 0, 0, + size[0], size[1], dither=gtk.gdk.RGB_DITHER_NORMAL, + x_dither=0, y_dither=0) + + self.pixmap_temp.draw_drawable(self.gc, self.pixmap, 0, 0, 0, 0, + width, height) + self.pixmap_temp.draw_drawable(self.gc, self.pixmap_sel, + 0, 0, self.orig_x, self.orig_y, size[0], size[1]) + self.pixmap_temp.draw_rectangle(self.gc_selection, False, + self.orig_x, self.orig_y, size[0], size[1]) + self.pixmap_temp.draw_rectangle(self.gc_selection1, False, + self.orig_x - 1, self.orig_y - 1, size[0] + 2, size[1] + 2) + + else: + self.pixmap.draw_pixbuf(self.gc, pix, 0, 0, 0, 0, width, height, + dither=gtk.gdk.RGB_DITHER_NORMAL, x_dither=0, y_dither=0) + + self.queue_draw() + if not self.selmove: + self.enableUndo(widget) + def _pixbuf2Image(self, pb): """change a pixbuf to RGB image @@ -1274,7 +1325,7 @@ class Area(gtk.DrawingArea): self.orig_x = 0 self.orig_y = 0 self.pixmap_temp.draw_rectangle(self.gc_selection, False, - 0, 0, width-1, height-1) + 0, 0, width - 1, height - 1) self.selmove = True self.sel_get_out = False self.emit('select') diff --git a/icons/invert-colors.svg b/icons/invert-colors.svg new file mode 100644 index 0000000..373ca70 --- /dev/null +++ b/icons/invert-colors.svg @@ -0,0 +1,387 @@ + +image/svg+xml \ No newline at end of file diff --git a/toolbox.py b/toolbox.py index 53e05fa..1ff4e6f 100644 --- a/toolbox.py +++ b/toolbox.py @@ -430,7 +430,6 @@ class ToolsToolbar(gtk.Toolbar): except: logging.debug('Could not create palette for tool selection area') - # New connect method # Using dictionnaries to control tool's properties self._tool_pencil.connect('clicked', self.set_tool, self._TOOL_PENCIL) @@ -564,8 +563,6 @@ class ToolsToolbar(gtk.Toolbar): #setting cursor: Moved to Area - - # def _on_fill_checkbutton_map(self, checkbutton, data=None): # """ # Update checkbutton condition to agree with Area.Area object; @@ -809,7 +806,6 @@ class ShapesToolbar(gtk.Toolbar): except: logging.debug('Could not create palette for Shape Triangle') - self._shape_arrow.connect('clicked', self.set_tool, self._SHAPE_ARROW) self._shape_ellipse.connect('clicked', self.set_tool, self._SHAPE_ELLIPSE) @@ -1031,7 +1027,6 @@ class TextToolbar(gtk.Toolbar): separator.set_draw(True) self.insert(separator, -1) - """ #FIXME: this button is not connected to the right callback self._bold = ToggleToolButton('format-text-bold') @@ -1249,6 +1244,7 @@ class ImageToolbar(gtk.Toolbar): class EffectsToolbar(gtk.Toolbar): _EFFECT_GRAYSCALE = 'grayscale' + _INVERT_COLOR = 'invert-colors' # Rainbow acts as a tool in Area, and it has to be described as a dict _EFFECT_RAINBOW = {'name': 'rainbow', 'line size': 10, @@ -1272,6 +1268,11 @@ class EffectsToolbar(gtk.Toolbar): self.insert(self._effect_rainbow, -1) self._configure_palette(self._effect_rainbow, self._EFFECT_RAINBOW) + self._invert_colors = ToolButton('invert-colors') + self.insert(self._invert_colors, -1) + self._invert_colors.show() + self._invert_colors.set_tooltip(_('Invert Colors')) + separator = gtk.SeparatorToolItem() self.insert(separator, -1) @@ -1284,16 +1285,11 @@ class EffectsToolbar(gtk.Toolbar): 'effect-black-and-white') self._black_and_white.set_tooltip(_('Black and White')) - self._invert_colors = ToolButton('invert_colors') - self.insert(self._invert_colors, -1) - self._invert_colors.show() - self._invert_colors.connect('clicked', test_connect, activity, - 'invert-colors') - self._invert_colors.set_tooltip(_('Invert Colors')) - """ + self._effect_grayscale.connect('clicked', self.grayscale) self._effect_rainbow.connect('clicked', self.rainbow) + self._invert_colors.connect('clicked', self.invert_colors) ##Make the colors be in grayscale def grayscale(self, widget): @@ -1303,6 +1299,9 @@ class EffectsToolbar(gtk.Toolbar): def rainbow(self, widget): self._activity.area.set_tool(self._EFFECT_RAINBOW) + def invert_colors(self, widget): + self._activity.area.invert_colors(widget) + # setting cursor: moved to Area def _configure_palette(self, button, tool=None): -- cgit v0.9.1