Click here to Skip to main content
13,053,276 members (60,439 online)
Click here to Skip to main content
Add your own
alternative version


45 bookmarked
Posted 10 May 2010

Saving Image Data in an XML File

, 11 May 2010
Rate this:
Please Sign up or sign in to vote.
How to save and retrieve binary image data in an XML file


In a recent Windows Forms project, I needed the ability to import and export graphics data from bitmaps to and from XML files. Since the bitmap data is binary and XML files only allow ASCII, it was apparent that a binary to ASCII conversion would be needed. A review of other articles and an internet search did not turn up anything much to my liking, so I decided to design and implement the needed functions myself. I hope that perhaps my efforts might be useful to anyone else with a similar problem to solve.

The particular application I was working on involved relatively small graphics symbols used in describing oil well cores and geological outcrops. The application stores all data, including symbols, in a database so that projects can be backed up or transferred simply by copying the database. In the application, the graphics symbols are stored as BLOBs or equivalent, however in transferring or sharing symbols between projects it was desirable to be able to save the data to an ASCII file containing all of the symbols needed. In that way, a corporate standard symbol library could be built up and made available with minimal effort.

The main problem in converting image data to and from an XML file format is the encoding of the binary data into an ASCII format that is compatible with XML files. Unfortunately I was unable to find a generic and generally accepted specification for saving binary data in XML files. At first, I decided to use hexadecimal encoding, however it was pointed out that .NET includes a function for Base64 encoding[^]. Since the images I needed to encode were relatively small, most any encoding would probably work, but Base64 is the simplest to implement, since it is already available as a .NET method.

The sample project included with this article contains the VS2008 C# project for reading and writing the XML files, as well as a couple of bitmap files (*.bmp) for testing. The main program allows the bitmaps to be imported and saved to the XML file and also imported from the XML file and displayed on the screen. In the sample project, the methods to create and read the XML files are included in the main form. The code to do the conversions in my real project is embedded in the methods that save and restore graphics symbols to the XML files.

Description of Code

The conversion from Bitmap to XML is done in 2 steps. First the Bitmap data is converted to a byte array, then the byte array is converted to an ASCII Base64 string. This could be coded in a single step, however I chose to use two steps to permit easily changing the encoding later if needed. The resulting string is then be saved as the value of the bitmap attribute of an XML <symbol name="sym_name" bitmap="hexstring" /> node.

In converting the bitmap to a byte array, a format was defined that saves the width and height (in pixels) of the image followed by an array of the pixel colors in order by rows. To accommodate 4 byte integers, the width and height numbers are specified as uints then coded most significant byte (MSB) first into 4 bytes. The pixel colors are extracted from the Bitmap using the GetPixel(i,j).ToArgb() method and the 32 bit color is then encoded in 4 bytes. I've not shown the details of converting width and height, but the brute force code to convert a pixel to 4 bytes is as follows:

// b[] is the byte array defined as
// byte[] b = new byte[4 * (bitmap.Height * bitmap.Width + 2)];
// Loop through each row
for (int j = 0; j < bitmap.Height; j++)
    // Loop through the pixel on this row
    for (int i = 0; i < bitmap.Width; i++)
        x = (uint)bitmap.GetPixel(i, j).ToArgb();
        y = (int)x;
        b[n] = (byte)(x / 0x1000000);
        x = x % (0x1000000);
        b[n] = (byte)(x / 0x10000);
        x = x % (0x10000);
        b[n] = (byte)(x / 0x100);
        x = x % 0x100;
        b[n] = (byte)x;

Once the byte array of the Bitmap data has been created, the simple application of Convert.ToBase64String() yields a string representation. Once the bitmap has been converted to a string, then it can be saved in an XML attribute. A sample of the created XML file is shown below:

    <symbol name="BMP_1" bitmap="AAAAEAAAAA7/wcEA ... " />
    <symbol name="BMP_2" bitmap="AAAACgAAAAf/av9q ... " />
    <symbol name="BMP_3" bitmap="AAAACAAAAAj/AAAA ... " />
    <symbol name="BMP_4" bitmap="AAAAEgAAABP///// ... " />

To read the bitmap data from the XML file and recreate the images, the above procedure is reversed. For each symbol in the XML file, the value of the bitmap attribute is extracted as a normal ASCII string which is then converted into a byte array using Convert.FromBase64String(). Then the bitmap can be reconstructed by extracting the width and height from the first 8 bytes, then each of the pixels from groups of 4 bytes. The code to accomplish this is as follows:

