home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / doc / python-gtk2 / examples / demos / pixbufs.py < prev    next >
Encoding:
Python Source  |  2006-08-09  |  6.3 KB  |  201 lines

  1. #!/usr/bin/env python
  2. '''Pixbufs
  3.  
  4. A GdkPixbuf represents an image, normally in RGB or RGBA format.
  5. Pixbufs are normally used to load files from disk and perform image scaling.
  6. This demo is not all that educational, but looks cool. It was written by
  7. Extreme Pixbuf Hacker Federico Mena Quintero. It also shows off how to use
  8. GtkDrawingArea to do a simple animation.
  9. Look at the Image demo for additional pixbuf usage examples.'''
  10. # pygtk version: Maik Hertha <maik.hertha@berlin.de>
  11.  
  12. import os
  13. import math
  14. import gobject
  15. import gtk
  16.  
  17. FRAME_DELAY = 50
  18. CYCLE_LEN = 60
  19. IMAGE_DIR = os.path.join(os.path.dirname(__file__), 'images')
  20. BACKGROUND_NAME = "background.jpg"
  21.  
  22. image_names = [
  23.     "apple-red.png",
  24.     "gnome-applets.png",
  25.     "gnome-calendar.png",
  26.     "gnome-foot.png",
  27.     "gnome-gmush.png",
  28.     "gnome-gimp.png",
  29.     "gnome-gsame.png",
  30.     "gnu-keys.png"
  31. ]
  32.  
  33. class PixbufsDemo(gtk.Window):
  34.     frame  = None      # frame of the background image
  35.     background = None  # background-pixbuf
  36.     images     = []    # list of pixbufs
  37.     back_width  = 0    # width of background image
  38.     back_height = 0    # height of background image
  39.     timeout_id  = 0    # timeout id
  40.     frame_num   = 0    # number of the current frame
  41.     timeout_id = None
  42.  
  43.     def __init__(self, parent=None):
  44.         gtk.Window.__init__(self)
  45.         try:
  46.             self.set_screen(parent.get_screen())
  47.         except AttributeError:
  48.             self.connect("destroy", lambda *w: gtk.main_quit())
  49.         self.connect("destroy", self.cleanup_callback)
  50.         self.set_title(self.__class__.__name__)
  51.         self.set_resizable(False)
  52.  
  53.         if not self.load_pixbufs():
  54.             dialog = gtk.MessageDialog(self,
  55.                 gtk.DIALOG_DESTROY_WITH_PARENT,
  56.                 gtk.MESSAGE_ERROR,
  57.                 gtk.BUTTONS_CLOSE,
  58.                 "Failed to load an image")
  59.             dialog.connect("response", lambda d, r: d.destroy())
  60.             dialog.show()
  61.  
  62.         else:
  63.             self.set_size_request(self.back_width, self.back_height)
  64.  
  65.             self.frame = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8,
  66.                 self.back_width, self.back_height)
  67.  
  68.             da = gtk.DrawingArea()
  69.             da.connect("expose_event", self.expose_cb)
  70.             self.add(da)
  71.  
  72.             self.timeout_id = gtk.timeout_add(FRAME_DELAY, self.timeout)
  73.  
  74.             self.show_all()
  75.  
  76.     def load_pixbufs(self):
  77.         ''' Loads the images for the demo and returns whether the
  78.             operation succeeded.
  79.         '''
  80.         if self.background is not None:
  81.             return True   # already loaded earlier
  82.  
  83.         # look in the the current directory where the file is installed
  84.         try:
  85.             self.background = gtk.gdk.pixbuf_new_from_file(
  86.                 os.path.join(IMAGE_DIR, BACKGROUND_NAME))
  87.         except gobject.GError, error:
  88.             return False
  89.  
  90.         self.back_width  = self.background.get_width()
  91.         self.back_height = self.background.get_height()
  92.  
  93.         for filename in image_names:
  94.             try:
  95.                 self.images.append(gtk.gdk.pixbuf_new_from_file(
  96.                     os.path.join(IMAGE_DIR, filename)))
  97.             except gobject.GError, error:
  98.                 return False
  99.  
  100.         return True
  101.  
  102.     def expose_cb(self, draw_area, event):
  103.         ''' Expose callback for the drawing area. '''
  104.         rowstride = self.frame.get_rowstride()
  105.  
  106.         # FIXME: what should be the result, string guchar an integer result?
  107.         #pixels = frame.get_pixels() + rowstride * event.area.y + event.area.x * 3
  108.         #pixels = frame.get_pixels()[len(frame.get_pixels()) + rowstride * event.area.y + event.area.x * 3]
  109.         pixels = self.frame.get_pixels()
  110.  
  111.         draw_area.window.draw_rgb_image(
  112.             draw_area.style.black_gc,
  113.             event.area.x, event.area.y,
  114.             event.area.width, event.area.height,
  115.             'normal',
  116.             pixels, rowstride,
  117.             event.area.x, event.area.y)
  118.  
  119.         return True
  120.  
  121.     def cleanup_callback(self, win):
  122.         if self.timeout_id is not None:
  123.             gtk.timeout_remove(self.timeout_id)
  124.             self.timeout_id = None
  125.  
  126.     def timeout(self):
  127.         ''' Timeout handler to regenerate the frame. '''
  128.         self.background.copy_area(0, 0, self.back_width, self.back_height,
  129.             self.frame, 0, 0)
  130.  
  131.         f = float(self.frame_num % CYCLE_LEN) / float(CYCLE_LEN)
  132.  
  133.         xmid = self.back_width / 2.0
  134.         ymid = self.back_height / 2.0
  135.  
  136.         radius = min(xmid, ymid) / 2.0
  137.  
  138.         N_IMAGES = len(image_names)
  139.         for i_name in image_names:
  140.             i = image_names.index(i_name)
  141.  
  142.             ang = 2.0 * math.pi * i / N_IMAGES - f * 2.0 * math.pi
  143.  
  144.             iw = self.images[i].get_width()
  145.             ih = self.images[i].get_height()
  146.  
  147.             r = radius +(radius / 3.0) * math.sin(f * 2.0 * math.pi)
  148.  
  149.             xpos = math.floor(xmid + r * math.cos(ang) - iw / 2.0 + 0.5)
  150.             ypos = math.floor(ymid + r * math.sin(ang) - ih / 2.0 + 0.5)
  151.  
  152.             if i % 2 == 0:
  153.                 k = math.cos(f * 2.0 * math.pi)
  154.             else:
  155.                 k = math.sin(f * 2.0 * math.pi)
  156.             k = 2.0 * k * k
  157.             k = max(0.25, k)
  158.  
  159.             # satisfy the c-source
  160.             r1 = gtk.gdk.Rectangle()
  161.             r1.x = int(xpos)
  162.             r1.y = int(ypos)
  163.             r1.width  = iw * k
  164.             r1.height = ih * k
  165.  
  166.             r2 = gtk.gdk.Rectangle()
  167.             r2.x = 0
  168.             r2.y = 0
  169.             r2.width  = self.back_width
  170.             r2.height = self.back_height
  171.  
  172.             dest = r1.intersect(r2)
  173.             if dest is not None:
  174.                 if i % 2 == 0:
  175.                     alpha = int(
  176.                         max(127, math.fabs(255 * math.cos(f * 2.0 * math.pi))))
  177.                 else:
  178.                     alpha = int(
  179.                         max(127, math.fabs(255 * math.sin(f * 2.0 * math.pi))))
  180.                 self.images[i].composite(
  181.                       self.frame,
  182.                       dest.x, dest.y,
  183.                       dest.width, dest.height,
  184.                       xpos, ypos,
  185.                       k, k,
  186.                       gtk.gdk.INTERP_NEAREST,
  187.                       alpha)
  188.  
  189.         if self is not None:
  190.             self.queue_draw()
  191.  
  192.         self.frame_num += 1
  193.         return True
  194.  
  195. def main():
  196.     PixbufsDemo()
  197.     gtk.main()
  198.  
  199. if __name__ == '__main__':
  200.     main()
  201.