[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/OFS/Image - Image.py:1.1.2.1 ImageData.py:1.1.2.1 ImageEdit.py:1.1.2.1 __init__.py:1.1.2.1 edit.pt:1.1.2.1

Stephan Richter srichter@cbu.edu
Sat, 19 Jan 2002 23:57:33 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/App/OFS/Image
In directory cvs.zope.org:/tmp/cvs-serv30501/Image

Added Files:
      Tag: Zope-3x-branch
	Image.py ImageData.py ImageEdit.py __init__.py edit.pt 
Log Message:
- Restructuring the directory structure in Zope.App.OFS
- Added a simple Image support including two views

NOTE: The ImageData.tag() method does not work yet, since absolute_url is 
      not implemented yet.


=== Added File Zope3/lib/python/Zope/App/OFS/Image/Image.py ===
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
# FOR A PARTICULAR PURPOSE.


import struct

from Zope.App.OFS.File.NaiveFile import INaiveFile, NaiveFile
from Zope.App.Security.IAttributeRolePermissionManageable \
     import IAttributeRolePermissionManageable


class IImage(INaiveFile):
    """This interface defines an Image that can be displayed.
    """

    def getSize():
        """Return a tuple (x, y) that describes the dimensions of
           the object.
        """
    


_RAISE_KEYERROR = []


class Image(NaiveFile):
    """ """

    __implements__ = IImage


    def __init__(self, data=None):
        """ """
        self._contentType, self._width, self._height = getImageInfo(data)
        self._data = data


    def edit(self, data, contentType=None):
        """See interface INaiveFile

           Note: It ignores the content type!
        """
        
        contentType, self._width, self._height = getImageInfo(data)
        if contentType:
            self._contentType = contentType
        self._data = data
        

    ############################################################
    # Implementation methods for interface
    # Zope.App.OFS.Image.IImage

    def getSize(self):
        '''See interface IImage'''

        return (self._width, self._height)

    #
    ############################################################
    


def getImageInfo(data):
    """ """
    
    data = str(data)
    size = len(data)
    height = -1
    width = -1
    content_type = ''

    # handle GIFs   
    if (size >= 10) and data[:6] in ('GIF87a', 'GIF89a'):
        # Check to see if content_type is correct
        content_type = 'image/gif'
        w, h = struct.unpack("<HH", data[6:10])
        width = int(w)
        height = int(h)

    # See PNG v1.2 spec (http://www.cdrom.com/pub/png/spec/)
    # Bytes 0-7 are below, 4-byte chunk length, then 'IHDR'
    # and finally the 4-byte width, height
    elif ((size >= 24) and (data[:8] == '\211PNG\r\n\032\n')
          and (data[12:16] == 'IHDR')):
        content_type = 'image/png'
        w, h = struct.unpack(">LL", data[16:24])
        width = int(w)
        height = int(h)
            
    # Maybe this is for an older PNG version.
    elif (size >= 16) and (data[:8] == '\211PNG\r\n\032\n'):
        # Check to see if we have the right content type
        content_type = 'image/png'
        w, h = struct.unpack(">LL", data[8:16])
        width = int(w)
        height = int(h)

    # handle JPEGs
    elif (size >= 2) and (data[:2] == '\377\330'):
        content_type = 'image/jpeg'
        jpeg = StringIO(data)
        jpeg.read(2)
        b = jpeg.read(1)
        try:
            while (b and ord(b) != 0xDA):
                while (ord(b) != 0xFF): b = jpeg.read(1)
                while (ord(b) == 0xFF): b = jpeg.read(1)
                if (ord(b) >= 0xC0 and ord(b) <= 0xC3):
                    jpeg.read(3)
                    h, w = struct.unpack(">HH", jpeg.read(4))
                    break
                else:
                    jpeg.read(int(struct.unpack(">H", jpeg.read(2))[0])-2)
                b = jpeg.read(1)
            width = int(w)
            height = int(h)
        except: pass

    return content_type, width, height


=== Added File Zope3/lib/python/Zope/App/OFS/Image/ImageData.py ===
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
# FOR A PARTICULAR PURPOSE.

"""
    Define view component for naive file editing.
"""

import string
from Zope.Publisher.Browser.AttributePublisher import AttributePublisher
from Zope.PageTemplate.PageTemplateFile import PageTemplateFile

class ImageData(AttributePublisher):

    __implements__ = AttributePublisher.__implements__
    
    def __init__( self, image ):
        self._image = image


    def index(self, REQUEST=None):        
        image = self.getContext()
        if REQUEST is not None:
            REQUEST['RESPONSE'].setHeader('content-type', image.getContentType()) 
        return image.getData()


    def tag(self, height=None, width=None, alt=None,
            scale=0, xscale=0, yscale=0, css_class=None, **args):
        """
        Generate an HTML IMG tag for this image, with customization.
        Arguments to self.tag() can be any valid attributes of an IMG tag.
        'src' will always be an absolute pathname, to prevent redundant
        downloading of images. Defaults are applied intelligently for
        'height', 'width', and 'alt'. If specified, the 'scale', 'xscale',
        and 'yscale' keyword arguments will be used to automatically adjust
        the output height and width values of the image tag.

        Since 'class' is a Python reserved word, it cannot be passed in
        directly in keyword arguments which is a problem if you are
        trying to use 'tag()' to include a CSS class. The tag() method
        will accept a 'css_class' argument that will be converted to
        'class' in the output tag to work around this.
        """
        if width is None:
            width=self.getContext().getSize()[0]
        if height is None:
            height = self.getContext().getSize()[0]

        # Auto-scaling support
        xdelta = xscale or scale
        ydelta = yscale or scale

        if xdelta and width:
            width = str(int(round(int(width) * xdelta)))
        if ydelta and height:
            height = str(int(round(int(height) * ydelta)))

        result='<img src="%s"' % (self.absolute_url())

        if alt is None:
            alt=getattr(self, 'title', '')
        result = '%s alt="%s"' % (result, alt)

        if height is not None:
            result = '%s height="%s"' % (result, height)

        if width is not None:
            result = '%s width="%s"' % (result, width)

        if not 'border' in map(string.lower, args.keys()):
            result = '%s border="0"' % result

        if css_class is not None:
            result = '%s class="%s"' % (result, css_class)

        for key in args.keys():
            value = args.get(key)
            result = '%s %s="%s"' % (result, key, value)

        return '%s />' % result


    def getContext(self):
        return self._image


=== Added File Zope3/lib/python/Zope/App/OFS/Image/ImageEdit.py ===
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
# FOR A PARTICULAR PURPOSE.

"""
    Define view component for image editing.
"""

from Zope.Publisher.Browser.AttributePublisher import AttributePublisher
from Zope.PageTemplate.PageTemplateFile import PageTemplateFile

class ImageEdit(AttributePublisher):

    __implements__ = AttributePublisher.__implements__
    
    def __init__( self, image ):
        self._image = image


    def editAction(self, data, contentType, REQUEST=None):

        image = self.getContext()

        if contentType != image.getContentType():
            image.setContentType(contentType)

        if data:
            image.edit(data.read())

        if REQUEST is not None:
            return self.index(REQUEST, msg='Image Edited.')


    def getContext( self ):
        return self._image


    index = PageTemplateFile('www/image_edit.pt')





=== Added File Zope3/lib/python/Zope/App/OFS/Image/__init__.py ===


=== Added File Zope3/lib/python/Zope/App/OFS/Image/edit.pt ===
<html metal:use-macro="views/standard_macros/page">
  <head>
    <style metal:fill-slot="headers" type="text/css">
      <!--
      .ContentIcon {
	  width: 20px;
      }
      
      .ContentTitle {
	  text-align: left;
      }
      -->
    </style>
  </head>

  <body>
    <div metal:fill-slot="body">

 
      <p tal:content="options/msg | nothing">
        Message will go here.
      </p>

      <form action="editAction" method="post" enctype="multipart/form-data">

        <table class="EditTable">      
	  <tbody>   
  
	    <tr>
	      <th class="EditAttributeName">Content-Type</th>
	      <td class="EditAttributeValue">
        	<input type="text" name="contentType"
        	  tal:attributes="value here/getContentType" />
              </td>
	    </tr>

	    <tr>
	      <th class="EditAttributeName">Size</th>
	      <td class="EditAttributeValue"
          	  tal:content="here/getSize">
              </td>
	    </tr>
  
	    <tr>
	      <th class="EditAttributeName">Data</th>
	      <td class="EditAttributeValue">
        	<input type="file" name="data"
        	  tal:attributes="value string:Select a File" />
              </td>
	    </tr>      
  
	  </tbody>     
      </table>

      <input type="submit" name="edit" value="Save Changes">

      </form> 

    </div>
  </body>
</html>