Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/ImageProcess.py
diff options
context:
space:
mode:
authorKeshav Sharma <keshav7890@gmail.com>2011-07-03 11:22:14 (GMT)
committer Keshav Sharma <keshav7890@gmail.com>2011-07-03 11:22:14 (GMT)
commitca10d560496dc9f6edde8b422fe591c96c175a6d (patch)
tree5efdf45be57028217d8f742651301ec234824401 /ImageProcess.py
added activity folder
Diffstat (limited to 'ImageProcess.py')
-rw-r--r--ImageProcess.py523
1 files changed, 523 insertions, 0 deletions
diff --git a/ImageProcess.py b/ImageProcess.py
new file mode 100644
index 0000000..2e5cb54
--- /dev/null
+++ b/ImageProcess.py
@@ -0,0 +1,523 @@
+# Copyright (C) 2008, One Laptop per Child
+# Author: Keshav Sharma <keshav7890@gmail.com> & Vaibhav Sharma
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+from __future__ import division
+import pygtk
+import gtk
+from gtk import gdk
+import gobject
+import sys
+import Image,ImageEnhance,ImageFont,ImageFilter,ImageOps
+import ImageDraw
+import StringIO
+import logging
+import random
+from sugar import mime
+import gst, pygame, sys, time
+from random import *
+
+class ImageProcessor(gtk.DrawingArea):
+ __gsignals__ = {
+ 'expose-event' : ('override'),
+ 'zoom-changed' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []),
+ 'angle-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []),
+ }
+
+ __gproperties__ = {
+ 'zoom': (gobject.TYPE_FLOAT, 'Zoom Factor', 'Factor of zoom',0, 4, 1, gobject.PARAM_READWRITE),
+ 'angle': (gobject.TYPE_INT, 'Angle', 'Angle of rotation',0, 360, 0, gobject.PARAM_READWRITE),
+ 'file_location':( gobject.TYPE_STRING, 'File Location', 'Location of the image file',
+ '', gobject.PARAM_READWRITE),
+ }
+
+ def __init__(self):
+ gtk.DrawingArea.__init__(self)
+ self.set_app_paintable(True)
+ self.pixbuf = None
+ self.zoom = None
+ self.input_text = "text to edit"
+ self._tempfile = None
+ self.file_location = None
+ self._temp_pixbuf = None
+ self.edit_text = None
+ self.im = None
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ self.angle = 0
+
+ def do_get_property(self, pspec):
+ if pspec.name == 'zoom' : return self.zoom
+ elif pspec.name == 'angle' : return self.angle
+ elif pspec.name == 'file_location': return self.file_location
+ else: raise AttributeError('unknown property %s' % pspec.name)
+
+ def do_set_property(self, pspec, value):
+ if pspec.name == 'zoom': self.set_zoom(value)
+ elif pspec.name == 'angle': self.set_angle(value)
+ elif pspec.name == 'file_location' : self.set_file_location(value)
+ else: raise AttributeError('unknown property %s' % pspec.name)
+
+ def calculate_optimal_zoom(self, width=None, height=None, pixbuf=None):
+ # This tries to figure out a best fit model
+ # If the image can fit in, we show it in 1:1,
+ # in any other case we show it in a fit to screen way
+
+ if pixbuf == None:
+ pixbuf = self.pixbuf
+
+ if width == None or height == None:
+ rect = self.parent.get_allocation()
+ width = rect.width
+ height = rect.height
+
+ if width < pixbuf.get_width() or height < pixbuf.get_height():
+ # Image is larger than allocated size
+ zoom = min(width / pixbuf.get_width(),
+ height / pixbuf.get_height())
+ else: zoom = 1
+
+ self._optimal_zoom_flag = True
+
+ return zoom - 0.018 #XXX: Hack
+
+ def set_pixbuf( self , pixbuf ):
+ self.pixbuf = pixbuf
+ self.zoom = None
+ self._image_changed_flag = True
+ if self.window:
+ alloc = self.get_allocation()
+ rect = gdk.Rectangle( alloc.x , alloc.y , alloc.width ,alloc.height )
+ self.window.invalidate_rect( rect , True )
+ self.window.process_updates( True )
+
+ #def do_size_request(self, requisition):
+ # requisition.width = self.pixbuf.get_width()
+ # requisition.height = self.pixbuf.get_height()
+
+ def do_expose_event(self, event):
+ ctx = self.window.cairo_create()
+ ctx.rectangle(event.area.x, event.area.y,
+ event.area.width, event.area.height)
+ ctx.clip()
+ self.draw(ctx)
+
+ def draw(self, ctx):
+ if not self.pixbuf:
+ return
+ if self.zoom == None:
+ self.zoom = self.calculate_optimal_zoom()
+
+ if self._temp_pixbuf == None or self._image_changed_flag == True:
+ width, height = self.rotate()
+ self._temp_pixbuf = self._temp_pixbuf.scale_simple(width, height, gtk.gdk.INTERP_TILES)
+ self._image_changed_flag = False
+
+ rect = self.get_allocation()
+ x = rect.x
+ y = rect.y
+
+ width = self._temp_pixbuf.get_width()
+ height = self._temp_pixbuf.get_height()
+
+ if self.parent:
+ rect = self.parent.get_allocation()
+ if rect.width > width:
+ x = int(((rect.width - x) - width) / 2)
+
+ if rect.height > height:
+ y = int(((rect.height - y) - height) / 2)
+
+ self.set_size_request(self._temp_pixbuf.get_width(),
+ self._temp_pixbuf.get_height())
+
+ ctx.set_source_pixbuf(self._temp_pixbuf, x, y)
+
+ ctx.paint()
+
+ def set_zoom(self, zoom):
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = False
+ self.zoom = zoom
+
+ if self.window:
+ alloc = self.get_allocation()
+ rect = gdk.Rectangle(alloc.x, alloc.y,
+ alloc.width, alloc.height)
+ self.window.invalidate_rect(rect, True)
+ self.window.process_updates(True)
+
+ self.emit('zoom-changed')
+
+ def set_angle(self, angle):
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+
+ self.angle = angle
+
+ if self.window:
+ alloc = self.get_allocation()
+ rect = gdk.Rectangle(alloc.x, alloc.y,
+ alloc.width, alloc.height)
+ self.window.invalidate_rect(rect, True)
+ self.window.process_updates(True)
+
+ self.emit('angle-changed')
+
+ def rotate(self):
+ if self.angle == 0:
+ rotate = gtk.gdk.PIXBUF_ROTATE_NONE
+ elif self.angle == 90:
+ rotate = gtk.gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE
+ elif self.angle == 180:
+ rotate = gtk.gdk.PIXBUF_ROTATE_UPSIDEDOWN
+ elif self.angle == 270:
+ rotate = gtk.gdk.PIXBUF_ROTATE_CLOCKWISE
+ elif self.angle == 360:
+ self.angle = 0
+ rotate = gtk.gdk.PIXBUF_ROTATE_NONE
+ else:
+ logging.warning('Got unsupported rotate angle')
+
+ self._temp_pixbuf = self.pixbuf.rotate_simple(rotate)
+ width = int(self._temp_pixbuf.get_width() * self.zoom)
+ height = int(self._temp_pixbuf.get_height() * self.zoom)
+
+ return (width, height)
+
+ def zoom_in(self):
+ self.set_zoom(self.zoom + 0.2)
+ if self.zoom > (4): return False
+ else: return True
+
+ def zoom_out(self):
+ self.set_zoom(self.zoom - 0.2)
+ if self.zoom <= 0.2: return False
+ else: return True
+
+ def grey(self,value):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ im = self.pixbuftoImage(pixbuf)
+ im.convert("RGB")
+ r, g, b = im.split()
+ im = Image.merge("RGB", (g,g,g))
+ pix=self.imagetopixbuf(im)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+ def image_copy(self,value):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ im = self.pixbuftoImage(pixbuf)
+ self.im = im.copy()
+
+ def image_paste(self,value):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ im = self.im
+ pix=self.imagetopixbuf(im)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+
+ def image_Blur(self,value):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ im = self.pixbuftoImage(pixbuf)
+ im = im.filter(ImageFilter.BLUR)
+ pix=self.imagetopixbuf(im)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+
+ def image_Transpose(self,value):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ im = self.pixbuftoImage(pixbuf)
+ im = im.transpose(Image.FLIP_LEFT_RIGHT)
+ pix=self.imagetopixbuf(im)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+
+ def image_Offset(self,value):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ im = self.pixbuftoImage(pixbuf)
+ w,h=im.size
+ im = im.offset(w/2,h/2)
+ pix=self.imagetopixbuf(im)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+
+ def image_Contour(self,value):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ im = self.pixbuftoImage(pixbuf)
+ im = im.filter(ImageFilter.CONTOUR)
+ pix=self.imagetopixbuf(im)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+
+ def image_Finedges(self,value):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ im = self.pixbuftoImage(pixbuf)
+ im = im.filter(ImageFilter.FIND_EDGES)
+ pix=self.imagetopixbuf(im)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+
+ def image_Solarize(self,value):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ im = self.pixbuftoImage(pixbuf)
+ im = ImageOps.solarize(im, threshold=128)
+ pix=self.imagetopixbuf(im)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+
+ def image_left_top(self,edit_text):
+ self.edit_text="left_top"
+ self.image_edit_text(self.edit_text)
+
+ def image_right_top(self,edit_text):
+ self.edit_text='right_top'
+ self.image_edit_text(self.edit_text)
+
+ def image_left_bottom(self,edit_text):
+ self.edit_text='left_bottom'
+ self.image_edit_text(self.edit_text)
+
+ def image_right_bottom(self,edit_text):
+ self.edit_text='right_bottom'
+ self.image_edit_text(self.edit_text)
+
+ def image_edit_text(self,edit_text):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ self.edit_text = edit_text
+ if self.window:
+ im = self.pixbuftoImage(pixbuf)
+ out=self.Imprint(im, self.input_text,self.edit_text)
+ pix=self.imagetopixbuf(out)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+ def input_text_cb(self,text):
+ self.input_text=str(text)
+
+ def Imprint(self,im, inputtext,edit_text, font=None, color=None, opacity=.6, margin=(30,30)):
+ """
+ imprints a PIL image with the indicated text in lower-right corner
+ """
+ if im.mode != "RGBA":
+ im = im.convert("RGBA")
+ w,h=im.size
+ textlayer = Image.new("RGBA", im.size, (0,0,0,0))
+ textdraw = ImageDraw.Draw(textlayer)
+ textsize = textdraw.textsize(inputtext, font=font)
+ if edit_text=="left_top":
+ textpos = [margin[i] for i in [0,1]]
+ elif edit_text=="right_top":
+ textpos = im.size[0]-textsize[0]-margin[0],margin[1]
+ elif edit_text=="left_bottom":
+ textpos = margin[0],im.size[1]-textsize[1]-margin[1]
+ else:
+ textpos = [im.size[i]-textsize[i]-margin[i] for i in [0,1]]
+ textdraw.text(textpos, inputtext, font=font, fill="red")
+ if opacity != 1:
+ textlayer = self.reduce_opacity(textlayer,opacity)
+ return Image.composite(textlayer, im, textlayer)
+
+ def image_Sharpen(self,value):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ im = self.pixbuftoImage(pixbuf)
+ im = im.filter(ImageFilter.SHARPEN)
+ pix=self.imagetopixbuf(im)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+
+ def image_Ambross(self,value):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ im = self.pixbuftoImage(pixbuf)
+ im = im.filter(ImageFilter.EMBOSS)
+ pix=self.imagetopixbuf(im)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+
+ def image_Invert(self,value):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+ if self.window:
+ im = self.pixbuftoImage(pixbuf)
+ im = ImageOps.invert(im)
+ pix=self.imagetopixbuf(im)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+
+
+ def image_Watermark(self,mark,pos):
+ pixbuf = self.pixbuf
+ self._image_changed_flag = True
+ self._optimal_zoom_flag = True
+
+ if self.window:
+ im1=Image.open(mark)
+ im = self.pixbuftoImage(pixbuf)
+ if pos=="tile":
+ im = self.watermark(im, im1,"tile",0.5)
+ elif pos=="scale":
+ im = self.watermark(im, im1,"scale",0.5)
+ else :#if pos is top_left
+ im = self.watermark(im, im1,(0,0),0.5)
+ #(raw_input('type of watermark(tile/scale,(xsize,ysize))')), 0.5)
+ pix=self.imagetopixbuf(im)
+ self.set_pixbuf( pix )
+ self.window.process_updates( True )
+
+
+ def pixbuftoImage(self,pb):
+ width,height = pb.get_width(),pb.get_height()
+ return Image.fromstring("RGB",(width,height),pb.get_pixels() )
+
+ def imagetopixbuf(self,im):
+ file1 = StringIO.StringIO()
+ im.save(file1, "ppm")
+ contents = file1.getvalue()
+ file1.close()
+ loader = gtk.gdk.PixbufLoader("pnm")
+ loader.write(contents, len(contents))
+ pixbuf = loader.get_pixbuf()
+ loader.close()
+ return pixbuf
+
+ def reduce_opacity(self,im, opacity):
+ """Returns an image with reduced opacity."""
+ assert opacity >= 0 and opacity <= 1
+ if im.mode != 'RGBA': im = im.convert('RGBA')
+ else : im = im.copy()
+ alpha = im.split()[3]
+ alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
+ im.putalpha(alpha)
+ return im
+ #watermark to an image
+ def watermark(self,im, mark, position, opacity=1):
+ """Adds a watermark to an image."""
+ if opacity < 1 : mark = self.reduce_opacity(mark, opacity)
+ if im.mode != 'RGBA': im = im.convert('RGBA')
+ # create a transparent layer the size of the image and draw the
+ # watermark in that layer.
+ layer = Image.new('RGBA', im.size, (0,0,0,0))
+ if position == 'tile':
+ w,h=im.size
+ mark = mark.resize((w/2, h/2))
+ for y in range(0, im.size[1], mark.size[1]):
+ for x in range(0, im.size[0], mark.size[0]): layer.paste(mark,(x, y))
+ elif position == 'scale':
+ # scale, but preserve the aspect ratio
+ ratio = min(float(im.size[0]) / mark.size[0], float(im.size[1]) / mark.size[1])
+ w = int(mark.size[0] * ratio)
+ h = int(mark.size[1] * ratio)
+ mark = mark.resize((w, h))
+ layer.paste(mark, ((im.size[0] - w) / 2, (im.size[1] - h) / 2))
+ else:
+ w,h=im.size
+ mark = mark.resize((w/2, h/2))
+ layer.paste(mark, position)
+ # composite the watermark with the layer
+ return Image.composite(layer, im, layer)
+
+ def original_cb(self,value):
+ self.set_file_location(self.original)
+
+ def set_file_location(self, file_location):
+ self.original=file_location
+ self.pixbuf = gtk.gdk.pixbuf_new_from_file(file_location)
+ self.file_location = file_location
+ self.zoom = None
+ self._image_changed_flag = True
+ if self.window:
+ alloc = self.get_allocation()
+ rect = gdk.Rectangle(alloc.x, alloc.y, alloc.width, alloc.height)
+ self.window.invalidate_rect(rect, True)
+ self.window.process_updates(True)
+
+#check working of functions
+def update(view_object):
+ view.grey("g")
+ return True
+
+
+if __name__ == '__main__':
+ window = gtk.Window()
+
+ vadj = gtk.Adjustment()
+ hadj = gtk.Adjustment()
+ sw = gtk.ScrolledWindow(hadj, vadj)
+
+ view = ImageProcessor()
+
+ view.set_file_location(sys.argv[1])
+
+
+ sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+
+
+ sw.add_with_viewport(view)
+ window.add(sw)
+
+ window.set_size_request(800, 600)
+
+ window.show_all()
+
+ gobject.timeout_add(1000, update, view)
+
+ gtk.main()