[Checkins] SVN: z3c.image/trunk/src/z3c/image/ - added a paste processor and a view

Jürgen Kartnaller juergen at kartnaller.at
Wed Jun 20 02:34:18 EDT 2007


Log message for revision 76824:
  - added a paste processor and a view
  - some small refactoring to simplify derived views
  

Changed:
  U   z3c.image/trunk/src/z3c/image/image.py
  U   z3c.image/trunk/src/z3c/image/proc/BROWSER.txt
  U   z3c.image/trunk/src/z3c/image/proc/README.txt
  U   z3c.image/trunk/src/z3c/image/proc/adapter.py
  U   z3c.image/trunk/src/z3c/image/proc/browser.py
  U   z3c.image/trunk/src/z3c/image/proc/interfaces.py
  U   z3c.image/trunk/src/z3c/image/testing/__init__.py

-=-
Modified: z3c.image/trunk/src/z3c/image/image.py
===================================================================
--- z3c.image/trunk/src/z3c/image/image.py	2007-06-20 03:30:21 UTC (rev 76823)
+++ z3c.image/trunk/src/z3c/image/image.py	2007-06-20 06:34:18 UTC (rev 76824)
@@ -1,14 +1,16 @@
-from zope.app.file import Image
-from zope.app.file.interfaces import IImage
 import os
 import stat
-from zope import interface
 import tempfile
 
+from zope import interface
+
+from zope.app.file.interfaces import IImage
+
 LengthError = (TypeError, AttributeError)
 
+
 class VImage(object):
-    
+
     """a non persistent image implementation"""
 
     interface.implements(IImage)

Modified: z3c.image/trunk/src/z3c/image/proc/BROWSER.txt
===================================================================
--- z3c.image/trunk/src/z3c/image/proc/BROWSER.txt	2007-06-20 03:30:21 UTC (rev 76823)
+++ z3c.image/trunk/src/z3c/image/proc/BROWSER.txt	2007-06-20 06:34:18 UTC (rev 76824)
@@ -18,7 +18,7 @@
    >>> dataCtrl.add_file(file(imagePath, 'rb'), 'image/jpeg', 'flower.jpg')
    >>> browser.getControl('Add').click()
 
-Let us upen the standard view of the image
+Let us open the standard view of the image
 
    >>> browser.open('http://localhost/flower.jpg')
    >>> getImageInfo(browser.contents)
@@ -54,7 +54,7 @@
    >>> getImageInfo(browser.contents)
    ('image/jpeg', 20, 23)
 
-There is also a prcessorview, which does processing in the folloing order:
+There is also a processorview, which does processing in the folloing order:
 
  1. rotate
  2. resize

Modified: z3c.image/trunk/src/z3c/image/proc/README.txt
===================================================================
--- z3c.image/trunk/src/z3c/image/proc/README.txt	2007-06-20 03:30:21 UTC (rev 76823)
+++ z3c.image/trunk/src/z3c/image/proc/README.txt	2007-06-20 06:34:18 UTC (rev 76824)
@@ -54,6 +54,18 @@
   >>> res.getImageSize()
   (30, 20)
 
+Also another image can be pasted into the image.
+
+Note: paste changes the original image
+
+  >>> pimg.reset()
+  >>> data = testing.readTestImage('locked.png')
+  >>> from PIL import Image
+  >>> from StringIO import StringIO
+  >>> img = Image.open(StringIO(data))
+  >>> pimg.paste(img, (0, 0), img)
+  >>> res = pimg.process()
+
 Also the PNG and GIF filetypes are supported.
 
   >>> image = testing.getTestImage('locked.png')

Modified: z3c.image/trunk/src/z3c/image/proc/adapter.py
===================================================================
--- z3c.image/trunk/src/z3c/image/proc/adapter.py	2007-06-20 03:30:21 UTC (rev 76823)
+++ z3c.image/trunk/src/z3c/image/proc/adapter.py	2007-06-20 06:34:18 UTC (rev 76824)
@@ -3,7 +3,6 @@
 from z3c.image.image import VImage
 from zope.app.file.interfaces import IFile
 from zope.cachedescriptors.property import readproperty
-from PIL import Image as PILImage
 from cStringIO import StringIO
 from interfaces import IProcessableImage
 from PIL import ImageFile, Image
@@ -17,7 +16,7 @@
 except:
     ulimit = -1
     maxEntries = 100
-    
+
 # see http://mail.python.org/pipermail/image-sig/2003-May/002228.html
 ImageFile.MAXBLOCK = 1024*1024*10
 imgCache = RAMCache()
@@ -28,8 +27,8 @@
 
 def invalidateCache(object, event):
     imgCache.invalidate(object)
-    
 
+
 class ProcessableImage(object):
 
     component.adapts(IFile)
@@ -47,7 +46,7 @@
             data = data.read()
         p = Image.open(StringIO(data))
         return p
-        
+
     def _toImage(self, pimg, *args,**kw):
         """returns an Image object from the given PIL image"""
         if self.format == 'gif':
@@ -71,15 +70,20 @@
     def crop(self, croparea):
         croparea = map(int,croparea)
         self.cmds.append(('crop',(croparea,),{}))
-    
+
     def resize(self, size):
         """See IPILImageResizeUtility"""
-        size = map(int,size)
+        size = map(int, size)
         self.cmds.append(('resize',(size, Image.ANTIALIAS),{}))
 
