Mailing List Archive

- 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>
Re: - Image object enhancements (patch included!) [ In reply to ]
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 :^)
Re: - Image object enhancements (patch included!) [ In reply to ]
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
Re: - Image object enhancements (patch included!) [ In reply to ]
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
Re: - Image object enhancements (patch included!) [ In reply to ]
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.
Re: - Image object enhancements (patch included!) [ In reply to ]
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?
Re: - Image object enhancements (patch included!) [ In reply to ]
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. :)