home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 June / maximum-cd-2009-06.iso / DiscContents / digsby_setup.exe / lib / gui / toolbox / imagefx.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-02-26  |  15.3 KB  |  421 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. DISABLE_ALL_CACHING = False
  5. NUM_IMAGES_TO_CACHE = 80
  6. from util import try_this
  7. from util.lrucache import LRU
  8. import wx
  9. from wx import ImageFromDataWithAlpha, BitmapFromImage, Bitmap, BitmapFromIcon, ImageFromBitmap, IMAGE_QUALITY_HIGH, Point
  10. from PIL import Image, ImageDraw, ImageFilter, ImageMath, ImageOps, ImageEnhance
  11. from PIL.Image import BICUBIC, ANTIALIAS
  12. from functools import wraps
  13. from uuid import uuid1
  14. imagecache = LRU(NUM_IMAGES_TO_CACHE)
  15. CORNERS = (('tl', None), ('tr', Image.ROTATE_270), ('bl', Image.FLIP_TOP_BOTTOM), ('br', Image.ROTATE_180))
  16.  
  17. def cacheing(func):
  18.     name = func.__name__
  19.     
  20.     def wrapper(img, *a):
  21.         
  22.         try:
  23.             cachekey = img.cachekey
  24.         except AttributeError:
  25.             
  26.             try:
  27.                 cachekey = (img.path,)
  28.             except AttributeError:
  29.                 img.path = str(uuid1())
  30.                 cachekey = (img.path,)
  31.             except:
  32.                 None<EXCEPTION MATCH>AttributeError
  33.             
  34.  
  35.             None<EXCEPTION MATCH>AttributeError
  36.  
  37.         key = cachekey + (name + repr(a),)
  38.         
  39.         try:
  40.             return imagecache[key]
  41.         except KeyError:
  42.             img = func(img, *a)
  43.             img.cachekey = key
  44.             imagecache[key] = img
  45.             return img
  46.  
  47.  
  48.     wrapper = (None, wraps(func))(wrapper)
  49.     return wrapper
  50.  
  51. if DISABLE_ALL_CACHING:
  52.     import sys
  53.     print >>sys.stderr, 'WARNING: image caching is disabled'
  54.     objmemoize = refmemoize = cacheing = (lambda f: f)
  55. else:
  56.     refmemoize = objmemoize = cacheing
  57.  
  58. def wxbitmap_to_wximage(wxbitmap):
  59.     return wxbitmap.ConvertToImage()
  60.  
  61. wxbitmap_to_wximage = cacheing(wxbitmap_to_wximage)
  62.  
  63. def wxbitmap_to_pil(wxbitmap):
  64.     return wximage_to_pil(wxbitmap_to_wximage(wxbitmap))
  65.  
  66. wxbitmap_to_pil = refmemoize(wxbitmap_to_pil)
  67.  
  68. def wxicon_to_pil(wxicon):
  69.     return wxbitmap_to_pil(BitmapFromIcon(wxicon))
  70.  
  71. wxicon_to_pil = cacheing(wxicon_to_pil)
  72.  
  73. def wxicon_to_bitmap(wxicon):
  74.     return BitmapFromIcon(wxicon)
  75.  
  76. wxicon_to_bitmap = cacheing(wxicon_to_bitmap)
  77.  
  78. def wximage_to_pil(wximage):
  79.     size = (wximage.Width, wximage.Height)
  80.     img = Image.new('RGB', size)
  81.     img.fromstring(wximage.Data)
  82.     (r, g, b) = img.split()
  83.     if wximage.HasAlpha() or wximage.HasMask():
  84.         a = Image.new('L', wximage.GetSize())
  85.         if wximage.HasMask():
  86.             if not wximage.HasAlpha():
  87.                 wximage.InitAlpha()
  88.             
  89.         
  90.         if wximage.HasAlpha():
  91.             a.fromstring(wximage.AlphaData)
  92.         
  93.         img = Image.merge('RGBA', (r, g, b, a))
  94.     else:
  95.         img = Image.merge('RGB', (r, g, b))
  96.     return img
  97.  
  98. wximage_to_pil = refmemoize(wximage_to_pil)
  99.  
  100. def wximage_to_wxbitmap(wximage, depth = 32):
  101.     return BitmapFromImage(wximage)
  102.  
  103.  
  104. def pil_to_wxbitmap(pilimg):
  105.     return wximage_to_wxbitmap(pil_to_wximage(pilimg), 32)
  106.  
  107. pil_to_wxbitmap = objmemoize(pil_to_wxbitmap)
  108.  
  109. def pil_to_wximage(pilimg):
  110.     pilimage = None if pilimg.mode == 'RGBA' else pilimg.convert('RGBA')
  111.     (w, h) = pilimg.size
  112.     rgb = pilimage.tostring('raw', 'RGB')
  113.     alpha = pilimage.tostring('raw', 'A')
  114.     return ImageFromDataWithAlpha(w, h, rgb, alpha)
  115.  
  116. pil_to_wximage = objmemoize(pil_to_wximage)
  117.  
  118. def wxbitmap_inverted(wxbitmap):
  119.     return ImageOps.invert(pilimg_convert(wxbitmap.PIL, 'RGB')).WXB
  120.  
  121. wxbitmap_inverted = cacheing(wxbitmap_inverted)
  122.  
  123. def has_transparency(i):
  124.     return any(i.histogram()[768:1024])
  125.  
  126.  
  127. def pil_to_white_gif(i):
  128.     bg = Image.new('RGBA', i.size, (255, 255, 255, 255))
  129.     bg.paste(i, i)
  130.     return pil_to_gif(bg)
  131.  
  132.  
  133. def pil_to_gif(i):
  134.     import cStringIO
  135.     s = cStringIO.StringIO()
  136.     (r, g, b, a) = i.split()
  137.     rgb = Image.merge('RGB', (r, g, b))
  138.     rgb = rgb.convert('P', palette = Image.ADAPTIVE, colors = 255, dither = Image.NONE)
  139.     pal = rgb.getpalette()
  140.     if len(pal) < 768:
  141.         r1 = pal[::3]
  142.         g1 = pal[1::3]
  143.         b1 = pal[2::3]
  144.         rv = (set(xrange(256)) - set(r1)).pop()
  145.         gv = (set(xrange(256)) - set(g1)).pop()
  146.         bv = (set(xrange(256)) - set(b1)).pop()
  147.         pal[-3:] = [
  148.             rv,
  149.             gv,
  150.             bv]
  151.         rgb.putpalette(pal, rawmode = 'RGB')
  152.         a2 = a.point((lambda p: None if p >= 128 else 255))
  153.         rgb.paste(255, (0, 0), a2)
  154.         rgb.save(s, 'GIF', transparency = 255, interlace = False)
  155.     else:
  156.         rgb.putpalette(pal, rawmode = 'RGB')
  157.         rgb.save(s, 'GIF', interlace = False)
  158.     return s.getvalue()
  159.  
  160.  
  161. def wxbitmap_resizedwh(wxbitmap, w, h):
  162.     return pil_to_wxbitmap(pilimg_resizedwh(wximage_to_pil(wxbitmap_to_wximage(wxbitmap)), w, h))
  163.  
  164. wxbitmap_resizedwh = refmemoize(wxbitmap_resizedwh)
  165.  
  166. def wxbitmap_resized(wxbitmap, size):
  167.     
  168.     try:
  169.         (w, h) = size
  170.     except TypeError:
  171.         return wxbitmap_in_square(wxbitmap, size)
  172.  
  173.     return wxbitmap_resizedwh(wxbitmap, w, h)
  174.  
  175. wxbitmap_resized = refmemoize(wxbitmap_resized)
  176.  
  177. def wxbitmap_resized_smaller(wxbitmap, size):
  178.     if max(wxbitmap.Width, wxbitmap.Height) > size:
  179.         return wxbitmap.Resized(size)
  180.     else:
  181.         return wxbitmap
  182.  
  183.  
  184. def pil_resized_smaller(pil, size):
  185.     return None if max(pil.size) > size else pil
  186.  
  187.  
  188. def pilimg_resized(pilimg, size):
  189.     
  190.     try:
  191.         (w, h) = size
  192.     except TypeError:
  193.         return pilimg_in_square(pilimg, size)
  194.  
  195.     return pilimg_resizedwh(pilimg, w, h)
  196.  
  197. pilimg_resized = objmemoize(pilimg_resized)
  198.  
  199. def pilimg_convert(pilimg, mode):
  200.     return pilimg.convert(mode)
  201.  
  202. pilimg_convert = objmemoize(pilimg_convert)
  203.  
  204. def pilimg_resizedwh(pilimg, w, h):
  205.     w = None if w == -1 else int(w)
  206.     h = None if h == -1 else int(h)
  207.     size = (w, h)
  208.     if pilimg.mode == 'P':
  209.         pilimg = pilimg_convert(pilimg, 'RGBA')
  210.     
  211.     return None(pilimg.resize, size if min(size) < min(pilimg.size) else Image.BICUBIC)
  212.  
  213. pilimg_resizedwh = objmemoize(pilimg_resizedwh)
  214.  
  215. def pilimg_in_square(img, squaresize):
  216.     (w, h) = img.size
  217.     if img.mode == 'P':
  218.         img = pilimg_convert(img, 'RGBA')
  219.     
  220.     new = Image.new('RGBA', (squaresize, squaresize), (0, 0, 0, 0))
  221.     if w > h:
  222.         new_height = int((h / float(w)) * squaresize)
  223.         img = None(img.resize, (squaresize, new_height) if squaresize > w else ANTIALIAS)
  224.         new.paste(img, (0, (squaresize - new_height) / 2))
  225.     else:
  226.         new_width = int((w / float(h)) * squaresize)
  227.         img = None(img.resize, (new_width, squaresize) if squaresize > h else ANTIALIAS)
  228.         new.paste(img, ((squaresize - new_width) / 2, 0))
  229.     return new
  230.  
  231. pilimg_in_square = objmemoize(pilimg_in_square)
  232.  
  233. def pil_resize_canvas(img, w, h, alignment = wx.ALIGN_CENTER):
  234.     if alignment != wx.ALIGN_CENTER:
  235.         raise NotImplementedError
  236.     
  237.     (ow, oh) = img.size
  238.     new = Image.new('RGBA', (w, h), (0, 0, 0, 0))
  239.     new.paste(img, (w / 2 - ow / 2, w / 2 - oh / 2))
  240.     return new
  241.  
  242. pil_resize_canvas = objmemoize(pil_resize_canvas)
  243.  
  244. def pil_setalpha(img, alpha):
  245.     channels = img.split()
  246.     if len(channels) == 4:
  247.         (r, g, b, a) = channels
  248.     elif len(channels) == 3:
  249.         a = Image.new('L', img.size, 'white')
  250.     else:
  251.         raise AssertionError('Cannot set alpha, image does not have 3 or 4 bands.')
  252.     img.putalpha(ImageEnhance.Brightness(a).enhance(alpha))
  253.  
  254.  
  255. def wxbitmap_in_square(bmp, squaresize, scaleup = True):
  256.     w = bmp.Width
  257.     h = bmp.Height
  258.     if w > squaresize and h > squaresize or scaleup:
  259.         img = ImageFromBitmap(bmp)
  260.         if w > h:
  261.             new_height = int((h / float(w)) * squaresize)
  262.             img = img.Scale(squaresize, new_height, IMAGE_QUALITY_HIGH)
  263.             offset = Point(0, (squaresize - new_height) / 2)
  264.         else:
  265.             new_width = int((w / float(h)) * squaresize)
  266.             img = img.Scale(new_width, squaresize, IMAGE_QUALITY_HIGH)
  267.             offset = Point((squaresize - new_width) / 2, 0)
  268.         return BitmapFromImage(img)
  269.     
  270.     return bmp
  271.  
  272. wxbitmap_in_square = refmemoize(wxbitmap_in_square)
  273.  
  274. def wxbitmap_greyed(bitmap):
  275.     return wximage_to_wxbitmap(wxbitmap_to_wximage(bitmap).ConvertToGreyscale())
  276.  
  277. wxbitmap_greyed = refmemoize(wxbitmap_greyed)
  278.  
  279. def pilimg_greyed(pil):
  280.     pil = pil.copy()
  281.     alpha = 'A' in pil.getbands()
  282.     if alpha:
  283.         (r, g, b, a) = pil.split()
  284.     
  285.     pil = ImageOps.grayscale(pil)
  286.     if alpha:
  287.         pil.putalpha(a)
  288.     
  289.     return pil
  290.  
  291. pilimg_greyed = objmemoize(pilimg_greyed)
  292.  
  293. def drop_shadow(image, offset = (5, 5), background = (0, 0, 0, 0), shadow = 4473924, border = 8, iterations = 3):
  294.     image = image.PIL
  295.     totalWidth = image.size[0] + abs(offset[0]) + 2 * border
  296.     totalHeight = image.size[1] + abs(offset[1]) + 2 * border
  297.     back = Image.new(image.mode, (totalWidth, totalHeight), background)
  298.     shadowLeft = border + max(offset[0], 0)
  299.     shadowTop = border + max(offset[1], 0)
  300.     back.paste(shadow, [
  301.         shadowLeft,
  302.         shadowTop,
  303.         shadowLeft + image.size[0],
  304.         shadowTop + image.size[1]])
  305.     n = 0
  306.     while n < iterations:
  307.         back = back.filter(ImageFilter.BLUR)
  308.         n += 1
  309.     imageLeft = border - min(offset[0], 0)
  310.     imageTop = border - min(offset[1], 0)
  311.     back.paste(image, (imageLeft, imageTop))
  312.     return back
  313.  
  314.  
  315. def pil_combine(imgs, direction = wx.HORIZONTAL, align = wx.ALIGN_CENTER):
  316.     imgs = [ img.PIL for img in imgs ]
  317.     length_idx = [
  318.         wx.HORIZONTAL,
  319.         wx.VERTICAL].index(direction)
  320.     breadth_idx = [] if length_idx else 1
  321.     for img in imgs:
  322.         size = img.size
  323.         length += size[length_idx]
  324.         breadth = max(breadth, size[breadth_idx])
  325.     
  326.     newsize = length = breadth = 0 if direction == wx.HORIZONTAL else (breadth, length)
  327.     newimg = Image.new('RGBA', newsize, (0, 0, 0, 0))
  328.     pos = (0, 0)
  329.     for img in imgs:
  330.         newimg.paste(img, pos)
  331.         if direction == wx.HORIZONTAL:
  332.             pos = (pos[0] + img.size[0], pos[1])
  333.             continue
  334.         []
  335.         pos = (pos[0], pos[1] + img.size[1])
  336.     
  337.     return newimg
  338.  
  339.  
  340. def rounded_corners(corner_size = 1, rounded_imgs = { }):
  341.     if not isinstance(corner_size, int):
  342.         corner_size = (try_this,)((lambda : int(bool(corner_size))), 1)
  343.     else:
  344.         corner_size = max(0, min(corner_size, 3))
  345.     
  346.     try:
  347.         return rounded_imgs[corner_size]
  348.     except KeyError:
  349.         pass
  350.  
  351.     imgs = []
  352.     skin = skin
  353.     import gui
  354.     rounded_img = Image.open(skin.resourcedir() / ('corner' + str(corner_size) + '.gif')).convert('L')
  355.     for name, rotation in CORNERS:
  356.         mask = None if rotation is not None else rounded_img
  357.         imgs.append(mask)
  358.     
  359.     return rounded_imgs.setdefault(corner_size, imgs)
  360.  
  361.  
  362. def rounded_mask(size, cornersize = 1):
  363.     img = Image.new('L', size, 255)
  364.     (w, h) = size
  365.     p = img.paste
  366.     r = rounded_corners(cornersize)
  367.     i = r[0]
  368.     p(i, (0, 0, i.size[0], i.size[1]))
  369.     i = r[1]
  370.     p(i, (w - i.size[0], 0, w, i.size[1]))
  371.     i = r[2]
  372.     p(i, (0, h - i.size[1], i.size[0], h))
  373.     i = r[3]
  374.     p(i, (w - i.size[0], h - i.size[1], w, h))
  375.     return img
  376.  
  377.  
  378. def pilimg_rounded(image, cornersize = 1):
  379.     newimage = image.copy()
  380.     newimage.putalpha(ImageMath.eval('convert(min(a,b), "L")', a = newimage.split()[-1], b = rounded_mask(newimage.size, cornersize)))
  381.     return newimage
  382.  
  383. pilimg_rounded = objmemoize(pilimg_rounded)
  384.  
  385. def wxbitmap_rounded(wxbitmap, cornersize = 1):
  386.     if cornersize == 0:
  387.         return wxbitmap
  388.     else:
  389.         return pil_to_wxbitmap(pilimg_rounded(wximage_to_pil(wxbitmap_to_wximage(wxbitmap)), cornersize))
  390.  
  391. wxbitmap_rounded = refmemoize(wxbitmap_rounded)
  392. Image.Image.Resized = pilimg_resized
  393. Image.Image.ResizedSmaller = pil_resized_smaller
  394. Image.Image.Rounded = pilimg_rounded
  395. Image.Image.WXB = property((lambda pil: pil_to_wxbitmap(pil)))
  396. Image.Image.WX = property((lambda pil: pil_to_wximage(pil)))
  397. Image.Image.Greyed = property(pilimg_greyed)
  398. Image.Image.ResizeCanvas = pil_resize_canvas
  399. Image.Image.PIL = property((lambda pil: pil))
  400. wx.Bitmap.Resized = wxbitmap_resized
  401. wx.Bitmap.ResizedSmaller = wxbitmap_resized_smaller
  402. wx.Bitmap.Greyed = property(wxbitmap_greyed)
  403. wx.Bitmap.Rounded = wxbitmap_rounded
  404. wx.Bitmap.WXB = property((lambda self: self))
  405. wx.Bitmap.WX = property((lambda wxb: wxbitmap_to_wximage(wxb)))
  406. wx.Bitmap.PIL = property((lambda self: wxbitmap_to_pil(self)))
  407. wx.Bitmap.Inverted = property(wxbitmap_inverted)
  408. wx.Image.WX = property((lambda self: self))
  409. wx.Image.WXB = property((lambda self: wximage_to_wxbitmap(self, 32)))
  410. wx.Image.PIL = property((lambda self: wximage_to_pil(self)))
  411. wx.Icon.PIL = property((lambda self: wxicon_to_pil(self)))
  412. wx.Icon.WXB = property((lambda self: wxicon_to_bitmap(self)))
  413. if __name__ == '__main__':
  414.     from tests.testapp import testapp
  415.     from gui.skin import get
  416.     a = testapp('../../..')
  417.     img = Image.new('RGBA', (40, 50), 'red')
  418.     img.Resized(100).Show()
  419.     a.MainLoop()
  420.  
  421.