-2

I have an issue with my WinForms project. I need to display image of created maze and i use bitmap. But empty bitmap(9990, 9990) takes 400MB+. Is there way to decrease this memory consumption or i need to change bitmap to anything else?

Bitmap bm = new Bitmap(9990, 9990);

Thank you for your help.

The cell and wall have one size 10x10 px.

https://i.stack.imgur.com/yj9CA.png

2 Answers2

1

I decreased the memory usage by using a custom PixelFormat; It reduced memory consumption by 2-4 times.

var format = System.Drawing.Imaging.PixelFormat.Format16bppRgb565;
                inBm = new Bitmap(
                    CellWid * (maze.finish.X + 2),
                    CellHgt * (maze.finish.Y + 2), format);
  • @ondřej-kubíček It can be better, but we cant use Graphics from bitmap with `Format8bppIndexed` format. Indexed palette -_- – Timur Sidoryuk Jan 27 '19 at 11:21
  • That's actually not _too_ hard to get around; you just make a new 8bpp image of the desired dimensions, open its backing array using `LockBits`, and copy data into it per line, using `Marshal.Copy`. I posted a full "byte array to image" function for that [here](https://stackoverflow.com/a/43967594/395685). Heck, if you can do it with 16colours for the main maze layout, you can even [go down to 4bpp](https://stackoverflow.com/a/51124131/395685). – Nyerguds Sep 16 '19 at 14:35
0

Is there a way to decrease memory consumption? As long as you do not need the whole maze rendered at once there is. You use 10*10*4 = 400B to store information about one cell. Chances are, you only need to know if the cell is a wall or not. That is 1 bit. You can reduce 400MB to 125kB to store information about the whole maze. And render only the part you actually need. Here is some code to play with, this draws 999x999 cells "maze" you can move by mouse

BitArray maze = null;
int mazeWidth = 999;
int mazeHeight = 999;
int xPos = 0;
int yPos = 0;
int cellSize = 10;

private void Form1_Load(object sender, EventArgs e)
{
    maze = new BitArray(mazeWidth * mazeHeight);
    Random rnd = new Random();
    for (int i = 0; i < maze.Length; ++i)
    {
        maze[i] = rnd.Next(4) == 0;
    }

    xPos = -Width / 2;
    yPos = -Height / 2;
    DoubleBuffered = true;
}

private void Form1_Paint(object sender, PaintEventArgs e)
{
    for (int y = Math.Max(0, yPos / cellSize); y < mazeHeight; ++y)
    {
        int yDraw = y * cellSize - yPos;
        if (yDraw > Height) { return; }
        for (int x = Math.Max(0, xPos / cellSize); x < mazeWidth; ++x)
        {
            if (maze[x + y * mazeWidth])
            {
                int xDraw = x * cellSize - xPos;
                if (xDraw > Width) { break; }
                e.Graphics.FillRectangle(
                    Brushes.Black,
                    xDraw,
                    yDraw,
                    cellSize,
                    cellSize
                    );
            }
        }
    }
}

public static int Clamp(int value, int min, int max)
{
    if (value < min) { return min; }
    if (value > max) { return max; }
    return value;
}


int fromX;
int fromY;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
    fromX = e.X;
    fromY = e.Y;
}

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        int w2 = Width / 2;
        int h2 = Height / 2;
        xPos = Clamp(xPos + fromX - e.X, -w2, mazeWidth * cellSize - w2);
        yPos = Clamp(yPos + fromY - e.Y, -h2, mazeHeight * cellSize - h2);
        fromX = e.X;
        fromY = e.Y;
        Invalidate();
    }
}
Antonín Lejsek
  • 6,003
  • 2
  • 16
  • 18