#C#, Winform 

**Edit** Changing the way you fill the coordinates array you can have different patterns - see below

Do you like this kind of pattern?

![LandScape][1]

![Abstract][2]

Bonus:

![Scream][3]
![Scream Scrambled][4]

Random swap exactly one time all pixels in upper half with all pixels in lower half.
Repeat the same procedure for unscrambling (bonus).

#Code

**Scramble.cs**

<!-- language-all: lang-cs -->

 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Data;
 using System.Drawing;
 using System.Windows.Forms;
 using System.Drawing.Imaging;
 using System.IO;
 
 namespace Palette
 {
 public partial class Scramble : Form
 {
 public Scramble()
 {
 InitializeComponent();
 }
 
 public struct Coord
 {
 public int x, y;
 }
 
 private void Work(Bitmap srcb, Bitmap outb)
 {
 int w = srcb.Width, h = srcb.Height;
 Coord[] coord = new Coord[w * h];
 
 FastBitmap fsb = new FastBitmap(srcb);
 FastBitmap fob = new FastBitmap(outb);
 fsb.LockImage();
 fob.LockImage();
 ulong seed = 0;
 int numpix = 0;
 for (int y = 0; y < h; y++)
 for (int x = 0; x < w; numpix++, x++)
 {
 coord[numpix].x = x;
 coord[numpix].y = y;
 uint color = fsb.GetPixel(x, y);
 seed += color;
 fob.SetPixel(x, y, color);
 }
 fsb.UnlockImage();
 fob.UnlockImage();
 pbOutput.Refresh();
 Application.DoEvents();
 
 int half = numpix / 2;
 int limit = half;
 XorShift rng = new XorShift(seed);
 progressBar.Visible = true;
 progressBar.Maximum = limit;
 
 fob.LockImage();
 while (limit > 0)
 {
 int p = (int)(rng.next() % (uint)limit);
 int q = (int)(rng.next() % (uint)limit);
 uint color = fob.GetPixel(coord[p].x, coord[p].y); 
 fob.SetPixel(coord[p].x, coord[p].y, fob.GetPixel(coord[half+q].x, coord[half+q].y)); 
 fob.SetPixel(coord[half+q].x, coord[half+q].y, color); 
 limit--;
 if (p < limit)
 {
 coord[p]=coord[limit];
 }
 if (q < limit)
 {
 coord[half+q]=coord[half+limit];
 }
 if ((limit & 0xfff) == 0)
 {
 progressBar.Value = limit;
 fob.UnlockImage();
 pbOutput.Refresh();
 fob.LockImage();
 }
 }
 fob.UnlockImage();
 pbOutput.Refresh();
 progressBar.Visible = false; 
 }
 
 void DupImage(PictureBox s, PictureBox d)
 {
 if (d.Image != null)
 d.Image.Dispose();
 d.Image = new Bitmap(s.Image.Width, s.Image.Height); 
 }
 
 void GetImagePB(PictureBox pb, string file)
 {
 Bitmap bms = new Bitmap(file, false);
 Bitmap bmp = bms.Clone(new Rectangle(0, 0, bms.Width, bms.Height), PixelFormat.Format32bppArgb);
 bms.Dispose(); 
 if (pb.Image != null)
 pb.Image.Dispose();
 pb.Image = bmp;
 }
 
 private void btnOpen_Click(object sender, EventArgs e)
 {
 OpenFileDialog openFileDialog = new OpenFileDialog();
 
 openFileDialog.InitialDirectory = "c:\\temp\\";
 openFileDialog.Filter = "Image Files(*.BMP;*.JPG;*.PNG)|*.BMP;*.JPG;*.PNG|All files (*.*)|*.*";
 openFileDialog.FilterIndex = 1;
 openFileDialog.RestoreDirectory = true;
 
 if (openFileDialog.ShowDialog() == DialogResult.OK)
 {
 try
 {
 string file = openFileDialog.FileName;
 GetImagePB(pbInput, file);
 pbInput.Tag = file;
 DupImage(pbInput, pbOutput);
 Work(pbInput.Image as Bitmap, pbOutput.Image as Bitmap);
 file = Path.GetDirectoryName(file) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(file) + ".scr.png";
 pbOutput.Image.Save(file);
 }
 catch (Exception ex)
 {
 MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
 }
 
 }
 }
 }
 
 //Adapted from Visual C# Kicks - http://www.vcskicks.com/
 unsafe public class FastBitmap
 {
 private Bitmap workingBitmap = null;
 private int width = 0;
 private BitmapData bitmapData = null;
 private Byte* pBase = null;
 
 public FastBitmap(Bitmap inputBitmap)
 {
 workingBitmap = inputBitmap;
 }
 
 public BitmapData LockImage()
 {
 Rectangle bounds = new Rectangle(Point.Empty, workingBitmap.Size);
 
 width = (int)(bounds.Width * 4 + 3) & ~3;
 
 //Lock Image
 bitmapData = workingBitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
 pBase = (Byte*)bitmapData.Scan0.ToPointer();
 return bitmapData;
 }
 
 private uint* pixelData = null;
 
 public uint GetPixel(int x, int y)
 {
 pixelData = (uint*)(pBase + y * width + x * 4);
 return *pixelData;
 }
 
 public uint GetNextPixel()
 {
 return *++pixelData;
 }
 
 public void GetPixelArray(int x, int y, uint[] Values, int offset, int count)
 {
 pixelData = (uint*)(pBase + y * width + x * 4);
 while (count-- > 0)
 {
 Values[offset++] = *pixelData++;
 }
 }
 
 public void SetPixel(int x, int y, uint color)
 {
 pixelData = (uint*)(pBase + y * width + x * 4);
 *pixelData = color;
 }
 
 public void SetNextPixel(uint color)
 {
 *++pixelData = color;
 }
 
 public void UnlockImage()
 {
 workingBitmap.UnlockBits(bitmapData);
 bitmapData = null;
 pBase = null;
 }
 }
 
 public class XorShift
 {
 private ulong x; /* The state must be seeded with a nonzero value. */
 
 public XorShift(ulong seed)
 {
 x = seed;
 }
 
 public ulong next()
 {
 	 x ^= x >> 12; // a
 	 x ^= x << 25; // b
 	 x ^= x >> 27; // c
 	return x * 2685821657736338717L;
 }
 }
 } 

