Solved

Delphi: How to decode Base64 encoded string into viewable bitmap image

Posted on 2008-06-12
6
13,231 Views
Last Modified: 2013-11-23
Hi,

I'm referring to previous question titled Decode hex text file into viewable bitmap image, which targeted VB.NET development.
http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_22710540.html

Does anybody know how to perform similar task in Delphi?

I also have a string encoded in Base64 , which is the result of capturing a signature image from a PDA. The string looks like below:

PRY7FTcUNBQyFjEYMhozHDYcNx84ITYjMyQxJS8kLSQtJP//QxJCFEIWQhlBG0EdQR9BIUMfQx///1YOVhBUD1IQUBBNEUwTSxZMGE0aTxxRHFMeVR9XHlgbWBlWGFMYURhPGE8Y//9gGl8YXxZfFF8SYBBgDmIPYxFkFGUXZhloFmgUaRFqDmoMagpqCv//Rz1HP0dBR0RGRkZJRktGTUZN//9NPE4+TkBOQ09FT0dQSlFMUEpPR09FTURLRUlFR0RHRP//WzxZO1Y9VD1SP1JBUkNTRVVHWEhaSFpI//9aQVhBVkFTQVFAUUD//2NEY0FiP2I8YjpiOGQ2ZjVoN2o5aztqPWk/Z0BkQGI+Y0BlQWdCakNsQ25EbkT//3w0eTR3NXQ2cjdwOW87cD1yP3RAdkJ4QnpDekP//3k5dzp1OnM6cTpuOW45//8=

here is what the PDA vendor says about the file:
-----------------------------------------------------------------
Ok, the data coming in is basically a list of lines to draw.

To make the data in the first place, a series of points that would create the lines of the signature are recorded, where any pen lift (i.e. the drawing stopped) is recorded as 255,255 to serve as a terminator.

This array of points is turned into a byte array (i.e. line from 2,3 to 40, 50 to 80, 3 becomes byte[] {2,3,40,50, 80, 3} )

This is run through a Microsoft call Convert.ToBase64String to cut down on size (ever seen how big an xml encoded byte array is?) and make it easier to pass the data back into a webservice via a string parameter.  The data will need to be de-converted from this form to get the byte array back out, that is then used to draw the lines in the code sample you supplied.
-----------------------------------------------------------------

How to convert this string back into a viewable Bitmap image using DELPHI? How about in PHP?

I believe that from the byte array, each pair is a point. So to draw the signature you just draw the points. So byte[0] =  31 and byte[1] = 102 is point 1. Then you would draw a line from this point to the next point which is byte[2] and byte[3] and then you would draw a line from this to the next point and so on.

