Skip to content

Base64 encode and decode images in Delphi

Quite some time ago, I blogged about how to encode and decode data as Base64. The post is still accessed on a regular basis. However, I have received a question multiple times and want to provide the solution: How can images be encoded and decoded?

The key lies in the polymorphism of TPicture that allows you to implement a solution that is not even depending on one file format. Developers often make the mistake to use TBitmap . At that moment you become set on bitmaps.

The solution I present here will allow you to encode any binary data as Base64. In order to encode images, one has to write the image data as binary. Obviously, we do not interpret the file format at any time. Still, it is possible to display the image after decoding as the VCL is pretty smart 😉

Let’s build a VCL Form application with the following main form:

Screenshot

I used a TAdvMemo from TMS Software as it shows line numbers and a gutter. It looks nicer, but can also be replaced with a standard TMemo in this case.

The two buttons will either load an image and generate the Base64 encoded text in the memo or load a Base64 text and show the decoded image.

Here’s the source code for encoding the image file:

procedure TFrmMain.btnLoadImageClick(Sender: TObject); 
var 
  LInput : TMemoryStream; 
  LOutput: TMemoryStream; 
begin 
  // show open file dialog 
  if 
    dlgOpen.Execute then 
    begin 
    // load image into image component (TPicture) 
    Image.Picture.LoadFromFile(dlgOpen.FileName); 
    LInput := TMemoryStream.Create; 
    LOutput := TMemoryStream.Create; 
    // write picture to stream and encode
    try 
      Image.Picture.SaveToStream(LInput); 
      LInput.Position := 0; 
      TNetEncoding.Base64.Encode( LInput, LOutput );
      LOutput.Position := 0; 
      Memo.Lines.LoadFromStream( LOutput );
    finally 
      LInput.Free;
      LOutput.Free;
    end; 
  end; 
end;

We use the TPicture property of the TImage component on the form. Of course, we could use a TPicture object that we create ourselves as well to make the method independent of our GUI. However, for a demo this will suffice. Key is to save the picture to the stream. Do not use a bitmap, etc. – use TPicture . The Base64 algorithm does not care for the input as long as it is a TStream . The memo then loads the data from the stream to display it.

The other direction works just the same way:

procedure TFrmMain.btnLoadTextClick(Sender: TObject); 
var 
  LInput: TMemoryStream;
  LOutput: TMemoryStream; 
begin 
  if dlgOpen.Execute then 
  begin
    Memo.Lines.LoadFromFile(dlgOpen.FileName);
    LInput := TMemoryStream.Create;
    LOutput := TMemoryStream.Create;
    try
      Memo.Lines.SaveToStream(LInput);
      LInput.Position := 0; 
      TNetEncoding.Base64.Decode( LInput, LOutput ); 
      LOutput.Position := 0; 
      Image.Picture.LoadFromStream(LOutput);
    finally
      LInput.Free;
      LOutput.Free;
    end;
  end;
end;
Instead of Encode, we call Decode for the Base64 class, of course. Otherwise, we load the text into the memo, save its contents to a stream and then decode that stream. The stream then is loaded into the TPicture property.

Again, be aware that this works for PNG, JPEG, … or whatever file format you include in your binary. For this demo, I included the following units in my project file so that I can use JPEG and PNG:

program prjImageToBase64;
uses 
 jpeg,
 pngimage,
 Vcl.Forms, 
 uFrmMain in 'uFrmMain.pas' {FrmMain};
Of course, the Base64 encoding classes are found in the System.NetEncoding unit:

var 
  FrmMain: TFrmMain; 
implementation 
uses System.NetEncoding;
Here’s an example what an encoding of a picture looks like:

Screenshot