- Image object enhancements (patch included!)
Christopher G. Petrilli wrote:
What I want to be able to do is have a folder that contains images as a subfolder to my current folder. Now I know I can reference them, no problem: <!--#var "images.logo"--> but that doesn't give the right SRC= line in the IMG directive. Now I sat and thought about this, but I'm just not sure how an image is supposed to find itself in the hierarchy so it can publish the right URL to find itself.
This is related to another problem, which is that if you have: Folder: /site Doc: standard_html_header (contains "<!--#var logo-->") Image: logo Doc: index_html ("<!--#var standard_html_header-->") Folder: foo Doc: index_html ("<!--#var standard_html_header-->") Folder: bar Doc: index_html ("<!--#var standard_html_header-->") If you go look at http://localhost/site, http://localhost/site/foo/, and http://localhost/site/foo/bar/, your browser will need to download http://localhost/site/logo, http://localhost/site/foo/logo, and http://localhost/site/foo/bar/logo. It doesn't know that they're the same object, since they're differently-named. The __str__ method on images really needs to figure out the true absolute path of the object and use that. (like <IMG SRC="/site/logo">) ... Speaking of things that need to be done about Image objects, the fact that they don't send a size can be annoying to users of a site. When the image tag includes a width and height, the browser can lay out the page without waiting to see how large the image is. I had trouble falling asleep last night, so I got up and thought I'd take a look at how hard it'd be to implement. Shortly thereafter, I had the patches below. :^) Image now autodetects the dimensions of uploaded GIF or PNG images (JPEG is harder and I use many more GIFs than JPEGs, so I punted on that. Someone else can add it if they feel ambitious). For pre-existing objects, you can make the object compute (or recompute) the dimensions by going into the Edit tab, clearing the dimension inputs, and submitting. You can also manually set the dimensions to something else if you like, though this is not generally recommended as a way to scale images. If Image is unable to figure out the dimensions (JPEG, or some other unknown format), the width and heigh remain unset and the IMG tag is generated without them. Maybe next time I'm insomniac I'll look at the absolute oath issue :^) --- Image.py.orig Sun Dec 6 23:16:46 1998 +++ Image.py Mon Dec 7 08:20:04 1998 @@ -93,7 +93,7 @@ from Globals import Persistent from Acquisition import Implicit from DateTime import DateTime -import string +import string, struct manage_addFileForm=HTMLFile('imageAdd', globals(),Kind='File',kind='file') def manage_addFile(self,id,file,title='',precondition='',REQUEST=None): @@ -157,6 +157,7 @@ self.title=title if precondition: self.precondition=precondition self.size=len(self.data) + self._post_upload() def id(self): return self.__name__ @@ -187,12 +188,15 @@ """ raise 'Redirect', URL1 - def manage_edit(self,title,content_type,precondition='',REQUEST=None): + def manage_edit(self,title,content_type,precondition='',width='',height='',REQUEST=None): """ Changes the title and content type attributes of the File or Image. """ self.title=title self.content_type=content_type + self.width = width + self.height = height + self._intuit_image_size() if precondition: self.precondition=precondition elif self.precondition: del self.precondition if REQUEST: return MessageDialog( @@ -211,6 +215,7 @@ data=file.read() self.data=Pdata(data) self.size=len(data) + self._post_upload() if REQUEST: return MessageDialog( title ='Success!', message='Your changes have been saved', @@ -226,6 +231,7 @@ 'handle PUT requests' self.data=Pdata(BODY) self.size=len(BODY) + self._post_upload() try: type=REQUEST['CONTENT_TYPE'] if type: self.content_type=type @@ -246,6 +252,10 @@ """ return self.content_type + def _post_upload(self): + # hook can be overridden in subclasses + pass + def size(self): return len(self.data) def __str__(self): return str(self.data) def __len__(self): return 1 @@ -263,7 +273,7 @@ if REQUEST is not None: return self.manage_main(self,REQUEST) class Image(File): - """Principia object for *Images*, can be GIF or JPEG. Has the same + """Principia object for *Images*, can be GIF, PNG, or JPEG. Has the same methods as File objects. Images also have a string representation that renders an HTML 'IMG' tag. """ @@ -282,8 +292,36 @@ kind='image') manage=manage_main=manage_editForm + def _post_upload(self): + self.width = self.height = '' + self._intuit_image_size() + def __str__(self): - return '<IMG SRC="%s" ALT="%s">' % (self.__name__, self.title_or_id()) + w = h = '' + if hasattr(self, 'width') and len(self.width): + w = 'WIDTH="%s" ' % self.width + if hasattr(self, 'height') and len(self.height): + h = 'HEIGHT="%s" ' % self.height + + return '<IMG SRC="%s" %s%sALT="%s">' % (self.__name__, w, h, self.title_or_id()) + + def _intuit_image_size(self): + w = h = '' + + # handle GIFs + if (self.size >= 10) and self.data[:6] in ('GIF87a', 'GIF89a'): + w, h = struct.unpack("<HH", self.data[6:10]) + w = str(int(w)); h = str(int(h)) + + # handle PNGs + if (self.size >= 16) and (self.data[:8] == '\x89PNG\r\n\x1a\n'): + w, h = struct.unpack(">LL", self.data[8:16]) + w = str(int(w)); h = str(int(h)) + + if not hasattr(self, 'width') or not len(self.width): + self.width = w + if not hasattr(self, 'height') or not len(self.height): + self.height = h def cookId(id, title, file): if not id and hasattr(file,'filename'): @@ -306,3 +344,5 @@ def __len__(self): return len(self.data) + def __getslice__(self, i, j): + return self.data[i:j] --- imageEdit.dtml.orig Sun Dec 6 23:08:03 1998 +++ imageEdit.dtml Sun Dec 6 23:17:22 1998 @@ -18,6 +18,20 @@ </TD> </TR> <TR> + <TH ALIGN="LEFT" VALIGN="TOP"><EM>Width</EM></TH> + <TD ALIGN="LEFT" VALIGN="TOP"> + <INPUT TYPE="STRING" NAME="width" SIZE="10" + VALUE="<!--#if width--><!--#var width--><!--#/if-->"> + </TD> + </TR> + <TR> + <TH ALIGN="LEFT" VALIGN="TOP"><EM>Height</EM></TH> + <TD ALIGN="LEFT" VALIGN="TOP"> + <INPUT TYPE="STRING" NAME="height" SIZE="10" + VALUE="<!--#if height--><!--#var height--><!--#/if-->"> + </TD> + </TR> + <TR> <TH ALIGN="LEFT" VALIGN="TOP">Content Type</TH> <TD ALIGN="LEFT" VALIGN="TOP"> <INPUT TYPE="TEXT" NAME="content_type:required" SIZE="40" --- imageView.dtml.orig Sun Dec 6 23:24:31 1998 +++ imageView.dtml Sun Dec 6 23:24:37 1998 @@ -5,7 +5,10 @@ <BODY BGCOLOR="#FFFFFF" LINK="#000099" VLINK="#555555"> <!--#var manage_tabs--> -<IMG src="<!--#var id-->" ALT="<!--#var title_or_id-->"> +<IMG src="<!--#var id-->" +<!--#if width-->WIDTH="<!--#var width-->"<!--#/if--> +<!--#if height-->HEIGHT="<!--#var height-->"<!--#/if--> +ALT="<!--#var title_or_id-->"> </BODY> </HTML>
Hi Ty (Ty Sarna), in <199812072202.QAA24362@fezzik.endicor.com> on Dec 7 you wrote:
If you go look at http://localhost/site, http://localhost/site/foo/, and http://localhost/site/foo/bar/, your browser will need to download http://localhost/site/logo, http://localhost/site/foo/logo, and http://localhost/site/foo/bar/logo. It doesn't know that they're the same object, since they're differently-named.
The __str__ method on images really needs to figure out the true absolute path of the object and use that. (like <IMG SRC="/site/logo">)
I'm a bit worried that this will tend to break acquisition behavior in general. For these types of problem, I'd tend to just specify the absolute URL in the reference. Deals with the problem without having to change acquisition. Kent
Kent Polk wrote:
The __str__ method on images really needs to figure out the true absolute path of the object and use that. (like <IMG SRC="/site/logo">)
I'm a bit worried that this will tend to break acquisition behavior in general. For these types of problem, I'd tend to just specify the absolute URL in the reference. Deals with the problem without having to change acquisition.
I don't think it would break anything. Basically, you know that the identical Image object is available at this other place, so you're just precalculating the acquisition. Instead of telling the browser that the image is at B when it's really at A, and then having a fetch of it at B acquire the version at A, the Image object just short-circuits this and tells the browser that it's at A to begin with. The change would be local to the Image product and wouldn't affect the Acquisition machinery at all. Then again, I haven't tried it yet, so maybe I'm missing something. And I'd better get back to work before you come over here and beat me up :^)
Hi Ty (Ty Sarna), in <199812072251.QAA26012@fezzik.endicor.com> on Dec 7 you wrote:
I don't think it would break anything. Basically, you know that the
Dirtbiker's credo: Never precede any maneuver by a comment more predictive than "Watch this!"
Then again, I haven't tried it yet, so maybe I'm missing something. And I'd better get back to work before you come over here and beat me up :^)
Violence. Pssha. Who needs violence when you have ... ummm what was that bit of info I had on you??? Kent
At 04:51 PM 12/7/98 -0600, Ty Sarna wrote:
Kent Polk wrote:
The __str__ method on images really needs to figure out the true absolute path of the object and use that. (like <IMG SRC="/site/logo">)
I'm a bit worried that this will tend to break acquisition behavior in general. For these types of problem, I'd tend to just specify the absolute URL in the reference. Deals with the problem without having to change acquisition.
I don't think it would break anything. Basically, you know that the identical Image object is available at this other place, so you're just precalculating the acquisition. Instead of telling the browser that the image is at B when it's really at A, and then having a fetch of it at B acquire the version at A, the Image object just short-circuits this and tells the browser that it's at A to begin with. The change would be local to the Image product and wouldn't affect the Acquisition machinery at all.
Then again, I haven't tried it yet, so maybe I'm missing something. And I'd better get back to work before you come over here and beat me up :^)
My ImageFile class for ASDF has a __repr__ method that returns a (more-or-less) absolute URL, and it doesn't break anything, acquisition-wise. I wouldn't worry about it breaking in ZOPE. I define __str__ roughly the same way as in ZOPE (i.e., <IMG SRC="id">), but have __repr__ just return the URL. This makes it easy to do <IMG SRC="<!--#var "`image`"-->" WIDTH=...> stuff.
Phillip J. Eby wrote:
My ImageFile class for ASDF has a __repr__ method that returns a (more-or-less) absolute URL, and it doesn't break anything, acquisition-wise. I wouldn't worry about it breaking in ZOPE. I define __str__ roughly the same way as in ZOPE (i.e., <IMG SRC="id">), but have __repr__ just return the URL. This makes it easy to do <IMG SRC="<!--#var "`image`"-->" WIDTH=...> stuff.
Cool! Do you mind revealing your technique for getting the URL?
At 08:58 PM 12/7/98 -0600, Ty Sarna wrote:
Phillip J. Eby wrote:
My ImageFile class for ASDF has a __repr__ method that returns a (more-or-less) absolute URL, and it doesn't break anything, acquisition-wise. I wouldn't worry about it breaking in ZOPE. I define __str__ roughly the same way as in ZOPE (i.e., <IMG SRC="id">), but have __repr__ just return the URL. This makes it easy to do <IMG SRC="<!--#var "`image`"-->" WIDTH=...> stuff.
Cool! Do you mind revealing your technique for getting the URL?
I don't mind, but it won't help you unless you're developing in ASDF, and since I haven't released the source yet... :) Seriously, there is a relatively easy way to build up an absolute URL for Zope objects (or at least, this used to work in Principia). So let me give you that instead. :) theObject = self myURL = theObject.id while hasattr(theObject,'aq_parent') and hasattr(theObject.aq_parent,'id'): theObject=theObject.aq_parent myURL = "%s/%s" % (theObject.id,myURL) Adding on the appropriate REQUEST.BASEx, etc. is left as an exercise for the reader. :)
participants (3)
-
kent@eaenki.nde.swri.edu -
Phillip J. Eby -
Ty Sarna