**Scramble.designer.cs**

 namespace Palette
 {
 partial class Scramble
 {
 private System.ComponentModel.IContainer components = null;
 
 protected override void Dispose(bool disposing)
 {
 if (disposing && (components != null))
 {
 components.Dispose();
 }
 base.Dispose(disposing);
 }
 
 private void InitializeComponent()
 {
 this.panel = new System.Windows.Forms.FlowLayoutPanel();
 this.pbInput = new System.Windows.Forms.PictureBox();
 this.pbOutput = new System.Windows.Forms.PictureBox();
 this.progressBar = new System.Windows.Forms.ProgressBar();
 this.btnOpen = new System.Windows.Forms.Button();
 this.panel.SuspendLayout();
 ((System.ComponentModel.ISupportInitialize)(this.pbInput)).BeginInit();
 ((System.ComponentModel.ISupportInitialize)(this.pbOutput)).BeginInit();
 this.SuspendLayout();
 // 
 // panel
 // 
 this.panel.AutoScroll = true;
 this.panel.AutoSize = true;
 this.panel.Controls.Add(this.pbInput);
 this.panel.Controls.Add(this.pbOutput);
 this.panel.Dock = System.Windows.Forms.DockStyle.Top;
 this.panel.Location = new System.Drawing.Point(0, 0);
 this.panel.Name = "panel";
 this.panel.Size = new System.Drawing.Size(748, 306);
 this.panel.TabIndex = 3;
 // 
 // pbInput
 // 
 this.pbInput.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
 this.pbInput.Location = new System.Drawing.Point(3, 3);
 this.pbInput.MinimumSize = new System.Drawing.Size(100, 100);
 this.pbInput.Name = "pbInput";
 this.pbInput.Size = new System.Drawing.Size(100, 300);
 this.pbInput.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
 this.pbInput.TabIndex = 3;
 this.pbInput.TabStop = false;
 // 
 // pbOutput
 // 
 this.pbOutput.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
 this.pbOutput.Location = new System.Drawing.Point(109, 3);
 this.pbOutput.MinimumSize = new System.Drawing.Size(100, 100);
 this.pbOutput.Name = "pbOutput";
 this.pbOutput.Size = new System.Drawing.Size(100, 300);
 this.pbOutput.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
 this.pbOutput.TabIndex = 4;
 this.pbOutput.TabStop = false;
 // 
 // progressBar
 // 
 this.progressBar.Dock = System.Windows.Forms.DockStyle.Bottom;
 this.progressBar.Location = new System.Drawing.Point(0, 465);
 this.progressBar.Name = "progressBar";
 this.progressBar.Size = new System.Drawing.Size(748, 16);
 this.progressBar.TabIndex = 5;
 // 
 // btnOpen
 // 
 this.btnOpen.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
 this.btnOpen.Location = new System.Drawing.Point(12, 429);
 this.btnOpen.Name = "btnOpen";
 this.btnOpen.Size = new System.Drawing.Size(53, 30);
 this.btnOpen.TabIndex = 6;
 this.btnOpen.Text = "Start";
 this.btnOpen.UseVisualStyleBackColor = true;
 this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click);
 // 
 // Scramble
 // 
 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
 this.BackColor = System.Drawing.SystemColors.ControlDark;
 this.ClientSize = new System.Drawing.Size(748, 481);
 this.Controls.Add(this.btnOpen);
 this.Controls.Add(this.progressBar);
 this.Controls.Add(this.panel);
 this.Name = "Scramble";
 this.Text = "Form1";
 this.panel.ResumeLayout(false);
 this.panel.PerformLayout();
 ((System.ComponentModel.ISupportInitialize)(this.pbInput)).EndInit();
 ((System.ComponentModel.ISupportInitialize)(this.pbOutput)).EndInit();
 this.ResumeLayout(false);
 this.PerformLayout();
 
 }
 
 
 private System.Windows.Forms.FlowLayoutPanel panel;
 private System.Windows.Forms.PictureBox pbOutput;
 private System.Windows.Forms.ProgressBar progressBar;
 private System.Windows.Forms.PictureBox pbInput;
 private System.Windows.Forms.Button btnOpen;
 }
 }
 
