diff options
author | Keshav Sharma <keshav7890@gmail.com> | 2011-07-03 11:22:14 (GMT) |
---|---|---|
committer | Keshav Sharma <keshav7890@gmail.com> | 2011-07-03 11:22:14 (GMT) |
commit | ca10d560496dc9f6edde8b422fe591c96c175a6d (patch) | |
tree | 5efdf45be57028217d8f742651301ec234824401 /ImageProcess.py |
added activity folder
Diffstat (limited to 'ImageProcess.py')
-rw-r--r-- | ImageProcess.py | 523 |
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() |