They also sent us a function (in C#) to draw the byte array but how to convert this function into Delphi and PHP?

thanks
Anthony
using System;

using System.Drawing;

using System.Collections;

 

namespace ADS.WorkstationPC

{

	/// <summary>

	/// Summary description for SignatureToBitmap.

	/// </summary>

	public class SignatureToBitmap

	{

		private static SignatureToBitmap UniqueBitmap = new SignatureToBitmap();

		private SignatureToBitmap()

		{

			//

			// TODO: Add constructor logic here

			//

 

		}

		public static Bitmap GetBitmap(byte[] rawsignature)

		{

			Bitmap bmSignature = new Bitmap(254, 254);

			Graphics gr = Graphics.FromImage(bmSignature);

			Pen pen = new Pen(new SolidBrush(Color.Black), 1);

			ArrayList alline = new ArrayList();

			ArrayList alpoint = new ArrayList();

 

			foreach (byte abyte in rawsignature)

			{

				alpoint.Add((int)abyte);

				if (alpoint.Count > 1)

				{

					Point apoint = new Point((int)alpoint[0], (int)alpoint[1]);

					alpoint.Clear(); // clear the array list

					alline.Add(apoint); //adds to the end of the array list

					if (apoint.X == 255) 

						alline.Clear();

                    else if (alline.Count > 1)

					{

						Point firstpoint = (Point)alline[0]; //?

						alline.RemoveAt(0); // removes the element at that index

						gr.DrawLine(pen, firstpoint, apoint);

					}

				}

			}

 

			return bmSignature;

		}

	}

}

Open in new window

byte-array.gif
signature.gif
encodedstring.gif
0
Comment
Question by:COS_IT_AU
  • 3
6 Comments
 
LVL 45

Expert Comment

by:aikimark
ID: 21783706
Is the Base64 decoding a problem?  If so, please look at the decoding routine found on this Torry's page:
http://www.swissdelphicenter.ch/torry/showcode.php?id=1524

When you reach this statement:
     x := x mod 256;
You will have the numeric value you seek.  You do not need the next statement to convert this numeric value into a character.  Just add the numeric value to a byte array or list.

Then use the numeric value pairs to paint on a canvas, using a series of .LineTo() and .MoveTo() methods.
References and Tutorials:
http://www.ibrtses.com/delphi/graphicedit1.html
http://www.functionx.com/delphi/gdi/drawing101.htm
http://delphi.about.com/library/bluc/text/uc052102b.htm

After the painting, you will have a bitmap.

Since Base64 uses more characters than bytes, you will be safe to allocate a byte array the same size as the number of characters.
0
 
LVL 26

Accepted Solution

by:
EddieShipman earned 125 total points
ID: 21950139
I used SZCodeBaseX (http://www.szutils.net/download.php?ID=2) to encode and decode a small GIF file. Since it was a GIF, I also needed TGIFImage from Torry's
(http://www.torry.net/vcl/graphics/gif/gifimaged7f.zip)

It also worked on a JPG file.
Now, the base64 code that I got came back different than yours. If you could have posted your exact B64 code, then I could test it.

Do you know what extension the file getting from the PDA is?

unit Unit1;
 

interface
 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls, ExtCtrls, GIFImage;
 

type

  TForm1 = class(TForm)

    btnEncode: TButton;

    btnDecode: TButton;

    Image1: TImage;

    Memo1: TMemo;

    procedure btnEncodeClick(Sender: TObject);

    procedure btnDecodeClick(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;
 

var

  Form1: TForm1;
 

implementation
 

uses SZCodeBaseX;
 

{$R *.dfm}
 
 

procedure TForm1.btnEncodeClick(Sender: TObject);

var

  ss: TStringStream;

  sl: TStringList;

begin

  sl := TStringList.Create;

  ss := TStringStream.Create('');

  try

    SZEncodeBase64('C:\image10.gif', ss);

    Memo1.Lines.Text := ss.DataString;

    ss.Position := 0;

    sl.LoadFromStream(ss);

    sl.SaveToFile( 'C:\DelphiEncode.txt' );

  finally

    sl.Free;

    ss.Free;

  end;

end;
 

procedure TForm1.btnDecodeClick(Sender: TObject);

var

  strm: TFileStream;

  ss: TStringStream;

  sl: TStringList;

  s: string;

  GIF: TGIFimage;

begin

  strm := TFileStream.Create( 'C:\delphi-Decode.gif', fmCreate );

  sl := TStringList.Create;

  ss := TStringStream.Create(s);

  try

    strm.Position := 0;

    sl.LoadFromFile( 'C:\DelphiEncode.txt' );

    s := sl.Text;

    SZDecodeBase64(ss, strm);

  finally

    sl.Free;

    ss.Free;

    strm.Free;

    GIF := TGIFImage.Create;

    try

      GIF.LoadFromFile('C:\delphi-Decode.gif');

      Image1.Picture.Assign(GIF);

    finally

      GIF.Free;

    end;

  end;

end;
 

end.

Open in new window

0
 
LVL 26

Expert Comment

by:EddieShipman
ID: 21968494
Anthony, have you tried this code? Do you have any more input?
0
 
LVL 26

Expert Comment

by:EddieShipman
ID: 22221591
It's been over a month, have you tried this, yet? Please accept my answer if it worked for you.
0
 

Author Closing Comment

by:COS_IT_AU
ID: 31501471
Hi Eddie, sorry for the delayed response.... Cheers!
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Delphi application Soap connection 5 96
How to call a form that is in a DLL  from an application? 13 64
Copying WordPress Pages 5 76
tidtcpserver connection lost handle 2 70
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Jaspersoft Studio is a plugin for Eclipse that lets you create reports from a datasource.  In this article, we'll go over creating a report from a default template and setting up a datasource that connects to your database.
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.

912 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now