This simple loopdeck plugin fills each LED with a 64x64 fragment of the screen, starting from the top-left of the cursor. Pressing any button right now just starts or stops it. Update this so pressing the bottom-left button zooms out, and pressing the bottom-right button zooms in.

```
/// DisplayController.cs ///
namespace Loupedeck.LoupeUtilPlugin
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Linq;
    using System.Threading;
    using System.Windows.Forms;

    public class DisplayController : PluginDynamicFolder
    {
        private readonly TotalCanvas canvas = new TotalCanvas();
        private volatile Boolean threadRunning = false;
        private Thread thread;

        public DisplayController()
        {
            this.canvas.UpdateGraphics(graphics => graphics.CopyFromScreen(new Point(Control.MousePosition.X, Control.MousePosition.Y), new Point(0,0), new Size(TotalCanvas.WIDTH, TotalCanvas.HEIGHT)));
            this.thread = new Thread(this.UpdateThread);
            this.DisplayName = "Magnifier";
            this.GroupName = "System";
        }

        public override PluginDynamicFolderNavigation GetNavigationArea(DeviceType deviceType) => PluginDynamicFolderNavigation.ButtonArea;
        
        public override IEnumerable<String> GetButtonPressActionNames(DeviceType deviceType)
        {
            return new[]
            {
                PluginDynamicFolder.NavigateUpActionName,
                //this.CreateCommandName("Magnify (0,0)"),
                this.CreateCommandName("Magnify (1,0)"),
                this.CreateCommandName("Magnify (2,0)"),
                this.CreateCommandName("Magnify (3,0)"),
                this.CreateCommandName("Magnify (4,0)"),
                this.CreateCommandName("Magnify (0,1)"),
                this.CreateCommandName("Magnify (1,1)"),
                this.CreateCommandName("Magnify (2,1)"),
                this.CreateCommandName("Magnify (3,1)"),
                this.CreateCommandName("Magnify (4,1)"),
                this.CreateCommandName("Magnify (0,2)"),
                this.CreateCommandName("Magnify (1,2)"),
                this.CreateCommandName("Magnify (2,2)"),
                this.CreateCommandName("Magnify (3,2)"),
                this.CreateCommandName("Magnify (4,2)"),
            };
        }

        public override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize)
        {
            var arr = actionParameter.Where(Char.IsDigit).ToArray();
            var x = arr[0] - 48;
            var y = arr[1] - 48;
            BitmapImage image = this.canvas.GetImage()[x + y * 5];
            using (var bitmapBuilder = new BitmapBuilder(imageSize))
            {
                bitmapBuilder.SetBackgroundImage(image);
                return bitmapBuilder.ToImage();
            }
        }

        public override void RunCommand(String commandParameter)
        {
            if (this.threadRunning)
            {
                this.threadRunning = false;
            }
            else
            {
                this.thread = new Thread(this.UpdateThread);
                this.threadRunning = true;
                this.thread.Start();
            }
        }

        // Used to run an update thread for the screen
        public void UpdateThread()
        {
            while(this.threadRunning)
            {
                this.canvas.UpdateGraphics(graphics => graphics.CopyFromScreen(new Point(Control.MousePosition.X, Control.MousePosition.Y), new Point(0,0), new Size(TotalCanvas.WIDTH, TotalCanvas.HEIGHT)));
                // this.CommandImageChanged("Magnify (0,0)");
                this.CommandImageChanged("Magnify (1,0)");
                this.CommandImageChanged("Magnify (2,0)");
                this.CommandImageChanged("Magnify (3,0)");
                this.CommandImageChanged("Magnify (4,0)");
                this.CommandImageChanged("Magnify (0,1)");
                this.CommandImageChanged("Magnify (1,1)");
                this.CommandImageChanged("Magnify (2,1)");
                this.CommandImageChanged("Magnify (3,1)");
                this.CommandImageChanged("Magnify (4,1)");
                this.CommandImageChanged("Magnify (0,2)");
                this.CommandImageChanged("Magnify (1,2)");
                this.CommandImageChanged("Magnify (2,2)");
                this.CommandImageChanged("Magnify (3,2)");
                this.CommandImageChanged("Magnify (4,2)");
                // TODO: this.ActionImageChanged(); // Notify the Loupedeck service that the command display name and/or image has changed.
                Thread.Sleep(30);
            }
        }
    }
}

/// ButtonCanvas.cs ///
namespace Loupedeck.LoupeUtilPlugin
{
    using System;
    using System.Drawing;
    using System.IO;

    public class ButtonCanvas
    {
        public const Int32 WIDTH = 80;
        public const Int32 HEIGHT = 80;
        
        private readonly Bitmap bmp = new Bitmap(WIDTH, HEIGHT);
        private readonly Object lockObject = new Object();
        // private readonly Region clipRegion = new Region(new Rectangle(0, 0, WIDTH, HEIGHT));

        // Allows arbitrary modification of the internal graphics
        public void UpdateGraphics(Action<Graphics> action)
        {
            lock (this.lockObject)
            {
                using (var graphics = Graphics.FromImage(this.bmp))
                {
                    // graphics.Clip = this.clipRegion;
                    action(graphics);
                }
            }
        }

        // Convenience wrapper for Graphics.FillRectangle with default parameters set to exactly cover the entire image.
        public void FillRectangle(Brush brush, Int32 x = 0, Int32 y = 0, Int32 width = WIDTH, Int32 height = HEIGHT) => this.UpdateGraphics(graphics => graphics.FillRectangle(brush, x, y, width, height));

        // Set a specific pixel value
        // x must be in the range of 0-79
        // y must be in the range of 0-79
        public void SetPixel(Int32 x, Int32 y, Color color) 
        {
            lock(this.lockObject)
            {
                this.bmp.SetPixel(x, y, color);
            }
        }

        // Create a renderable image from this canvas
        public BitmapImage CreateImage()
        {
            using (var stream = new MemoryStream())
            {
                lock (this.lockObject)
                {
                    this.bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
                }
                return BitmapImage.FromArray(stream.ToArray());
            }
        }
    }
}

/// TotalCanvas.cs ///
namespace Loupedeck.LoupeUtilPlugin
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.IO;

    public class TotalCanvas
    {
        public const Int32 WIDTH = 80 * 5;
        public const Int32 HEIGHT = 80 * 3;
        
        private readonly Bitmap bmp = new Bitmap(WIDTH, HEIGHT);
        private readonly Object lockObject = new Object();
        private List<BitmapImage> images = new List<BitmapImage>();
        // private readonly Region clipRegion = new Region(new Rectangle(0, 0, WIDTH, HEIGHT));

        // Allows arbitrary modification of the internal graphics
        public void UpdateGraphics(Action<Graphics> action)
        {
            lock (this.lockObject)
            {
                using (var graphics = Graphics.FromImage(this.bmp))
                {
                    // graphics.Clip = this.clipRegion;
                    action(graphics);
                    var imageList = new List<BitmapImage>();
                    for (var y = 0; y < 3; y++)
                    {
                        for (var x = 0; x < 5; x++)
                        {
                            lock (this.lockObject)
                            {
                                var sourceData = this.bmp.LockBits
                                (
                                    new Rectangle(x * 80, y * 80, 80, 80),
                                    System.Drawing.Imaging.ImageLockMode.ReadOnly,
                                    this.bmp.PixelFormat
                                );
                                using(var tile = new Bitmap
                                (
                                    sourceData.Width,
                                    sourceData.Height,
                                    sourceData.Stride,
                                    sourceData.PixelFormat,
                                    sourceData.Scan0))
                                {
                                    using (var stream = new MemoryStream())
                                    {
                                        tile.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
                                        imageList.Add(BitmapImage.FromArray(stream.ToArray()));
                                    }
                                }
                                this.bmp.UnlockBits(sourceData);
                            }
                        }
                    }
                    this.images = imageList;
                }
            }
        }

        // Create a renderable image from this canvas
        public List<BitmapImage> GetImage() => this.images;
    }
}
```