1 /* Pixbufs 2 * 3 * A Pixbuf represents an image, normally in RGB or RGBA format. 4 * Pixbufs are normally used to load files from disk and perform 5 * image scaling. 6 * 7 * This demo is not all that educational, but looks cool. It was written 8 * by Extreme Pixbuf Hacker Federico Mena Quintero. It also shows 9 * off how to use DrawingArea to do a simple animation. 10 * 11 * Look at the Image demo for additional pixbuf usage examples. 12 * 13 */ 14 15 using Gdk; 16 using Gtk; 17 18 using System; 19 using System.Runtime.InteropServices; // for Marshal.Copy 20 21 namespace GtkDemo 22 { 23 [Demo ("Pixbuf", "DemoPixbuf.cs")] 24 public class DemoPixbuf : Gtk.Window 25 { 26 const int FrameDelay = 50; 27 const int CycleLen = 60; 28 const string BackgroundName = "background.jpg"; 29 30 static string[] ImageNames = { 31 "apple-red.png", 32 "gnome-applets.png", 33 "gnome-calendar.png", 34 "gnome-foot.png", 35 "gnome-gmush.png", 36 "gnome-gimp.png", 37 "gnome-gsame.png", 38 "gnu-keys.png" 39 }; 40 41 // background image 42 static Pixbuf background; 43 static int backWidth, backHeight; 44 45 // images 46 static Pixbuf[] images; 47 48 // current frame 49 Pixbuf frame; 50 int frameNum; 51 52 // drawing area 53 DrawingArea drawingArea; 54 55 uint timeoutId; 56 DemoPixbuf()57 static DemoPixbuf () 58 { 59 // Load the images for the demo 60 61 background = Gdk.Pixbuf.LoadFromResource (BackgroundName); 62 63 backWidth = background.Width; 64 backHeight = background.Height; 65 66 images = new Pixbuf[ImageNames.Length]; 67 68 int i = 0; 69 foreach (string im in ImageNames) 70 images[i++] = Gdk.Pixbuf.LoadFromResource (im); 71 } 72 73 // Expose callback for the drawing area Expose(object o, ExposeEventArgs args)74 void Expose (object o, ExposeEventArgs args) 75 { 76 Widget widget = (Widget) o; 77 Gdk.Rectangle area = args.Event.Area; 78 byte[] pixels; 79 int rowstride; 80 81 rowstride = frame.Rowstride; 82 pixels = new byte[(frame.Height - area.Y) * rowstride]; 83 IntPtr src = (IntPtr)(frame.Pixels.ToInt64 () + rowstride * area.Y + area.X * 3); 84 Marshal.Copy (src, pixels, 0, pixels.Length); 85 86 widget.GdkWindow.DrawRgbImageDithalign (widget.Style.BlackGC, 87 area.X, area.Y, area.Width, area.Height, 88 Gdk.RgbDither.Normal, 89 pixels, rowstride, 90 area.X, area.Y); 91 args.RetVal = true; 92 } 93 94 // timeout handler to regenerate the frame timeout()95 bool timeout () 96 { 97 background.CopyArea (0, 0, backWidth, backHeight, frame, 0, 0); 98 99 double f = (double) (frameNum % CycleLen) / CycleLen; 100 101 int xmid = backWidth / 2; 102 int ymid = backHeight / 2; 103 104 double radius = Math.Min (xmid, ymid) / 2; 105 106 for (int i = 0; i < images.Length; i++) { 107 double ang = 2 * Math.PI * (double) i / images.Length - f * 2 * Math.PI; 108 109 int iw = images[i].Width; 110 int ih = images[i].Height; 111 112 double r = radius + (radius / 3) * Math.Sin (f * 2 * Math.PI); 113 114 int xpos = (int) Math.Floor (xmid + r * Math.Cos (ang) - 115 iw / 2.0 + 0.5); 116 int ypos = (int) Math.Floor (ymid + r * Math.Sin (ang) - 117 ih / 2.0 + 0.5); 118 119 double k = (i % 2 == 1) ? Math.Sin (f * 2 * Math.PI) : 120 Math.Cos (f * 2 * Math.PI); 121 k = 2 * k * k; 122 k = Math.Max (0.25, k); 123 124 Rectangle r1, r2, dest; 125 126 r1 = new Rectangle (xpos, ypos, (int) (iw * k), (int) (ih * k)); 127 r2 = new Rectangle (0, 0, backWidth, backHeight); 128 129 dest = Rectangle.Intersect (r1, r2); 130 if (!dest.IsEmpty) { 131 images[i].Composite (frame, dest.X, dest.Y, 132 dest.Width, dest.Height, 133 xpos, ypos, k, k, 134 InterpType.Nearest, 135 (int) ((i % 2 == 1) ? 136 Math.Max (127, Math.Abs (255 * Math.Sin (f * 2 * Math.PI))) : 137 Math.Max (127, Math.Abs (255 * Math.Cos (f * 2 * Math.PI))))); 138 } 139 } 140 141 drawingArea.QueueDraw (); 142 frameNum++; 143 144 return true; 145 } 146 DemoPixbuf()147 public DemoPixbuf () : base ("Pixbufs") 148 { 149 Resizable = false; 150 SetSizeRequest (backWidth, backHeight); 151 152 frame = new Pixbuf (Colorspace.Rgb, false, 8, backWidth, backHeight); 153 154 drawingArea = new DrawingArea (); 155 drawingArea.ExposeEvent += new ExposeEventHandler (Expose); 156 157 Add (drawingArea); 158 timeoutId = GLib.Timeout.Add (FrameDelay, new GLib.TimeoutHandler(timeout)); 159 160 ShowAll (); 161 } 162 OnDestroyed()163 protected override void OnDestroyed () 164 { 165 if (timeoutId != 0) { 166 GLib.Source.Remove (timeoutId); 167 timeoutId = 0; 168 } 169 } 170 OnDeleteEvent(Gdk.Event evt)171 protected override bool OnDeleteEvent (Gdk.Event evt) 172 { 173 Destroy (); 174 return true; 175 } 176 } 177 } 178