Solved

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

Posted on 2008-06-12
6
13,603 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 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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Magic Software info 18 152
Performance of SQL statement 37 145
Tvertscrollbox like a whatsapp layout delete messages 1 49
DBCtrlGrid, Delphi, Scroll 8 83
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
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…
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 use NetBeans IDE 8.0 for Windows to perform CRUD operations on a MySql database.

739 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