+    def paste(self, img, box=None, mask=None):
+        if box is not None:
+            box = tuple(map(int, box))
+        self.cmds.append(('paste',(img, box, mask), {}))
+
     def reset(self):
         self.cmds=[]
-        
+
     def process(self,quality=90,optimize=1):
         """processes the command queue and returns the image"""
         if not self.cmds:
@@ -93,7 +97,10 @@
 
         for name,args,kwords in self.cmds:
             func = getattr(pimg,name)
+            oldImg = pimg
             pimg = func(*args,**kwords)
+            if pimg is None:
+                pimg = oldImg
 
         img = self._toImage(pimg, quality=quality, optimize=optimize)
         imgCache.set(img, self.context, key=key)

Modified: z3c.image/trunk/src/z3c/image/proc/browser.py
===================================================================
--- z3c.image/trunk/src/z3c/image/proc/browser.py	2007-06-20 03:30:21 UTC (rev 76823)
+++ z3c.image/trunk/src/z3c/image/proc/browser.py	2007-06-20 06:34:18 UTC (rev 76824)
@@ -1,15 +1,20 @@
-from zope.publisher.browser import BrowserView
-from cStringIO import StringIO
-from zope.app.file import Image
-from interfaces import IProcessableImage
-from zope.dublincore.interfaces import IZopeDublinCore
-import zope.datetime 
 import time
+import PIL
 from datetime import datetime
-from zope.app.file.image import getImageInfo
+from cStringIO import StringIO
 from types import StringType
+
+import zope.datetime
+
 from zope.security.proxy import isinstance
+from zope.publisher.browser import BrowserView
+from zope.dublincore.interfaces import IZopeDublinCore
 
+from zope.app.file.image import getImageInfo
+
+from interfaces import IProcessableImage
+
+
 def getMaxSize(image_size, desired_size):
     """returns the maximum size of image_size to fit into the
     rectangualar defined by desired_size 
@@ -57,23 +62,22 @@
         self.size = (self.width,self.height)
 
     def _process(self):
-
         pimg = IProcessableImage(self.context)
+        self._pushCommands(pimg)
+        return pimg.process()
 
+    def _pushCommands(self, pimg):
         if self.degrees > 0:
             pimg.rotate(self.degrees)
         if self.width and self.height:
             pimg.resize(self.size)
-
         if self.cropX is not None and self.cropY is not None \
            and self.cropW is not None and self.cropH is not None:
-
             self.croparea = (int(self.cropX),
                              int(self.cropY),
                              int(self.cropX) + int(self.cropW),
                              int(self.cropY) + int(self.cropH))
             pimg.crop(self.croparea)
-
         return pimg.process()
 
     def processed(self):
@@ -125,10 +129,33 @@
         self.width = self.request.form.get('w',self.size[0])
         self.height = self.request.form.get('h',self.size[1])
 
-    def _process(self):
+    def _pushCommands(self, pimg):
         new_size = getMaxSize(self.size, (self.width, self.height))
-        pimg = IProcessableImage(self.context)
         if new_size != self.size:
             pimg.resize(new_size)
-        return pimg.process()
 
+
+class PasteImageView(ResizedImageView):
+    """Paste an image into the image.
+
+    The subclass must provide the image to be pasted.
+    """
+
+    img = None
+
+    def __init__(self,context,request):
+        super(PasteImageView, self).__init__(context, request)
+        self.x = self.request.form.get('x', 0)
+        self.y = self.request.form.get('y', 0)
+        self.imgId = self.request.form.get('img', 0)
+
+    def _pushCommands(self, pimg):
+        super(PasteImageView, self)._pushCommands(pimg)
+        img = self.img
+        if img is not None:
+            if type(img)!=StringType:
+                img.seek(0)
+                img = img.read()
+            img = PIL.Image.open(StringIO(img))
+            pimg.paste(img, (self.x, self.y), img)
+

Modified: z3c.image/trunk/src/z3c/image/proc/interfaces.py
===================================================================
--- z3c.image/trunk/src/z3c/image/proc/interfaces.py	2007-06-20 03:30:21 UTC (rev 76823)
+++ z3c.image/trunk/src/z3c/image/proc/interfaces.py	2007-06-20 06:34:18 UTC (rev 76824)
@@ -6,14 +6,14 @@
         """returns the processed image"""
 
     def rotate(degrees):
-
         """rotates the image by degrees"""
 
     def resize(size):
+        """resizes the image to (w,h)"""
 
-        """resizes the image to (w,h)"""
-        
     def crop(croparea):
+        """ crops the image """
 
-        """ crops the image """
-        
+    def paste(pos, img, mask):
+        """ paste an image at pos with mask"""
+

Modified: z3c.image/trunk/src/z3c/image/testing/__init__.py
===================================================================
--- z3c.image/trunk/src/z3c/image/testing/__init__.py	2007-06-20 03:30:21 UTC (rev 76823)
+++ z3c.image/trunk/src/z3c/image/testing/__init__.py	2007-06-20 06:34:18 UTC (rev 76824)
@@ -4,7 +4,11 @@
 
 dataDir = os.path.join(os.path.dirname(__file__),'data')
 
+def readTestImage(name):
+    path = os.path.join(dataDir,name)
+    return file(path, 'rb').read()
+
 def getTestImage(name):
     """returns a zope image with the given name from this directory"""
-    path = os.path.join(dataDir,name)
-    return Image(file(path, 'rb').read())
+    return Image(readTestImage(name))
+



More information about the Checkins mailing list