PIL: can't call same method twice
Hi, I encounter a problem, that I can not explain at all: I have an external method to resize an image (see below). I can call the method without a problem from a script within Zope and it does it's job. Hovever, if I call it twice within the same script, I get the error "can not identify image" although the same FileUpload instance is passed. My (dummy-)script looks something like this: # call the ext. method 'resize' one or more times x=1 # does not work for x >1 image=context.REQUEST.image # passed from a html-form for i in range(0,x): foo = context.resize(image, size=size) the external method 'resize' looks like this: def resize(self, image, size=200, resample='ANTIALIAS'): from PIL import Image image=Image.open(image) [...] I have no idea what the problem could be or where to look. Any advice would be a greate help. Regards Chris
Chris wrote:
Hi,
I encounter a problem, that I can not explain at all:
I have an external method to resize an image (see below). I can call the method without a problem from a script within Zope and it does it's job. Hovever, if I call it twice within the same script, I get the error "can not identify image" although the same FileUpload instance is passed.
My (dummy-)script looks something like this: # call the ext. method 'resize' one or more times x=1 # does not work for x >1 image=context.REQUEST.image # passed from a html-form for i in range(0,x): foo = context.resize(image, size=size)
the external method 'resize' looks like this: def resize(self, image, size=200, resample='ANTIALIAS'): from PIL import Image image=Image.open(image) [...]
I have no idea what the problem could be or where to look.
Any advice would be a greate help. Regards Chris
Maybe move this line image=context.REQUEST.image # passed from a html-form inside your for loop. Maybe image is being changed iteratively. eg, for i in range(0,x): image=context.REQUEST.image # passed from a html-form foo = context.resize(image, size=size) Just a guess, David
Hi David, this is not the problem (tried it before). The code foo = container.resize(context.REQUEST.image, size=size) # works nicely foo = container.resize(context.REQUEST.image, size=size) # 2nd time ->error does what you suggest. But it raises the same error. I looked at the request to see whether image is altered during the resize (but why should it be altert at all?): before and after resize the request has image <ZPublisher.HTTPRequest.FileUpload instance at 0x9668e2c> as expected. It lookt more like a bug (?!?) in the PIL-code. So I looked into the open method of PIL.Image.py (PIL 1.1.4) to no avail. With my limited knowedge I could not see anything obvious. The open() method opens the file "read-only" and tryes to identify the file by reading some header information of the file instance. This is failing however. I guess the prefix is not identified correctly. To do this, open() reads the first 16 characters ot the file. Since I don't know much about the header informations of images (tryed jpg and gif) I can not tell whether they are correct. So I still have no clue :-( Regards Chris David Hassalevris wrote:
Maybe move this line
image=context.REQUEST.image # passed from a html-form
inside your for loop. Maybe image is being changed iteratively. eg,
for i in range(0,x): image=context.REQUEST.image # passed from a html-form foo = context.resize(image, size=size)
Just a guess, David _______________________________________________ Zope maillist - Zope@zope.org http://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope-dev )
Chris wrote:
Hi David,
this is not the problem (tried it before).
The code foo = container.resize(context.REQUEST.image, size=size) # works nicely foo = container.resize(context.REQUEST.image, size=size) # 2nd time ->error does what you suggest. But it raises the same error.
I looked at the request to see whether image is altered during the resize (but why should it be altert at all?): before and after resize the request has image <ZPublisher.HTTPRequest.FileUpload instance at 0x9668e2c> as expected.
It lookt more like a bug (?!?) in the PIL-code. So I looked into the open method of PIL.Image.py (PIL 1.1.4) to no avail. With my limited knowedge I could not see anything obvious. The open() method opens the file "read-only" and tryes to identify the file by reading some header information of the file instance. This is failing however. I guess the prefix is not identified correctly. To do this, open() reads the first 16 characters ot the file. Since I don't know much about the header informations of images (tryed jpg and gif) I can not tell whether they are correct.
So I still have no clue :-(
Regards Chris
Chris, Yes! My suggestion would have made sense if image was passed by ref. But then this *is* python. If you can post ready-to-go code that reproduces this I'd be curious to take a look if for no other reason than I've been meaning to do to PIL stuff myself (i want to convert some chess parser code into python and display diagrams). Plus, there are others who may enjoy taking a crack at it just for the heck of it. David
Hi David,
Yes! My suggestion would have made sense if image was passed by ref. But then this *is* python. If you can post ready-to-go code that reproduces this I'd be curious to take a look if for no other reason
here is some code to reproduce. This is the striped down version of the relevant parts: 1. External Method (create an external method object 'my_thumbs' in ZMI pointing to the script on the fs 2. html-form (only for convenience - you can use a image file object instead) 3. the ZMI-Python script calling my_thumbs I solved my problem now with a different "my_thumb" method returning a list of the needed thumb versions so I call Image.open() only once. But I am sure interested to find out what is causing the problem. Regards, Chris # external method for 'my_thumbs' def thumbs(self, image, size=100): from PIL import Image image=Image.open(image) # this is the problem when called 2 times ... # do stuff with the image - not important for example image.thumbnail((size,size)) file=StringIO() image.save(file, 'JPEG') return file.getvalue() # html-form to provide an fileupload instance to 'resize_image' <html><head><title>Add Image</title></head><body> <form name="form" action="add_image" method="post" enctype="multipart/form-data"> <input name="image" type="file"> <input type="submit" value="submit Image"> </form> </body></html> # the resize_image ZMI Python script image = context.REQUEST.form['image'] image_small = container.my_thumbs(image, size=100) # works :-) image_medium = container.my_thumbs(image, size=200) # does not work :-( # do stuff with the images (store, view, ...) return 'Success :-)'
Chris wrote:
Hi David,
this is not the problem (tried it before).
The code foo = container.resize(context.REQUEST.image, size=size) # works nicely
at this point, try inserting: context.REQUEST.image.seek(0)
foo = container.resize(context.REQUEST.image, size=size) # 2nd time ->error does what you suggest. But it raises the same error.
cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
Chris Withers a écrit :
Chris wrote:
Hi David,
this is not the problem (tried it before).
The code foo = container.resize(context.REQUEST.image, size=size) # works nicely
at this point, try inserting:
context.REQUEST.image.seek(0)
foo = container.resize(context.REQUEST.image, size=size) # 2nd time ->error does what you suggest. But it raises the same error.
cheers,
Chris
I've the same problem and now it's work with this tip : "context.REQUEST.image.seek(0)". My xImageScale.py [external method] is : def xImageScale(img_file, maxx, maxy): from PIL import Image from cStringIO import StringIO img_file.seek(0) im = Image.open(img_file) im.thumbnail((maxx, maxy), Image.ANTIALIAS) out_file_str = StringIO() im.save(out_file_str, im.format) out_file_str.seek(0) tmp=out_file_str.read() out_file_str.close() return tmp -- Stéphane
KLEIN Stéphane wrote at 2005-5-31 00:13 +0200:
... I've the same problem and now it's work with this tip : "context.REQUEST.image.seek(0)".
My xImageScale.py [external method] is :
def xImageScale(img_file, maxx, maxy): from PIL import Image from cStringIO import StringIO img_file.seek(0) im = Image.open(img_file) im.thumbnail((maxx, maxy), Image.ANTIALIAS) out_file_str = StringIO() im.save(out_file_str, im.format) out_file_str.seek(0) tmp=out_file_str.read() out_file_str.close() return tmp
You need to learn that you *MUST* provide a *FULL* problem description when you seek help. This includes "Error Type", "Error Value" and "Traceback" in case you get an exception, and otherwise a clear description what went wrong. -- Dieter
Chris wrote at 2005-3-5 00:09 +0100:
... I have an external method to resize an image (see below). I can call the method without a problem from a script within Zope and it does it's job. Hovever, if I call it twice within the same script, I get the error "can not identify image" although the same FileUpload instance is passed.
That's an easy one: "FileUpload" is a file like object. A file has a file pointer associated. When it is read, the file pointer is advanced -- reading thus has a side effect. Almost surely, your first call moved the file pointer to the end and the second one does not find content. You can use the "seek" method to reposition the file pointer. -- Dieter
Hi Dieter,
Almost surely, your first call moved the file pointer to the end and the second one does not find content.
You can use the "seek" method to reposition the file pointer.
That is, what I thought, too. So I added in PIL.Image.py (Version 1.1.4) in line 1548 "fp.seek(0)" to "rewind" the file object (see below) to no avail. So I guess I am not in the right place. But I will dig into the PIL code soon. Thanx for pointing me in the right direction. Regards Chris # PIL.Image.py # Opens and identifies the given image file. def open(fp, mode="r"): "Open an image file, without loading the raster data" if mode != "r": raise ValueError("bad mode") if isStringType(fp): import __builtin__ filename = fp fp = __builtin__.open(fp, "rb") else: filename = "" fp.seek(0) # NEW LINE: rewind the object prefix = fp.read(16) # [...] continue to identify the the image
Am Sonntag, den 06.03.2005, 14:28 +0100 schrieb Chris:
Hi Dieter,
Almost surely, your first call moved the file pointer to the end and the second one does not find content.
You can use the "seek" method to reposition the file pointer.
That is, what I thought, too. So I added in PIL.Image.py (Version 1.1.4) in line 1548 "fp.seek(0)" to "rewind" the file object (see below) to no avail. So I guess I am not in the right place. But I will dig into the PIL code soon. Thanx for pointing me in the right direction. Regards Chris
You dont have to change PIL code. Just use Parser instead of the Image object directly. import PIL.ImageFile parser=PIL.ImageFile.Parser() chunksize=8192 yourfile.seek(0) chunk=yourfile.read(chunksize) while chunk: parser.feed(chunk) chunk=yourfile.read(chunksize) img=parser.close() ... after the first chunk you feed in, parser.image can contain data of your image, so you can read width and height
participants (6)
-
Chris -
Chris Withers -
David Hassalevris -
Dieter Maurer -
KLEIN Stéphane -
Tino Wildenhain