Contents

1.0 - Introduction
2.0 - The RFC 2397 data URL
3.0 - Image to Base64 converter
4.0 - Summary
5.0 - Notes/Links


Download source code (Visual Studio 2008, C#): Solution_Base64Encoder_01.zip [44 kB].

Environment: .NET Framework 2.0. Internet Explorer 8, Firefox 3.2, Opera 10.0 or later.


1.0 - Introduction

With inline Base64 images it is possible to embed (small) images directly in (X)HTML pages without using a link to a file on disk. The encoded image is slightly bigger than the original but HTTP(S) requests are simplified and performance is improved. This can play a role on busy wireless networks.
All the major browsers support inline Base64 encoded images following the RFC 2397 data URL specification [1]. With Internet Explorer 8.0 as last one to join this bandwagon (IE6 and IE7 have no support for this) it is useful to have a look at this technique.

This is the first part of two articles. Here we will look at the data URL specification and an image to Base64 converter is given, with an example how to embed the code as inline image in HTML.

The second part gives more details about conserving transparency and meta data in image files when they are converted to Base64 and also a Base64 to image converter for testing purposes.


2.0 - The RFC 2397 data URL

The RFC 2397 data URL specification [1] contains a description how to embed encoded data in (X)HTML as an alternative for external files. One implementation is to add data as Base64 code to the src attibute of an image element (<img src="data" />). The result is an inline image which is directly loaded with the page.


2.1 - Specification and use

The 'data' URL scheme allows inclusion of small data items as 'immediate' data, as if it had been included externally.

The URLs are of the form:

data:[<mediatype>][;base64],<data>

The <mediatype> is an Internet media type specification (with optional parameters.) The appearance of ';base64' means that the data is encoded as base64.

When data is added to an img element, the mediatype is an image mime type, like 'image/gif' or 'image/bmp [2].

In the following list the mime types for the most of the common image file formats:


 Table 1 - Image mime types.
Extension Mime type Description
.bmp image/bmp Windows Bitmap Graphics
.emf image/x-emf Extended (Enhanced) Windows Metafile Format
.exif ?? Exchangeable image file format
.gif image/gif Graphic Interchange Format
.jpe image/jpeg JPEG Image
.jpeg image/jpeg JPEG Image
.jpg image/jpeg JPEG Image
.png image/png Portable Network Graphics
.tif image/tiff Tagged Image Format File
.tiff image/tiff Tagged Image Format File
.ico image/x-icon Icon
.wmf image/wmf Windows Metafile


In this selection in fact the image formats available from the ImageFormat class (System.Drawing.Imaging) as they will be used later in the code.

This is an example of a data URL as it can be embedded in an HTML document:


  HTML - A 16x16 px inline image (File_Open_02.png: ).

 <img src="data:image/png;base64,
 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABh0RVh0
 U29mdHdhcmUAUGFpbnQuTkVUIHYzLjM2qefiJQAAAIJJREFUOE+dkssRgDAIRM3FEimYxnRgxPBJ
 CAkXFfcBy9CuWjxK1mpIV2mYsvLt81t1CTYFJJE9pYPWcK4Ch456Xv6ZhWpCwtubTQsgYhi5XMDB
 wSoA8CKHE6xgY8vvQMP07sPbMhPswJ+2WziB/x2cwuGQVp5l7HBIlYscweVTnsEvbhJ7HUX6hdEA
 AAAASUVORK5CYIIAAAAAAAAAAAAAAAAAAAAAAA==" 
 width="16" height="16" name="File_Open_02" />


Apart from the src attribute, the <img /> element can have any other attribute as usual, in this example width, height and name.


2.2 - Base64 encoding

Base64 code is 64-based (hence the name). Groups of 24 bits (3 x 8 bits) from the source data are split into 4 groups of 6 bits each, and the 6-bit digits are then encoded with the 'Base64 alphabet' [RFC 2045 - part 1]. This is a table with 64 characters A..Z, a..z, 0..9 and +,/ for all the possible 6-bit digits 000000, 000001 ... 111111. When needed, extra "=" characters are added at the end of the code for padding to ensure the result has always a multiple of 4 characters.


 Table 2 - Base64 alphabet.
Decimal Binary Base64
0 000000 A
1 000001 B
2 000010 C
3 000011 D
4 000100 E
5 000101 F
6 000110 G
7 000111 H
8 001000 I
9 001001 J
10 001010 K
11 001011 L
12 001100 M
13 001101 N
14 001110 O
15 001111 P
16 010000 Q
17 010001 R
18 010010 S
19 010011 T
20 010100 U
21 010101 V

Decimal Binary Base64
22 010110 W
23 010111 X
24 011000 Y
25 011001 Z
26 011010 a
27 011011 b
28 011100 c
29 011101 d
30 011110 e
31 011111 f
32 100000 g
33 100001 h
34 100010 i
35 100011 j
36 100100 k
37 100101 l
38 100110 m
39 100111 n
40 101000 o
41 101001 p
42 101010 q
43 101011 r

Decimal Binary Base64
44 101100 s
45 101101 t
46 101110 u
47 101111 v
48 110000 w
49 110001 x
50 110010 y
51 110011 z
52 110100 0
53 110101 1
54 110110 2
55 110111 3
56 111000 4
57 111001 5
58 111010 6
59 111011 7
60 111100 8
61 111101 9
62 111110 +
63 111111 /
-    
-    


In the following example the word "How" is converted to Base64 as "SG93":


  Text to Base64.

  Char    H        0        w
  ASCII   72       111      119
  Bin     01001000 01101111 01110111     <-- 3x 8-bit digits

  Bin     010010 000110 111101 110111    <-- 4x 6-bit digits
  Base64  S      G      9      3


The ASCII values of the characters are converted to bin (3x8 bits). The bits from 3 bytes is split into 4 groups of 6 bits. The 6-bit digits are then encoded with the table.
Because three characters are always encoded to four, the result is 4/3 (33%) larger. When working with images, however, compression plays also a role in the final result (jpg, png).

With this recipe we could make our own converter but it is easier to use the ToBase64String method from the System.Convert class (and the FromBase64String method for decoding), as is done in the code below. These methods, and all the other methods 'in the wild' all use the same rules defined by the RFC 2397 specification. So, Base64 code is exchangeable between applications.


2.3 - Maximum size

The size of data URIs is limited in some browsers. IE8 for example has a limit of 32,768 characters [4].
A test was done with IE 8 (8.0.6001.18702), Firefox 3.5.3 and Opera 10.0. A large wallpaper, 1600x1200 px, 309 kB was converted to Base64, resulting in almost 690k characters. This inline image was added to a HTML page and opened in the browser.
IE8 only displays the first part of the image (probably 32,768 characters), Firefox and Opera are showing the complete image.
When searching for information about maximum data size, Opera is often mentioned with a limit of 4100 characters, but this is apparently for older versions.

It is often said that inline images should be limited to small images, for example icons. In practice, however, often much larger images are used. Examples are the Google news pages with 80x80 px standard images (about 3000 characters), some pages contain more than 20 of them. We also see that all modern browsers support large data URLs which is a deviation from earlier policies.


3.0 - Image to Base64 converter

For making Base64 inline images which can be added to a webpage, an image to Base64 converter was made for converting regular images to data URLs. The converter has two parts, a function for opening an image from file as Bitmap, and a function for converting the Bitmap to Base64 code. The Base64 code can be added as data URL to an <img /> tag in (X)HTML.


  C# - Bitmap to Base64 converter

  using System.Drawing;
  using System.Drawing.Imaging;  // ImageFormat.
  using System.IO;
  [...]

  // ---------------------------------------------------------------
  // Date      230909
  // Purpose   Convert a bitmap to Base64 code.
  // Entry     oBitmap - The bitmap to convert.
  // Return    The bitmap as Base64 code. 
  // Comments  1) The base64 encoded bitmap is stored as PNG.
  //           2) The output-code contains a linebreak after 
  //           every 76 characters.
  // ---------------------------------------------------------------
  private string BitmapToBase64(Bitmap oBitmap)
  {
      Byte[] bytData = null;
      using (MemoryStream ms = new MemoryStream())
      {
          oBitmap.Save(ms, ImageFormat.Png);
          bytData = ms.GetBuffer();
      }
      return Convert.ToBase64String(bytData,
          Base64FormattingOptions.InsertLineBreaks);
  }

Use:

  C# - Using the converter.

  using System.Windows.Forms;
  using System.Drawing;
  using System.IO;
  [...]

  private TextBox txtBox1 = new TextBox();
  private PictureBox picBox1 = new PictureBox();
  [...]
  
  string sFile = @"D:\Images\Dog_01_16.png";
  Bitmap oB = FileOpenBitmap(sFile);
  string sBase64 = BitmapToBase64(oB);
  // Show Base64 code.
  txtBox1.Text = sBase64;
  // Show as Bitmap.
  picBox1.Image = (Image)oB;
  [...]

  // Open an image from file as Bitmap.
  private Bitmap FileOpenBitmap(string sFileName)
  {
      if (File.Exists(sFileName))
      {
          Bitmap oB1 = new Bitmap(sFileName);
          // Unlock file, remove meta data.
          Bitmap oB2 = new Bitmap(oB1);
          oB1.Dispose();
          return oB2;
      }
      else
      {
          return null;
      }
  }

Result:

  TXT - A 16x16 px image as Base64 code (Dog_01_16.png).

  iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
  jwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAFxJREFU
  OE9jYCAM/gMBC2Fl+FX8B0pjYJjBIAl8AKvmhoYGmDjYZJINQHIRdQzA6kxs/sYihhk4BDRieJdU
  24eAAXAnAhMKE7ZAQ/cDehiQKo8RC/QxADmDDawXAEtSnvGhRnkbAAAAAElFTkSuQmCCAAAAAAAA
  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==

As inline image for adding to HTML:

  HTML - Inline image with a data URL (Dog_01_16.png).

  <img src='data:image/png;base64,
  iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
  jwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAFxJREFU
  OE9jYCAM/gMBC2Fl+FX8B0pjYJjBIAl8AKvmhoYGmDjYZJINQHIRdQzA6kxs/sYihhk4BDRieJdU
  24eAAXAnAhMKE7ZAQ/cDehiQKo8RC/QxADmDDawXAEtSnvGhRnkbAAAAAElFTkSuQmCCAAAAAAAA
  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==' />


This image can be added to any HTML or XHTML page in the same way as a normal image (see the source of this page):





Fig. 3.1 - Bitmap to Base64.

The original image (left) is converted to Base64 code, which is then added as data URL to an inline image (right, see the source of this page).


The images are placed on a background with lines (using CSS) to show that the transparent background is conserved.


4.0 - Summary

Data URLs, as defined by RFC 2397 are used to embed 'immediate' data in a webpage as an alternative for linked files. When the data URL scheme is used for an image, with the src attribute, it is directly included in an (X)HTML page as inline image. This is now a viable option since all major browsers support inline images with data URLs, including Internet Explorer 8.
Because binary data from an image is added as Base64 code to the data URL, a tool is needed to convert images to Base64 code. In this discussion, some background information is given how to use data URLs and a function is given for converting images to Base64 code.


5.0 - Notes/Links


[1] RFC 2397 - Data URL specification.
http://www.ietf.org/rfc/rfc2397

[2] RFC 2045 - Multipurpose Internet Mail Extensions (MIME), Part 1.
Format of Internet Message Bodies - Base64 Content-Transfer-Encoding (Page 24). http://www.ietf.org/rfc/rfc2045

[3] RFC 2046 - Multipurpose Internet Mail Extensions (MIME). Part 2.
Media Types. http://www.ietf.org/rfc/rfc2046
http://mimetypes.info/images.htm

[4] Internet Explorer 8, Data Protocol.
Specifies a data URI, which is a resource, typically an image, embedded in the URI as opposed to one loaded from an external URL.
http://msdn.microsoft.com/en-us/library/cc848897%28VS.85%29.aspx