**Program.cs**

 using System;
 using System.Collections.Generic;
 using System.Windows.Forms;

 namespace Palette
 {
 static class Program
 {
 [STAThread]
 static void Main()
 {
 Application.EnableVisualStyles();
 Application.SetCompatibleTextRenderingDefault(false);
 Application.Run(new Scramble());
 }
 }
 }

Check 'Unsafe code' in project property to compile.

**Complex pattern**

![Scramble][5]

Change the first part of work function, up to Application.DoEvents:

 int w = srcb.Width, h = srcb.Height;
 string Msg = "Scramble";

 Graphics gr = Graphics.FromImage(outb);

 Font f = new Font("Arial", 100, FontStyle.Bold);
 var size = gr.MeasureString(Msg, f);
 f = new Font("Arial", w / size.Width * 110, FontStyle.Bold);
 size = gr.MeasureString(Msg, f);
 gr.DrawString(Msg, f, new SolidBrush(Color.White), (w - size.Width) / 2, (h - size.Height) / 2);

 gr.Dispose();

 Coord[] coord = new Coord[w * h];
 FastBitmap fsb = new FastBitmap(srcb);
 FastBitmap fob = new FastBitmap(outb);
 fsb.LockImage();
 fob.LockImage();
 ulong seed = 1;
 int numpix = h * w;
 int c1 = 0, c2 = numpix;
 int y2 = h / 2;

 int p2 = numpix/2;

 for (int p = 0; p < p2; p++)
 {
 for (int s = 1; s > -2; s -= 2)
 {
 int y = (p2+s*p) / w;
 int x = (p2+s*p) % w;

 uint d = fob.GetPixel(x, y);
 if (d != 0)
 {
 c2--;
 coord[c2].x = x;
 coord[c2].y = y;
 }
 else
 {
 coord[c1].x = x;
 coord[c1].y = y;
 c1++;
 }
 fob.SetPixel(x, y, fsb.GetPixel(x, y));
 }
 }
 fsb.UnlockImage();
 fob.UnlockImage();
 pbOutput.Refresh();
 Application.DoEvents();

 [1]: https://i.sstatic.net/uXGVH.jpg
 [2]: https://i.sstatic.net/AwbqU.png
 [3]: https://i.sstatic.net/UPZ15.png
 [4]: https://i.sstatic.net/ho4Na.png
 [5]: https://i.sstatic.net/lQ8Hd.png