[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