If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

Model:

db.define_table('uploads',
    Field('name','string'),
    Field('mainfile','upload'),
    Field('thumb','upload',writable=False,readable=False),
    )

Controller:

def makeThumbnail(dbtable,ImageID,size=(150,150)):
    try:    
        thisImage=db(dbtable.id==ImageID).select()[0]
        import os, uuid
        from PIL import Image
    except: return
    im=Image.open(request.folder + 'uploads/' + thisImage.mainfile)
    im.thumbnail(size,Image.ANTIALIAS)
    thumbName='uploads.thumb.%s.jpg' % (uuid.uuid4())
    im.save(request.folder + 'uploads/' + thumbName,'jpeg')
    thisImage.update_record(thumb=thumbName)
    return 

def uploadimage():
    dbtable = db.uploads          #uploads table name
    if len(request.args):
        records = db(dbtable.id==request.args[0]).select()
    if len(request.args) and len(records):
        form = SQLFORM(dbtable, records[0], deletable=True)
    else:
        form = SQLFORM(dbtable)
    if form.accepts(request.vars, session): 
        response.flash = 'form accepted'
        makeThumbnail(dbtable,form.vars.id,(175,175))
    elif form.errors:
        response.flash = 'form has errors'
    ## Quick list just to demonstrate...
    list = crud.select(dbtable)
    return dict(form=form,list=list)

(I am grateful to Lukasz (aka ls1) for his kind assistance).

Related slices

Comments (11)

  • Login to post



  • 0
    gheither 11 years ago

    This slice used to work for me about a year ago, now it's not after I upgraded my web2py.  Can anyone get this working with the latest web2py build?

    It creates the thumbnail successfully and stores it in the uploads folder, but when you try to retrieve the thumbnail through the URL bar or the DB admin screen you get a ticket.

    <type 'exceptions.TypeError'> Can't retrieve uploads.thumb.16e0d9fd-bc66-4b36-9c75-03aaea1d8603.PNG

    Please help!


  • 0
    eanappi 11 years ago
    I did what I explained and it worked perfect. But when uploading in Amazon EC2 does not work.
     
    There are dependencies to use this module?
    replies (1)
    • villas 11 years ago

      Of course, as noted you need PIL to be installed. Check filesystem permissions of the folder that your python/webserver can write files. BTW I like the code by simpel in the comments.


  • 0
    write2ariya 12 years ago

    Dear David

     

    This is very useful. I use you code in my project. Thank you for your contribution & sharing.

    (just wanna thanks, I will payback web2py community someway)

    Ariya


  • 0
    simpel 14 years ago
    You can do also:
    
    
    class RESIZE(object): 
        def __init__(self,nx=160,ny=80,error_message='niepoprawny plik'): 
            (self.nx,self.ny,self.error_message)=(nx,ny,error_message) 
        def __call__(self,value):
            if isinstance(value, str) and len(value)==0: 
                return (value,None) 
            from PIL import Image 
            import cStringIO 
            try: 
                img = Image.open(value.file) 
                img.thumbnail((self.nx,self.ny), Image.ANTIALIAS) 
                s = cStringIO.StringIO() 
                img.save(s, 'JPEG', quality=100) 
                s.seek(0) 
                value.file = s 
            except: 
                return (value, self.error_message) 
            else: 
                return (value, None)
                
    def THUMB(image, nx=120, ny=120):
        from PIL import Image 
        import os  
        img = Image.open(request.folder + 'uploads/' + image)
        img.thumbnail((nx,ny), Image.ANTIALIAS) 
        root,ext = os.path.splitext(image)
        thumb='%s_thumb%s' %(root, ext)
        img.save(request.folder + 'uploads/' + thumb)
        return thumb
    
    
    db.define_table('gallery',
        Field('image', 'upload', required=True, notnull=True, requires=[IS_IMAGE(), RESIZE(650, 650)]),
        Field('image_thumb', 'upload', compute=lambda r: THUMB(r['image'])))
    
    
    
    Why can't I edit my own comment? Can somebody delete my first comment? Thanks

  • 0
    mrfreeze 14 years ago
    I deleted it and will add comment editing. I thought previewing would be enough.

  • 0
    mrfreeze 14 years ago
    Done! The only rule is that you have to be the author of the last comment. Thanks.

  • 0
    simpel 14 years ago
    Great :) Thanks

  • 0
    rppowell 14 years ago
    just wanted to add that the thumbnail image name matters (at least in the current version of web2py). I ended up with this code:
    
    def makeThumbnail(img_name,size=(150,150)):
        try:    
            import os
            from PIL import Image
        except: 
            return
        im=Image.open(request.folder + 'uploads/' + img_name)
        im.thumbnail(size,Image.ANTIALIAS)
        root,ext = os.path.splitext(img_name)
        thumbName='%s_thumb%s' %(root, ext)
        im.save(request.folder + 'uploads/' + thumbName)
        return thumbName
    
    def add():
        form = SQLFORM(db.Item)
        if form.accepts(request.vars, session):
            response.flash = "Item Added"
            row = db(db.Item.id==form.vars.id).select()[0]
            img_name=row.image
            thumb = makeThumbnail(img_name)
            if thumb: row.update_record(image_thumb=thumb)
        elif form.errors:
            response.flash = "Form has errors"
        return dict(form=form)
    
    Does the thumbnail really need a UUID that is not related to the original image?

  • 0
    rppowell 14 years ago
    I guess I should put back in the original error checking!

  • 0
    villas 14 years ago
    The validator is good for transforming a field, but at the end you just have one image/field. In the case of this slice I wanted to automatically create a thumbnail from an upload which would result in having two files/fields. I think the use case is therefore different. However, it is still good to know this RESIZE validator. Thanks.

  • 0
    sherdim 14 years ago
    This solution supposes initial keeping of the uploaded BIG image. I am not a specialist in the webserver memory utilization, but a solution with validator RESIZE, which called on any upload to the given field is more straightforward IMHO. Such solution was published in the web2py group about a year ago. It utilizes PIL also and cStringIO as a temporal buffer. The same approach was for automarking images with the site logo. Place a module with validator in module folder. ================ __all__ = [ 'RESIZE', ] class RESIZE(object): """ Resize image such as thumbnail """ def __init__(self,nx=160,ny=80,error_message='image resize error'): (self.nx,self.ny,self.error_message)=(nx,ny,error_message) def __call__(self,value): if isinstance(value, str) and len(value)==0: return (value,None) from PIL import Image import cStringIO try: #load im=Image.open(value.file) #resize im.thumbnail((self.nx,self.ny),Image.ANTIALIAS) #by hand s=cStringIO.StringIO() im.save(s,'JPEG',quality=86) s.seek(0) value.file=s except: return (value,self.error_message) else: return (value,None) =========== Vale!

Hosting graciously provided by:
Python Anywhere