Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 14203
  • Last Modified:

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

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
COS_IT_AU
Asked:
COS_IT_AU
  • 3
1 Solution
 
aikimarkCommented:
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
 
EddieShipmanCommented:
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
 
EddieShipmanCommented:
Anthony, have you tried this code? Do you have any more input?
0
 
EddieShipmanCommented:
It's been over a month, have you tried this, yet? Please accept my answer if it worked for you.
0
 
COS_IT_AUAuthor Commented:
Hi Eddie, sorry for the delayed response.... Cheers!
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now