private Bitmap BitmapFromByteArray(byte[] byteArray)
    int n = 0;
    // Get the width
    uint x = (((uint)byteArray[n] * 256 + (uint)byteArray[n + 1]) * 256
           + (uint)byteArray[n + 2]) * 256 + (uint)byteArray[n + 3];
    int width = (int)x;
    n += 4;
    // Get the height
    x = (((uint)byteArray[n] * 256 + (uint)byteArray[n + 1]) * 256
      + (uint)byteArray[n + 2]) * 256 + (uint)byteArray[n + 3];
    int height = (int)x;
    n += 4;
    // Create the Bitmap object
    Bitmap bmp = new Bitmap(width, height);
    // The pixels are stored in order by rows
    for (int j = 0; j < height; j++)
        // Read the pixels for each row
        for (int i = 0; i < width; i++)
            x = (((uint)byteArray[n] * 256 + (uint)byteArray[n + 1]) * 256
              + (uint)byteArray[n + 2]) * 256 + (uint)byteArray[n + 3];
            bmp.SetPixel(i, j, Color.FromArgb((int)x));
            n += 4;
    return bmp;


The code I've presented here is probably not optimized in any way. Certainly there are methods for packing binary data into fewer ASCII characters using techniques more advanced than Base64 encoding. I did not pursue those methods here.

It would seem that with the popularity of the XML data format, there should be a nice specification for saving binary data, such as a Bitmap, in an XML file. Apparently the XML group has at least thought about the problem, for example see Unfortunately, it doesn't appear that a simple specification has ever been formalized, at least not one that I could find. If a more universally accepted way to store binary data in an XML file is found, then I'll be happy to change my code accordingly.

Commenters have asked why the XML CDATA construct was not used to enclose the binary image data. This certainly could be done, but I see no real advantage, so CDATA was not used.


10 May 2010Initial submission
10 May 2010Sure enough, had to fix some typos
11 May 2010Modified to use Base64 encoding, per suggestion from commenters


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Walt Fair, Jr.
Engineer Comport Computing
United States United States
Walt has been playing with software since around 1967 and has generated more runtime errors than the average village idiot. He is a CEO, Petroleum Engineer, software consultant, janitor, and now a graduate student again. Rather than sleep, he also plays with algorithms and systems for technical computing, develops software for engineering evaluations and is an avid amateur radio operator.

Walt was admitted back to UT Austin and is actually attempting to complete a PhD in engineering, thereby proving that he is crazier than the average old fart.

And now UT has gone and admitted Walt to PhD candidacy,now my disertation has been submitted and it is underreview, has been reviewed,so I'm preparing for my defense to I can wrtap things up and graduate. proving that old guys can still ... what was he doing again?

You may also be interested in...

Comments and Discussions

GeneralMy vote of 5 Pin
Member 916682515-Nov-12 2:41
memberMember 916682515-Nov-12 2:41 
GeneralMy vote of 5 Pin
manoj kumar choubey23-Feb-12 19:37
membermanoj kumar choubey23-Feb-12 19:37 
GeneralSmall Change Pin
Rod Kemp17-May-10 14:15
memberRod Kemp17-May-10 14:15 
GeneralRe: Small Change Pin
Walt Fair, Jr.17-May-10 14:38
memberWalt Fair, Jr.17-May-10 14:38 
GeneralInteresting! Pin
thund3rstruck11-May-10 8:47
memberthund3rstruck11-May-10 8:47 
GeneralRe: Interesting! Pin
Walt Fair, Jr.11-May-10 12:37
memberWalt Fair, Jr.11-May-10 12:37 
GeneralMy vote of 1 Pin
SuperToha11-May-10 3:33
memberSuperToha11-May-10 3:33 
GeneralRe: My vote of 1 Pin
Walt Fair, Jr.11-May-10 6:22
memberWalt Fair, Jr.11-May-10 6:22 
GeneralIt might be faster if you do not use GetPixel/SetPixel Pin
Wong Shao Voon10-May-10 23:18
memberWong Shao Voon10-May-10 23:18 
GeneralRe: It might be faster if you do not use GetPixel/SetPixel Pin
Walt Fair, Jr.11-May-10 6:23
memberWalt Fair, Jr.11-May-10 6:23 
GeneralGood idea Pin
alexxksys10-May-10 21:58
memberalexxksys10-May-10 21:58 
GeneralRe: Good idea Pin
Walt Fair, Jr.11-May-10 6:21
memberWalt Fair, Jr.11-May-10 6:21 
GeneralMy vote of 2 Pin
John Brett10-May-10 21:49
memberJohn Brett10-May-10 21:49 
GeneralRe: My vote of 2 Pin
Walt Fair, Jr.11-May-10 4:38
memberWalt Fair, Jr.11-May-10 4:38 
GeneralRe: My vote of 2 Pin
Walt Fair, Jr.11-May-10 6:20
memberWalt Fair, Jr.11-May-10 6:20 
GeneralMy vote of 1 Pin
Pavel Vladov10-May-10 21:11
memberPavel Vladov10-May-10 21:11 
GeneralRe: My vote of 1 Pin
Walt Fair, Jr.11-May-10 6:19
memberWalt Fair, Jr.11-May-10 6:19 
GeneralNice Idea Pin
King Balkoth10-May-10 7:36
memberKing Balkoth10-May-10 7:36 
GeneralRe: Nice Idea Pin
Walt Fair, Jr.10-May-10 7:54
memberWalt Fair, Jr.10-May-10 7:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170713.1 | Last Updated 11 May 2010
Article Copyright 2010 by Walt Fair, Jr.
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid