summaryrefslogtreecommitdiff
path: root/Bitmap.cs
blob: e508d3de2376a4aed788ca705075ba5f546694c3 (plain)
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
using System.Buffers.Binary;
using System.IO.Compression;
using Raylib_cs;

namespace OnekoOnline;

class Bitmap : IDisposable
{
    public readonly int Width;
    public readonly int Height;
    public readonly Texture2D Texture;

    readonly byte[] SerializedData;

    public Bitmap(Image img)
    {
        Width = img.Width;
        Height = img.Height;
        Texture = Raylib.LoadTextureFromImage(img);

        //Get Data for Serialization
        Color[] colors = new Color[Width*Height];
        int i = 0;
        for (int x = 0; x < Width; x++) {
            for (int y = 0; y < Height; y++) {
                colors[i] = Raylib.GetImageColor(img, x, y);
                i++;
            }
        }

        byte[] data = new byte[(colors.Length*4) + (sizeof(short)*2)];
        BinaryPrimitives.WriteInt16LittleEndian(data.AsSpan(0, sizeof(short)), (short)Width);
        BinaryPrimitives.WriteInt16LittleEndian(data.AsSpan(sizeof(short), sizeof(short)), (short)Height);
        int position = sizeof(short)*2;
        for (int c = 0; c < colors.Length; c++) {
            data[position] = colors[c].R;
            data[position+1] = colors[c].G;
            data[position+2] = colors[c].B;
            data[position+3] = colors[c].A;
            position += 4;
        }

        using MemoryStream stream = new();
        using DeflateStream compressor = new(stream, CompressionLevel.Optimal);
        compressor.Write(data);
        compressor.Close();
        SerializedData = stream.ToArray();

        Raylib.UnloadImage(img);
    }

    Bitmap(Image img, byte[] serializedData)
    {
        Width = img.Width;
        Height = img.Height;
        SerializedData = serializedData;

        Texture = Raylib.LoadTextureFromImage(img);
        Raylib.UnloadImage(img);
    }

    public static Bitmap FromFile(string path)
    {
        if (!File.Exists(path) || new FileInfo(path).Length > 40000 || !path.Contains(".png"))
        return new Bitmap(Raylib.GenImageChecked(32, 32, 4, 4, Color.BLACK, Color.PINK));

        byte[] memory = File.ReadAllBytes(path);
        return FromPNGMemory(memory);
    }

    public static Bitmap FromPNGMemory(byte[] memory)
    {
        return new Bitmap(Raylib.LoadImageFromMemory(".png", memory));
    }

    public static Bitmap Deserialize(ReadOnlySpan<byte> span)
    {
        byte[] compressed = span.ToArray();
        byte[] data;
        {
            using MemoryStream input = new(compressed);
            using MemoryStream output = new();
            using DeflateStream decompressor = new(input, CompressionMode.Decompress);
            decompressor.CopyTo(output);
            data = output.ToArray();
        }

        int width = BinaryPrimitives.ReadInt16LittleEndian(data.AsSpan(0, sizeof(short)));
        int height = BinaryPrimitives.ReadInt16LittleEndian(data.AsSpan(sizeof(short), sizeof(short)));
        Image img = Raylib.GenImageChecked(width, height, 4, 4, Color.PINK, Color.BLACK);

        int i = sizeof(short)*2;
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                Color color = new(data[i], data[i+1], data[i+2], data[i+3]);
                Raylib.ImageDrawPixel(ref img, x, y, color);
                i += 4;
            }
        }

        return new Bitmap(img, compressed);
    }

    public byte[] Serialize()
    {
        return SerializedData;
    }

    public void Dispose()
    {
        Raylib.UnloadTexture(Texture);
    }
}