KRIS-Norway
KRIS-Norway

Reputation: 15

Delphi 7 BASE64 function to make a showable <img src="data: image/jpg; data, xxxx -/> string

I'm trying to make this function in Delphi7

Function CreateBase64String(FileName:String):Base64String; 

Have tried INDY 6-7 and 9 - but INDY (6-7--9) gives me nothing but errors. Don't know why.

After a lot of trouble I have finally made this:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs, ExtDlgs, StdCtrls, Jpeg;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    select: TButton;
    Label1: TLabel;
    Label2: TLabel;
    ToB64: TButton;
    OpenPictureDialog1: TOpenPictureDialog;
    DecBtn: TButton;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure ToB64Click(Sender: TObject);
    procedure selectClick(Sender: TObject);
    procedure DecBtnClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1  : TForm1;
  Curdir : string;

implementation

Uses
   EncdDeCd;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
   Curdir := ExtractfileDir(Application.ExeName);
end;

procedure TForm1.ToB64Click(Sender: TObject);
var
   instream, oustream :  TMemoryStream;
begin
   instream := TMemoryStream.Create;
   instream.LoadFromFile(Edit1.text);
   oustream := TMemoryStream.Create;
   EncodeStream(instream,oustream);
   instream.Free;
   oustream.SaveToFile(Edit2.Text);
   oustream.Free;
end;

procedure TForm1.selectClick(Sender: TObject);
begin
   Edit1.Text := '';
   if OpenPictureDialog1.Execute then
      begin
         Edit1.Text := OpenPictureDialog1.FileName;
         Edit2.Text := ChangeFileExt(Edit1.Text,'.b64');
      end;
end;

procedure TForm1.DecBtnClick(Sender: TObject);
var
   instream, oustream : TMemoryStream;
   s                  : string;
begin
   instream := TMemoryStream.Create;
   instream.LoadFromFile(Edit2.text); //b64 file
   oustream := TMemoryStream.Create;
   DecodeStream(instream,oustream);
   instream.Free;
   s := Edit1.Text;
   insert('x',s,pos('.',s));        // sæt et 'X' på org filen
   oustream.SaveToFile(s);
   oustream.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
VAR
   Ofile : TextFile;
   ifile : TextFile;
   Istr  : string;
begin
   Edit1.Text := Curdir + '\sunset.jpg';
   Edit2.Text := Curdir + '\sunset.b64';
   ToB64Click(NIL);
   AssignFile(Ofile,curdir + '\TESTABCDEF.HTML');
   Rewrite(ofile);
   Writeln(ofile,'<HTML><BODY>');
   Write(ofile,'<img src="DATA:IMAGE/JPG; base64,');
   Assignfile(ifile,edit2.Text);
   Reset(ifile);
   While not Eof(Ifile) DO
      BEGIN
         Readln(Ifile,Istr);
         Write(ofile,Istr);
      END;
   Closefile(ifile);
   Writeln(ofile, '" height="100" width="100" />');
   Writeln(Ofile,'</body></html>');
   Closefile(ofile);
   DecBtnClick(NIL);
end;

END.

But no matter what I do, the OFILE (TESTABCDEF.HTML) don't show up correctly in my webbrowsers (Firefox and IE8).

The AssignFile-stuff is for test purposes only. Normally I use Streams.

Tried big JPEG's --> Error Tried small JPEG's --> Error!

Can anybody tell me What I'm doing wrong?

Kris / Norway

Upvotes: 0

Views: 3198

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 595377

Indy's base64 encoder works just fine, you probably just are not using it correctly.

Uses
  ..., IdCoderMIME;

Function CreateBase64String(FileName: String): String; 
var
  Fs: TFileStream;
begin
  Fs := TFileStream.Create(FileName, fmOpenRead);
  try
    Result := TIdEncoderMIME.EncodeStream(Fs);
  finally
    Fs.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Ofile : TextFile;
begin
  AssignFile(Ofile,curdir + '\TESTABCDEF.HTML');
  Rewrite(ofile);
  Writeln(ofile,'<HTML><BODY>');
  Write(ofile,'<img src="data:image/jpeg;base64,');
  Write(ofile, CreateBase64String(Curdir + '\sunset.jpg'));
  Writeln(ofile, '" height="100" width="100" />');
  Writeln(Ofile,'</body></html>');
  Closefile(ofile);
end;

I would even go as far as getting rid of the TextFile and use a TFileStream instead, so that Indy can write its base64 output directly to your target file and not waste memory putting it in a String first:

Uses
  ..., IdCoderMIME;

procedure WriteBase64String(ADest: TStream; FileName: String);
var
  Fs: TFileStream;
begin
  Fs := TFileStream.Create(FileName, fmOpenRead);
  try
    TIdEncoderMIME.EncodeStream(Fs, ADest);
  finally
    Fs.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Ofile : TFileStream;
begin
  Ofile := TFileStream.Create(curdir + '\TESTABCDEF.HTML', fmCreate);
  try
    // WriteStringToStream() is an Indy function...
    WriteStringToStream(Ofile, '<HTML><BODY>'+EOL);
    WriteStringToString(Ofile, '<img src="data:image/jpeg;base64,');
    WriteBase64String(Ofile, Curdir + '\sunset.jpg');
    WriteStringToStream(Ofile, '" height="100" width="100" />'+EOL);
    WriteStringToStream(Ofile, '</body></html>'+EOL);
  finally
    Ofile.Free;
  end;
end;

Upvotes: 1

Related Questions