Concept

Imagine each image as a collection of small boxes arranged in different positions. Each image has four sides, and our goal is to determine how these images can connect to one another based on the configuration of these sides.

TL.png
LRB.png
LR.png
L.png
SL.png
LRTB.png
TR.png
B.png
STR.png
TLR.png
TBR.png
TB.png
TBL.png
BTL.png
T.png

Let’s take the example of an image:

  • Image Tagged with 1 from above collection is made up of small boxes and has two open sides and two closed sides.
  • We represent open sides as 1 and closed sides as 0.
  • The sides are labeled as follows:
    • Left (L): 0
    • Right (R): 1
    • Top (T): 0
    • Bottom (B): 1

To connect this image to another on the right side, the adjacent image must have an open left side.

Therefore, images that can potentially connect are those with an opening on their left side. Examples of such images are 2, 3, 4, 6, 7, 10, 11, and 14. We can choose any of these images randomly to connect to the first image.

This approach can be applied to all other images to determine possible connections, allowing us to piece together the images like a puzzle based on the arrangement of open and closed sides.

Applying Above Concept

Requiements

  • VS Code
  • Skia Sharp
  • C# as Programming language
  • Image used in for this project Download Images

Code behind

Import Skia Library

1
2
3
#r "nuget:SkiaSharp"
using SkiaSharp;
using System.IO;

Model class for each Cell

Creating Model For holding each Image case data like side open or Close and location image

1
2
3
4
5
6
7
8
public class Entity
{
    public int L { get; set; } = -1;
    public int R { get; set; } = -1;
    public int T { get; set; } = -1;
    public int B { get; set; } = -1;
    public string Path { get; set; } = string.Empty;
}

Base Directory where all image file will be located

Location of parent folder where image is located

1
var baseDir = @"C:\Users\Prashant\Downloads\demo\WCF\Assets\road";

Creation Model Relation for each image

Creating model for each image with opening data where it is open and close and location of file

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
List<Entity> listOfEntity =
[
    new()
    {
        Path = Path.Combine(baseDir,"B.png"),
        B =1,
        L =0,
        T =0,
        R =0
    },
    new()
    {
        Path = Path.Combine(baseDir,"BTL.png"),
        B =0,
        L =1,
        T =1,
        R =0
    },
    new()
    {
        Path = Path.Combine(baseDir,"L.png"),
        B =0,
        L =1,
        T =0,
        R =0
    },
    new()
    {
        Path = Path.Combine(baseDir,"LR.png"),
        B =0,
        L =1,
        T =0,
        R =1
    },
    new()
    {
        Path = Path.Combine(baseDir,"LRB.png"),
        B =1,
        L =1,
        T =0,
        R =1
    },
    new()
    {
        Path = Path.Combine(baseDir,"LRTB.png"),
        B =1,
        L =1,
        T =1,
        R =1
    },
    new()
    {
        Path = Path.Combine(baseDir,"SL.png"),
        B =0,
        L =0,
        T =0,
        R =1
    },
    new()
    {
        Path = Path.Combine(baseDir,"STR.png"),
        B =0,
        L =0,
        T =1,
        R =1
    },
    new()
    {
        Path = Path.Combine(baseDir,"T.png"),
        B =0,
        L =0,
        T =1,
        R =0
    },
    new()
    {
        Path = Path.Combine(baseDir,"TB.png"),
        B =1,
        L =0,
        T =1,
        R =0
    },
    new()
    {
        Path = Path.Combine(baseDir,"TBL.png"),
        B =1,
        L =0,
        T =1,
        R =1
    },
    new()
    {
        Path = Path.Combine(baseDir,"TBR.png"),
        B =1,
        L =1,
        T =1,
        R =0
    },
    new()
    {
        Path = Path.Combine(baseDir,"TL.png"),
        B =1,
        L =0,
        T =0,
        R =1
    },
    new()
    {
        Path = Path.Combine(baseDir,"TLR.png"),
        B =0,
        L =1,
        T =1,
        R =1
    },
    new()
    {
        Path = Path.Combine(baseDir,"TR.png"),
        B =1,
        L =1,
        T =0,
        R =0
    }

];

Fisher Yeats Suffling to Randomise Data

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
void SuffeledArray<T>(List<T> array)
{
    var rand = new Random();
    for (int i = 0; i < array.Count; i++)
    {
        var randIndex = rand.Next(i, array.Count);
        var tempItem = array[randIndex];
        array[randIndex] = array[i];
        array[i] = tempItem;
    }
}

Draw Image on SKCanvas Function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
void DrawImage(string path, SKCanvas canvas, float x = 0, float y = 0)
{
    using (var inputStream = File.OpenRead(path))
    {
        using (var inputBitmap = SKBitmap.Decode(inputStream))
        {
            var imageInfo = new SKImageInfo(inputBitmap.Width, inputBitmap.Height);
            canvas.DrawBitmap(inputBitmap, x * 64, y * 64);
        }
    }
}

Find Matching neighobours and return on randomise element

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Entity FindEntity(int x, int y ,List<List<Entity>> matrix)
{
    var ls = new List<Entity>();
    foreach (var item in listOfEntity)
    {
        if (x == 0 )
        { 
            if( item.L == matrix[x][y-1].R && item.T !=1)
            {
                ls.Add(item); 
            } 
        }
        else
        {
            if(y==0)
            {
                if (item.T == matrix[x - 1][y].B && item.L !=1)
                {
                    ls.Add(item);
                }
            }
            else if(item.T == matrix[x - 1][y].B && item.L == matrix[x][y-1].R)
            {
                ls.Add(item);
            }
        }
    }
    
    SuffeledArray(ls);
    return ls.First();
}

Setpuing SkCanvas and Calling All Other methods

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

int width = 2560;
int height = 1280;
int step = 64;
Random random = new();
SKBitmap bmp = new(width, height);
SKCanvas canvas = new(bmp);
canvas.Clear(SKColor.Parse("#fff"));
SKPaint paint = new()
{
    Color = SKColors.White.WithAlpha(100),
    IsAntialias = true,
    StrokeWidth = 3,
    ColorF = SKColor.Parse("#003366")
};
var matrix = new List<List<Entity>>();
for(var i =0; i<height;i+=step)
{
    var cell = new List<Entity>();
    for(var j=0;j<width;j+=step) 
    {
        cell.Add(new());
    }
    matrix.Add(cell);
}
for (int i = 0; i < matrix.Count; i++)
{
    for (int j = 0; j < matrix[0].Count; j++)
    {
        if(i==0 && j==0)
        {
            matrix[0][0].Path = Path.Combine(baseDir, "TL.png");
            matrix[0][0].L = 0;
            matrix[0][0].R = 1;
            matrix[0][0].B = 1;
            matrix[0][0].T = 0;
            DrawImage(matrix[0][0].Path, canvas, j, i);
            continue;
        }
        matrix[i][j] = FindEntity(i, j,matrix);
        DrawImage(matrix[i][j].Path, canvas, j, i);
    }
}
// For saving the image as a file
using (SKFileWStream fs = new("image.jpg"))
{
    bmp.Encode(fs, SKEncodedImageFormat.Jpeg, quality: 50);
}
bmp.Display()

Thumbail of This Page Is Generated using same code above + 2 Line of Code to Write Text Obviously 😁😁😁😊