Solved

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

Posted on 2008-06-12
6
13,788 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
6 Comments
 
LVL 46

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

[Webinar] How Hackers Steal Your Credentials

Do You Know How Hackers Steal Your Credentials? Join us and Skyport Systems to learn how hackers steal your credentials and why Active Directory must be secure to stop them. Thursday, July 13, 2017 10:00 A.M. PDT

Question has a verified solution.

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

Programmer's Notepad is, one of the best free text editing tools available, simply because the developers appear to have second-guessed every weird problem or issue a programmer is likely to run into. One of these problems is selecting and deleti…
How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org Go to that link and select download selenium in the right hand column That will then direct you to their download page. From that p…
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.
Suggested Courses
Course of the Month5 days, 14 hours left to enroll

627 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