How to create a big image from a number of smaller ones
After the day before yesterday’s experiment showed that loading a single larger image on an Android phone is nearly three times faster than loading 52 smaller images, I decided to write a short utility program to read all the 52 individual card files and create one file with them laid out neatly in four rows of cards, one row per suite with each card running from Ace to King.
The individual card .png files were all in one folder with two letter filenames rank and suit in capitals like AS.png (Ace of spades), TH.png (Ten of Hearts and so on).
This 62 line C# program reads all 52 files into RAM in a two-dimension array cards (original name eh!) in the method LoadAllImages() then in BuildOneImage() it writes them out in the four rows into the bitmap allcards then saves them out as one .png format file.
C# makes doing this very easy. In C you would have to write your own file format handling code or use a library like libpng.
// Author D. Bolton Learncgames.com You are free to use and copy this program as you wish but please leave this line in.
using System;
using System.Drawing;
using System.Drawing.Imaging;
namespace mpics
{
class Program
{
const int CardWidth = 100;
const int CardHeight = 153;
const string source = "your path here"; // Path to all 52 card files
const string dest = "target file here"; // Path + filename for target .png file.
const string suits = "HCDS";
const string ranks = "A23456789TJQK";
static Bitmap[,] cards = new Bitmap[13,4];
static Bitmap allcards = new Bitmap(CardWidth * 13,CardHeight * 4);
static void Main(string[] args)
{
LoadAllImages();
BuildOneImage();
}
private static void BuildOneImage()
{
Console.WriteLine();
var aty = 0.0f;
using (Graphics g = Graphics.FromImage(allcards))
{
for (var y = 0; y < 4; y++)
{
var atx = 0.0f;
for (int x = 0; x < 13; x++)
{
var r = new Rectangle((int)atx, (int)aty, CardWidth, CardHeight);
g.DrawImage(cards[x,y],r);
atx += CardWidth;
}
aty += CardHeight;
}
}
allcards.Save(dest, ImageFormat.Png);
}
private static void LoadAllImages()
{
var i = 0;
foreach (char c in suits)
{
var j = 0;
foreach (char r in ranks)
{
var s = source + r + c+".png";
cards[j++,i] = (Bitmap)Bitmap.FromFile(s);
}
i++;
}
}
}
}
Don’t forget to set the source and dest path constants. This was compiled in Visual Studio 2019 and run on Windows 10. The only really important thing I found was using the Rectangle r in BuildOneImage(). If I used just atx and aty and didn’t specify the size of card then DrawImage() drew much smaller images into the bitmap. I’m not sure why as the card images when loaded from disk were 100 wide by 153 deep, the same as specified in the constants CardWidth and CardHeight.
The card images were originally downloaded from the American Contract Bridge League but were much bigger so I scaled them first to 100 x 153 pixels. There are many free playing card images on the web but these are one of the nicer sets.




Loading resources into RAM on a smartphone can be a relatively slowish process. I’d been working on a card game and had both a set of 52 individual playing cards plus a sheet of 52 in one image. I have two Android phones so used the opportunity to test which is quicker loading 52 small images or one larger image. MonoGame ‘s Draw routines can copy from part of an image; you just specify the source.
I was around when space invaders came out in the late 70s and played it a bit, although I preferred Galaxian, Gorf, Defender and Battle Zone (3D Tanks on the moon- vector graphics).

When I started this blog at the end of February it was to assist sales of my ebooks. The one written and the one being written. Things have changed a bit and the one being written is now the Raspberry Pi book. That book is still being written but it’s not as high a priority now.

In the asteroids game and shortly in my MatchThree game, I’ll be creating a level data array of struct. This has a struct for each level containing a count of particular features for that level.