How to create a jpg image dynamically in memory with .NET?

Slauma picture Slauma · Mar 28, 2011 · Viewed 33k times · Source

I have a .NET (3.5 SP1) library (DLL) written in C#. I have to extend this library by a class method which will have the following signature:

public byte[] CreateGridImage(int maxXCells, int maxYCells,
    int cellXPosition, int cellYPosition)
{
    ...
}

This method is supposed to do the following:

  • Input parameters maxXCells and maxYCells define the size of a grid of cells in X and Y direction. maxXCells and maxYCells is the number of cells in each direction. The individual cells are square-shaped. (So it's kind of an asymmetric chess board.)
  • Input parameters cellXPosition and cellYPosition identify one special cell within this grid and this cell has to be filled with a cross.
  • No fancy graphics are necessary, really only black grid lines on a white background and a X in one of the cells.
  • The resulting graphic must have jpg format.
  • Creation of this graphic must happen in memory and nothing should be stored in a file on disk nor painted on the screen.
  • The method returns the generated image as a byte[]

I'm very unfamiliar with graphics functions in .NET so my questions are:

  • Is this possible at all with .NET 3.5 SP1 without additional third-party libraries (which I would like to avoid)?
  • What are the basic steps I have to follow and what are the important .NET namespaces, classes and methods I need to know to achieve this goal (epecially to draw lines and other simple graphical elements "in memory" and convert the result into an byte array in jpg format)?

Thank you for suggestions in advance!

Answer

NakedBrunch picture NakedBrunch · Mar 28, 2011

The following is a full code sample that will use GDI to draw a grid and place a cross (with a red background) just like in the example image below. It uses GDI just like the other answers but the real work takes places by looping through the cells and drawing gridlines.

The following code

byte[] bytes = CreateGridImage(10,10, 9, 9, 30);

will create a 10x10 grid with a cross in the 9x9 position:

enter image description here

A new addition to CreateGridImage() is the addition of a boxSize argument which sets the size of each "square" in the grid

public static byte[] CreateGridImage(
            int maxXCells,
            int maxYCells,
            int cellXPosition,
            int cellYPosition,
            int boxSize)
{
    using (var bmp = new System.Drawing.Bitmap(maxXCells * boxSize+1, maxYCells * boxSize+1))
    {
        using (Graphics g = Graphics.FromImage(bmp))
        {
            g.Clear(Color.Yellow);
            Pen pen = new Pen(Color.Black);
            pen.Width = 1;

            //Draw red rectangle to go behind cross
            Rectangle rect = new Rectangle(boxSize * (cellXPosition - 1), boxSize * (cellYPosition - 1), boxSize, boxSize);
            g.FillRectangle(new SolidBrush(Color.Red), rect);

            //Draw cross
            g.DrawLine(pen, boxSize * (cellXPosition - 1), boxSize * (cellYPosition - 1), boxSize * cellXPosition, boxSize * cellYPosition);
            g.DrawLine(pen, boxSize * (cellXPosition - 1), boxSize * cellYPosition, boxSize * cellXPosition, boxSize * (cellYPosition - 1));

            //Draw horizontal lines
            for (int i = 0; i <= maxXCells;i++ )
            {
                g.DrawLine(pen, (i * boxSize), 0, i * boxSize, boxSize * maxYCells);
            }

            //Draw vertical lines            
            for (int i = 0; i <= maxYCells; i++)
            {
                g.DrawLine(pen, 0, (i * boxSize), boxSize * maxXCells, i * boxSize);
            }                    
        }

        var memStream = new MemoryStream();
        bmp.Save(memStream, ImageFormat.Jpeg);
        return memStream.ToArray();
    }
}