Advertisement
cogs

thumbnailarray.py

Feb 5th, 2012
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.73 KB | None | 0 0
  1. ## thumbnailarray.py
  2. ##
  3. ## coded by cogs [cogs@springlessclock.com]
  4. ## 2012.02.05
  5. ## This is just meant as an example of the different options
  6. ## available for resizing images in python.
  7. ## Calling this from the command line;
  8. ## >> python thumbnailarray.py [-w WIDTH] [-h HEIGHT] [-o OUTFILE] INFILE
  9. ## If you only pass in one of width or height then the image will be
  10. ## resized and try to maintain the aspect ratio, if neither is passed
  11. ## it will default to a height of 100px.
  12. ##
  13. ## Though this was originally written as a way to see how each algorithm
  14. ## would produce a thumbnail, it can be used to test whatever, up-scaling,
  15. ## down-scaling... that's about it. Feel free to use this or hack apart parts
  16. ## you want, I've included notes in the appropriate functions for where I
  17. ## found different algorithms.
  18. ##
  19. ## This is able to grab an image from a url, as well as from your
  20. ## file system, and save to a file you specify. If no file is specified,
  21. ## it will use the original file name for the base file. Don't worry, it will
  22. ## not overwrite the original file, it appends a string for each resize
  23. ## example. Use --help if you need more info; there's not a whole lot to it.
  24. ## This is set up to take only one image for simplicity's sake, but if you need
  25. ## bulk processing you should probably just cannibalize what you need, anyhow.
  26. ##
  27. ## PACKAGES YOU'LL NEED:
  28. ## - numpy : http://numpy.scipy.org/
  29. ## - PIL   : http://www.pythonware.com/products/pil/
  30. ##
  31. ## This was written on python 2.7, it has not been tested for anything else.
  32. ##
  33. ## Happy coding! -cogs
  34.  
  35. import numpy, Image, ImageFile, os, urllib2, argparse, sys
  36. from urlparse import urlparse
  37.  
  38. def getImg(filename):
  39.     """
  40.    This function will retrive the image at the specified file
  41.    name. It has some minor checking to see if it is on the
  42.    internet, and will read it via urllib2, but otherwise
  43.    assumes it is local. This returns a tuple, containing
  44.    the (image, path_to_file, filename). If this is a
  45.    url, the path_to_file will be an empty string.
  46.    """
  47.     loc = urlparse(filename)
  48.     if loc.scheme == '':
  49.         # the file is assumed to be local
  50.         fpath,fname = os.path.split(filename)
  51.         try:
  52.             return Image.open(filename),fpath,fname
  53.         except IOError:
  54.             print "Unable to open file %s" % filename
  55.             return False,fpath,fname
  56.     else:
  57.         # the file is assumed to be online
  58.         try:
  59.             _,fname = os.path.split(loc.path)
  60.             instr = urllib2.urlopen(filename)
  61.             parser = ImageFile.Parser()
  62.             parser.feed(instr.read())
  63.             img = parser.close()
  64.             return img,'',fname
  65.         except:
  66.             print "Unable to retrieve file %f" % filename
  67.             return False,'',''
  68.  
  69. def premult(img):
  70.     """
  71.    Credit for this function goes to madlag on stackoverflow,
  72.    as found here:
  73.    http://stackoverflow.com/a/6882161/1189554
  74.    """
  75.     im = img.convert('RGBA')
  76.     premult = numpy.fromstring(im.tostring(), dtype=numpy.uint8)
  77.     alphaLayer = premult[3::4] / 255.0 # gets the alpha channel
  78.     premult[::4]  *= alphaLayer
  79.     premult[1::4] *= alphaLayer
  80.     premult[2::4] *= alphaLayer
  81.     return Image.fromstring('RGBA', im.size, premult.tostring())
  82.  
  83. def resize(img,size,resamp):
  84.     """
  85.    Just calls the resize method in the PIL library with the
  86.    provided resampling type
  87.    """
  88.     return img.resize(size,resamp)
  89.  
  90. def noalpha(img,size,resamp):
  91.     """
  92.    This removes the alpha channel from the image then resizes
  93.    it.
  94.    """
  95.     newimg = img.convert('RGB')
  96.     return resize(newimg,size,resamp)
  97.  
  98. def doubleresize(img,size,resamp):
  99.     """
  100.    This method was suggested here:
  101.    http://united-coders.com/christian-harms/image-resizing-tips-general-and-for-python
  102.    And involves resizing to double your final size, first with
  103.    the fastest algorithm you have (nearest neighbor, usually)
  104.    and then down using the best algorithm you have. Here
  105.    "resamp" is the final algorithm used.
  106.    """
  107.     doublesize = (size[0] * 2,size[1] * 2)
  108.     newimg = img.resize(doublesize)
  109.     return resize(newimg,size,resamp)
  110.    
  111. def premultresize(img,size,resamp):
  112.     """
  113.    This is just to help out and make the main method more readable;
  114.    will call the premult method then the resize method with the
  115.    appropriate resampling type
  116.    """
  117.     newimg = premult(img)
  118.     return resize(newimg,size,resamp)
  119.  
  120. def resizearray(filename, size, outfile = None):
  121.     """
  122.    resizeimg will call each of the resize functions and
  123.    save the result.
  124.    """
  125.     img,fpath,fname = getImg(filename)
  126.  
  127.     if outfile is not None:
  128.         fpath, oname = os.path.split(outfile)
  129.         if oname != '.' and oname != '':
  130.             fname = oname
  131.  
  132.     if not img:
  133.         return
  134.  
  135.     width, height = size
  136.     if width is None and height is None:
  137.         height = 100
  138.  
  139.     # do some basic calculation to find what the missing side,
  140.     # if any, should be
  141.     origwidth, origheight = img.size
  142.     if width is None and height is not None:
  143.         width = int(origwidth * (height / float(origheight)))
  144.     elif height is None and width is not None:
  145.         height = int(origheight * (width / float(origwidth)))
  146.     newsize = (width, height)
  147.  
  148.     # this covers all of the standard resize interpolations
  149.     # supported by PIL, as well as two extra that were
  150.     # suggested. The tuples are in the order:
  151.     # 1. Name to be prepended to the output file
  152.     # 2. Function to call. Function should have the
  153.     #    signature: Image func(Image, (height,width), Image.ENUM)
  154.     # 3. One of the enumerated resampling algorithms. Options are:
  155.     #    Image. NEAREST, BILINEAR, BICUBIC, ANTIALIAS
  156.     rearray = [
  157.         ('NEAREST',   resize,        Image.NEAREST),
  158.         ('BILINEAR',  resize,        Image.BILINEAR),
  159.         ('BICUBIC',   resize,        Image.BICUBIC),
  160.         ('ANTIALIAS', resize,        Image.ANTIALIAS),
  161.         ('DOUBLE',    doubleresize,  Image.ANTIALIAS),
  162.         ('PREMULT',   premultresize, Image.ANTIALIAS),
  163.         ('NOALPHA',   noalpha,       Image.ANTIALIAS),
  164.         ]
  165.     for sampletype, funct, resamp in rearray:
  166.         newimg = funct(img,newsize,resamp)
  167.         saveloc = os.path.join(fpath,sampletype + '_' + fname)
  168.         try:
  169.             newimg.save('%s' % saveloc)
  170.         except:
  171.             print 'Unable to save %(path)s%(type)s_%(fname)s' % {
  172.                     'path':  fpath + os.sep,
  173.                     'type':  sampletype,
  174.                     'fname': fname}
  175.  
  176.  
  177. def main(*args):
  178.     parser = argparse.ArgumentParser(description="Create thumbnails of a file")
  179.     parser.add_argument('filename', metavar='F', type=str, nargs=1,
  180.                            help='The filename to parse')
  181.     parser.add_argument('-W','--width', dest='width', metavar='W', type=int,
  182.                            default=None, action='store',
  183.                            help='The desired width of the thumbnail')
  184.     parser.add_argument('-H','--height', dest='height', metavar='H', type=int,
  185.                            default=None, action='store',
  186.                            help='The desired height of the thumbnail')
  187.     parser.add_argument('-o','--outfile', dest='outfile', metavar='O', type=str,
  188.                            default=None, action='store',
  189.                            help='The base filename to write to')
  190.     parsed = parser.parse_args()
  191.     try:
  192.         size = (parsed.width, parsed.height)
  193.         oname = parsed.outfile
  194.         fname = parsed.filename
  195.         for readfile in fname:
  196.             resizearray(readfile,size,oname)
  197.     except:
  198.         print "Something went wrong"
  199.         return 1
  200.     else:
  201.         return 0
  202.  
  203. if __name__ == "__main__":
  204.     sys.exit(main(*sys.argv))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement