Sign in Join
Wiki copytemporary

Base64: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Base64

OldNewLine
1+Various code examples to handle Base64 encoded strings.
2+
3+## Contents
4+
5+ * 1 Convert Base64 string to picture, 1
6+ * 2 Convert Base64 string to picture, 2
7+ * 3 Convert Base64 string to picture, using BGRABitmap
8+
9+# Convert Base64 string to picture, 1
10+
11+Example from forum member **wp**.
12+```
13+uses
14+ Classes, Base64;
15+
16+ procedure DecodeBase64ToStream(AStream: TStream; const s: string; strict: boolean=false);
17+ var
18+ SD: String;
19+ InStream: TStringStream;
20+ Decoder: TBase64DecodingStream;
21+ begin
22+ if Length(s)=0 then
23+ Exit;
24+ SD := S;
25+ while Length(Sd) mod 4 > 0 do
26+ SD := SD + '=';
27+ InStream:= TStringStream.Create(SD);
28+ try
29+ if strict then
30+ Decoder:=TBase64DecodingStream.Create(InStream, bdmStrict)
31+ else
32+ Decoder:=TBase64DecodingStream.Create(InStream, bdmMIME);
33+ try
34+ AStream.CopyFrom(Decoder, Decoder.Size);
35+ AStream.Position := 0;
36+ finally
37+ Decoder.Free;
38+ end;
39+ finally
40+ InStream.Free;
41+ end;
42+ end;
43+
44+ var
45+ base64String: String =
46+ 'iVBORw0KGgoAAAANSUhEUgAAARIAAAAdCAYAAABmFuNCAAAFPElEQVR4Xu2cy5oiIQyFdaPP'+
47+ 'PCt1Nc9sbxyRTlcqJuFAYdvf9HGjllSAQ/grXGR/vV5vO76oABWgAhsU2BMkG9TjrVSACjwU'+
48+ 'IEjoCFSACmxWwAXJ4XDY7fe73fX6scpg1nVtNLLZWzPEzqzyM6/3+sasdkT8kHlVlVo+/wSS'+
49+ '4/Hv7nY71XBlf7nD5M/j86zruvEimzW/Q8oSDbnMjhiZVX7m9V7fmNWOiB8yr7zvaw3diKQI'+
50+ 'WF4CEd0ZZ1y3jahtaoDcgmngEi3JS4ASlTnL6zvrxbyqU7Z0QNLM8k/mtb2Pi4bT50hKCHSP'+
51+ 'ZR72Pz6uaVRhfxSIWIDs7+Q4n8+706k+Db8K/wkUOwTrypSJqQAV2KzAVJBoiPSCpEAkikCK'+
52+ 'rQKTm5NAohPCZLMv0AAVGFZgGkgsROpkLRaRaIhE0Yet4eVyeUQpAhdvcnhYFd5IBahAlwJT'+
53+ 'QLIFIqW0Nhqx0YdEHTog8dIwKulqeyamAtMU2AySGRAptfGGNRUgF1PZU5L2eVlymlI0RAWo'+
54+ 'QKgADJIKjDKBWveWWICUaz3DGSmRXmLTpfQhIikimCzL1bbGx+Px65I35Cq/y3WdVm4qv9nr'+
55+ '0dAty0vnU6OxJV/9vVVer0Uz217Zo3oi/SXSArmODnmjOuo2yTRE6qHTSNk9P4h8I0ub5Y+2'+
56+ 'ldaq1ye89JGNKK3NP2q7Jkg8YHgCjUCkOsGyb2UNkhqJlD0tZT+LvEsa2eti77FL1guw1qDw'+
57+ 'GsiK1Or0kaNYKLXykvTRfbYcWb7lN+3c3mcPsr2d2wOvwHaWjq1yat2ieqMw8bRvXfN8ywNb'+
58+ 'D/SzBwvaqTOfR+qEpLF1SkHyaohokJTJU728q+HhwWTZNFfXgMukq95Alzkh2mG9RtV2s4gk'+
59+ '6sxyf+tJY5+OSIewQPI6u+5wUUfoycvaQJ5siH0UlrrjekBG8/L0jjqUbUMU9LosSETSCw7E'+
60+ '5xFIjDxAGyBZhgNRgyzLr9gKzXNla0RSJk8FCOW9QKF+X0ck+rvYEgiNgiSCw4ig2rHRzzad'+
61+ 'dTiv83vtEUUJmf3Wb60OjXSqrFxoR880yQDaa18DBYXibJBIm2htRzSMyt9qsxG/D0HyHdFI'+
62+ 'FSwe2kQQEcBYJxkFSRT+jwjagscItFBHbT3lkAgK7XhoCO6BCq2PLQuS50gkF7WZV07kGlI/'+
63+ 'pC66XCO+2CprFMEhUctT34uOEUBBUgz27mBdP10ikJRUdRPaeo7kfL9+C1Zu+iZbrdN536Mh'+
64+ 'SBYlZE8COzmXQcw+OVqdvAUSFGKtfDI46LprjaLrSF5eNGJtbx0G6Cggm1dC6ofON3l+osth'+
65+ 'fSxKH2mIgiTKswdeUEQiE6mHw/NQZ3SSVSov/5vwJ08rTAo46qt+9peK61AommztdVimpwJU'+
66+ 'AFegCyTFrAeTLRFJpeE6KtGbzerUifxLb4GI3QGbDWtwOZiSClCBEQWgyVYddWzdgOYVUkcl'+
67+ '6Bb5B17U/28IkpHm5z1UYI4CwD4SGc7o4cXnQKPj/zSt4mZDHAsNbUtWdzikaSnM36nA6xRo'+
68+ 'gkSGM/oMkDJHsXVuxI9MKrT8f/k+HyUgS8bo5NbrZKRlKvC7FYBA8kqJ7BFuembaA4qUxUKk'+
69+ 'dRRcBeL7j5CcVQbdJrNsUkMeIdnrS1/90Vv+7TXWm14yz49azDfDrZf7/OMhdWebdWwej1rk'+
70+ 'UYu9vvQb/PCtZ7YWgZEjEpGICLEz64g+5rX9iD5q+H9p+PYzWxFIMA0VoAI/W4G3z5H8bHlY'+
71+ 'OipABRAFCBJEJaahAlQgVYAgoYNQASqwWYF/o2XhCcA1FYIAAAAASUVORK5CYII=';
72+
73+ procedure TForm1.Button1Click(Sender: TObject);
74+ var
75+ stream: TMemoryStream;
76+ begin
77+ stream := TMemoryStream.Create;
78+ try
79+ DecodeBase64ToStream(stream, base64String);
80+ Image1.Picture.LoadFromStream(stream);
81+ finally
82+ stream.Free;
83+ end;
84+ end;
85+```
86+
87+# Convert Base64 string to picture, 2
88+
89+This unit is from forum member **KodeZwerg**. He created a pretty easy to handle method that supports now all (?) formats that Lazarus Graphics offers. To name them: JPEG, PNG, GIF, BMP, ICO and TIFF.
90+```
91+unit uBase64Image;
92+
93+ {$mode ObjFPC}{$H+}
94+
95+ interface
96+
97+ uses
98+ Classes, SysUtils, Graphics, ExtCtrls, Base64;
99+
100+ function FileToBytes(const AFilename: string): TBytes;
101+ function BytesToBase64(const AData: TBytes): AnsiString;
102+ function Base64ToBytes(const ABase64String: AnsiString): TBytes;
103+ function GetGraphicClassFromBytes(const AData: TBytes): TGraphicClass;
104+ procedure AssignBase64ToImage(const ABase64String: AnsiString; const AImage: TImage);
105+
106+ implementation
107+
108+ { convert any file into bytes }
109+
110+ function FileToBytes(const AFilename: string): TBytes;
111+ var
112+ FileStream: TFileStream;
113+ begin
114+ FileStream := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite);
115+ try
116+ SetLength(Result, FileStream.Size);
117+ FileStream.ReadBuffer(Result[0], FileStream.Size);
118+ finally
119+ FileStream.Free;
120+ end;
121+ end;
122+
123+ { convert bytes to base64 }
124+
125+ function BytesToBase64(const AData: TBytes): AnsiString;
126+ var
127+ encodedStream: TStringStream;
128+ encodingStream: TBase64EncodingStream;
129+ begin
130+ encodedStream := TStringStream.Create('');
131+ try
132+ encodingStream := TBase64EncodingStream.Create(encodedStream);
133+ try
134+ encodingStream.WriteBuffer(AData[0], Length(AData));
135+ finally
136+ encodingStream.Free;
137+ end;
138+ Result := encodedStream.DataString;
139+ finally
140+ encodedStream.Free;
141+ end;
142+ end;
143+
144+ { convert base64 to bytes }
145+
146+ function Base64ToBytes(const ABase64String: AnsiString): TBytes;
147+ var
148+ decodedStream: TBase64DecodingStream;
149+ base64stream: TStringStream;
150+ begin
151+ base64stream := TStringStream.Create(ABase64String);
152+ try
153+ decodedStream := TBase64DecodingStream.Create(base64stream);
154+ try
155+ SetLength(Result, decodedStream.Size);
156+ decodedStream.ReadBuffer(Result[0], decodedStream.Size);
157+ finally
158+ decodedStream.Free;
159+ end;
160+ finally
161+ base64stream.Free;
162+ end;
163+ end;
164+
165+ { determine the image format }
166+
167+ function GetGraphicClassFromBytes(const AData: TBytes): TGraphicClass;
168+ begin
169+ Result := nil;
170+ // JPEG
171+ if (((Length(AData) >= 8) and (CompareMem(@AData[0], @[$FF, $D8, $FF, $DB], 4)
172+ or CompareMem(@AData[0], @[$FF, $D8, $FF, $E0, $00, $10, $4A, $46], 8)
173+ or CompareMem(@AData[0], @[$49, $46, $00, $01], 4)
174+ or CompareMem(@AData[0], @[$FF, $D8, $FF, $EE], 4)
175+ or (CompareMem(@AData[0], @[$FF, $D8, $FF, $E1], 4) and CompareMem(@AData[6], @[$45, $78], 2))
176+ or CompareMem(@AData[0], @[$69, $66, $00, $00], 4)
177+ or CompareMem(@AData[0], @[$FF, $D8, $FF, $E0], 4)))) then
178+ Result := TJPEGImage
179+ else
180+ // PNG
181+ if ((Length(AData) >= 8) and CompareMem(@AData[0], @[$89, $50, $4E, $47, $0D, $0A, $1A, $0A], 8)) then
182+ Result := TPortableNetworkGraphic
183+ else
184+ // GIF
185+ if ((Length(AData) >= 6) and (CompareMem(@AData[0], @[$47, $49, $46, $38, $37, $61], 6)
186+ or CompareMem(@AData[0], @[$47, $49, $46, $38, $39, $61], 6))) then
187+ Result := TGIFImage
188+ else
189+ // BMP
190+ if ((Length(AData) >= 2) and CompareMem(@AData[0], @[$42, $4D], 2)) then
191+ Result := TBitmap
192+ else
193+ // ICON
194+ if ((Length(AData) >= 4) and CompareMem(@AData[0], @[$00, $00, $01, $00], 4)) then
195+ Result := TIcon
196+ else
197+ // TIFF
198+ if ((Length(AData) >= 4) and (CompareMem(@AData[0], @[$49, $49, $2A, $00], 4)
199+ or CompareMem(@AData[0], @[$4D, $4D, $00, $2A], 6))) then
200+ Result := TTiffImage
201+ else
202+ raise Exception.Create('Unknown Graphic Type!');
203+ end;
204+
205+ { analyze and display a found image format into a TImage }
206+
207+ procedure AssignBase64ToImage(const ABase64String: AnsiString; const AImage: TImage);
208+ var
209+ bytes: TBytes;
210+ graphic: TGraphic;
211+ stream: TStream;
212+ begin
213+ AImage.Picture.Clear;
214+ bytes := Base64ToBytes(ABase64String);
215+ graphic := GetGraphicClassFromBytes(bytes).Create;
216+ try
217+ stream := TBytesStream.Create(bytes);
218+ try
219+ graphic.LoadFromStream(stream);
220+ finally
221+ stream.Free;
222+ end;
223+ AImage.Picture.Assign(graphic);
224+ finally
225+ graphic.Free;
226+ end;
227+ end;
228+
229+ end.
230+```
231+
232+# Convert Base64 string to picture, using BGRABitmap
233+
234+This unit is from forum member **KodeZwerg**. You must install the [[BGRABitmap]] component. But you can also use this unit without BGRABitmap, if you disable the define "UseBGRA" in the top of the "interface" part.
235+```
236+unit ubase64image;
237+
238+ (* ************************* *)
239+ (* * Base64 to Image * *)
240+ (* ************************* *)
241+ { Created: 2023 by KodeZwerg }
242+ { Dialect: FreePascal }
243+ { Type: Helper unit }
244+ { License: Unlicensed }
245+
246+ { This unit can convert a Base64 encoded string into a TImage }
247+ { Additional you can do the opposite, create from a file a Base64 }
248+
249+ { Thank you Remy for teaching me about TGraphicClass usage! }
250+ { Thank you paweld for beta testing and fixing a transparency bug! }
251+ { Thank you wp for teaching me more about TGraphicClass usage! }
252+ { Thank you wp for complaining about my original names, critism help! }
253+
254+ {$mode ObjFPC}{$H+}
255+
256+ interface
257+
258+ // remove the dot to utilize BGRABitmap package
259+ // put a dod infront of $ to deactivate BGRABitmap support
260+ {$DEFINE UseBGRA}
261+
262+ uses
263+ Classes, SysUtils, Graphics, ExtCtrls, Dialogs, Types, LCLType, Controls,
264+ Base64
265+ {$If defined(UseBGRA)},BGRABitmap, BGRABitmapTypes, BGRAGraphics, BGRASVG, BGRAOpenRaster, BGRAPhoxo, BGRAPaintNet{$EndIf};
266+
267+ // this method creates a stream from a file, additional it can throw a warning if a certain mb limit is exceeded
268+ function CreateStreamFromFile(const AFilename: string; var AStream: TStream; const AFileSizeWarningInMegabyte: Integer = 1): Boolean;
269+ // this method convert a stream into a base64 string
270+ function CreateBase64FromStream(const AStream: TStream): string;
271+ // this method convert a base 64 into a stream
272+ function CreateStreamFromBase64(const ABase64String: AnsiString): TStream;
273+ // depending what mode you selected you having either this or that method available to display out of a base64 a timage
274+ {$If defined(UseBGRA)}
275+ // this method convert base64 into a timage, additional you can choose between a faster bitmap conversation or a slower png compressed variant
276+ procedure AssignBase64ToImage(const ABase64String: AnsiString; const AImage: TImage; const AFastMode: Boolean = False);
277+ {$Else}
278+ // this method convert a base64 into a timage
279+ procedure AssignBase64ToImage(const ABase64String: AnsiString; const AImage: TImage);
280+ {$EndIf}
281+ implementation
282+
283+ function CreateStreamFromFile(const AFilename: string; var AStream: TStream; const AFileSizeWarningInMegabyte: Integer = 1): Boolean;
284+ function SizeToString(const ASize: UInt64; const oneKB: Integer = {$IFDEF MSWINDOWS}1024{$ELSE}1000{$ENDIF}): string;
285+ var
286+ Calc: Extended;
287+ Sign: String;
288+ SizeLength: Integer;
289+ begin
290+ SizeLength := 0;
291+ Calc := ASize;
292+ while (Calc > oneKB) do
293+ begin
294+ Calc := Calc / oneKB;
295+ Inc(SizeLength);
296+ end;
297+ case SizeLength of
298+ 0: Sign := ' byte';
299+ 1: Sign := ' kb'; // Kilo Byte
300+ 2: Sign := ' mb'; // Mega Byte
301+ 3: Sign := ' gb'; // Giga Byte
302+ 4: Sign := ' tb'; // Tera Byte
303+ 5: Sign := ' pb'; // Peta Byte
304+ 6: Sign := ' eb'; // Exa Byte
305+ 7: Sign := ' zb'; // Zetta Byte
306+ 8: Sign := ' yb'; // Yotta Byte
307+ 9: Sign := ' rb'; // Ronna Byte
308+ 10:Sign := ' qb'; // Quetta Byte
309+ else
310+ Sign :=' (' + IntToStr(SizeLength) + ')';
311+ end;
312+ Result := FormatFloat('#,##0.00', Calc) + Sign;
313+ end;
314+ const
315+ oneKB = Integer({$IFDEF MSWINDOWS}1024{$ELSE}1000{$ENDIF});
316+ oneMB = Integer(oneKB * oneKB);
317+ var
318+ FileStream: TFileStream;
319+ begin
320+ FileStream := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite);
321+ try
322+ Result := False;
323+ if (FileStream.Size > (oneMB * AFileSizeWarningInMegabyte)) then
324+ if QuestionDlg('Filesize Warning!',
325+ Format('Filesize is bigger than %dmb (%s)!', [AFileSizeWarningInMegabyte, SizeToString(FileStream.Size)])
326+ + LineEnding + 'Continue loading?',
327+ mtWarning, [mrYes, mrNo], 0) = mrNo then
328+ Exit;
329+ AStream := TMemoryStream.Create;
330+ try
331+ AStream.CopyFrom(FileStream, FileStream.Size);
332+ finally
333+ AStream.Position := 0;
334+ Result := True;
335+ end;
336+ finally
337+ FileStream.Free;
338+ end;
339+ end;
340+
341+ function CreateBase64FromStream(const AStream: TStream): string;
342+ var
343+ EncodedStream: TStringStream;
344+ Encoder: TBase64EncodingStream;
345+ begin
346+ Result := '';
347+ EncodedStream := TStringStream.Create('');
348+ Encoder := TBase64EncodingStream.Create(EncodedStream);
349+ try
350+ AStream.Position := 0;
351+ Encoder.CopyFrom(AStream, AStream.Size);
352+ Encoder.Flush;
353+ Result := EncodedStream.DataString;
354+ AStream.Position := 0;
355+ finally
356+ Encoder.Free;
357+ EncodedStream.Free;
358+ end;
359+ end;
360+
361+ function CreateStreamFromBase64(const ABase64String: AnsiString): TStream;
362+ var
363+ DecodedStream: TBase64DecodingStream;
364+ Base64Stream: TStringStream;
365+ begin
366+ Base64Stream := TStringStream.Create(ABase64String);
367+ try
368+ DecodedStream := TBase64DecodingStream.Create(base64stream);
369+ try
370+ Result := TMemoryStream.Create;
371+ try
372+ Result.CopyFrom(DecodedStream, DecodedStream.Size);
373+ finally
374+ Result.Position := 0;
375+ end;
376+ finally
377+ DecodedStream.Free;
378+ end;
379+ finally
380+ Base64Stream.Free;
381+ end;
382+ end;
383+
384+ {$IfNDef UseBGRA}
385+ function GetGraphicClassFromStream(const AStream: TStream): TGraphicClass;
386+ function HasIconSignature(const AStream: TStream): Boolean;
387+ const
388+ IconSignature: array[0..3] of Byte = ($00, $00, $01, $00);
389+ var
390+ SignatureBytes: array[0..3] of Byte;
391+ begin
392+ AStream.Position := 0;
393+ AStream.ReadBuffer(SignatureBytes, SizeOf(SignatureBytes));
394+ Result := CompareMem(@SignatureBytes, @IconSignature, SizeOf(SignatureBytes));
395+ AStream.Position := 0;
396+ end;
397+ const
398+ REGISTERED: array[0..5] of TGraphicClass = (TBitmap, TJpegImage,
399+ TPortableNetworkGraphic, TTiffImage, TGifImage, TPixMap);
400+ var
401+ i: Integer;
402+ begin
403+ Result := nil;
404+ AStream.Position := 0;
405+ for i := 0 to High(REGISTERED) do
406+ if REGISTERED[i].IsStreamFormatSupported(AStream) then
407+ begin
408+ Result := REGISTERED[i];
409+ AStream.Position := 0;
410+ Exit;
411+ end;
412+ if HasIconSignature(AStream) then
413+ Result := TIcon;
414+ AStream.Position := 0;
415+ end;
416+
417+ procedure AssignBase64ToImage(const ABase64String: AnsiString; const AImage: TImage);
418+ var
419+ graphicClass: TGraphicClass;
420+ graphic: TGraphic;
421+ stream: TStream;
422+ size: TSize;
423+ begin
424+ AImage.Picture.Clear;
425+ stream := CreateStreamFromBase64(ABase64String);
426+ graphicClass := GetGraphicClassFromStream(stream);
427+ if Assigned(graphicClass) then
428+ begin
429+ graphic := graphicClass.Create;
430+ try
431+ graphic.LoadFromStream(stream);
432+ if (graphicClass.ClassType = TIcon) then
433+ begin
434+ size.Width := AImage.Width;
435+ size.Height := AImage.Height;
436+ TIcon(graphic).Current := TIcon(graphic).GetBestIndexForSize(size);
437+ end;
438+ AImage.Picture.Assign(graphic);
439+ finally
440+ graphic.Free;
441+ end;
442+ end;
443+ stream.Free;
444+ end;
445+ {$EndIf}
446+
447+ {$If defined(UseBGRA)}
448+ function BGRABitmapToPNGStream(const ABGRABitmap: TBGRABitmap): TStream;
449+ begin
450+ Result := TMemoryStream.Create;
451+ try
452+ ABGRABitmap.SaveToStreamAsPng(Result);
453+ finally
454+ Result.Position := 0;
455+ end;
456+ end;
457+
458+ function BGRABitmapToBitmap(const ABGRABitmap: TBGRABitmap): TBitmap;
459+ begin
460+ Result := TBitmap.Create;
461+ try
462+ Result.PixelFormat := ABGRABitmap.Bitmap.PixelFormat;
463+ Result.Transparent := ABGRABitmap.HasTransparentPixels or ABGRABitmap.HasSemiTransparentPixels;
464+ Result.SetSize(ABGRABitmap.Width, ABGRABitmap.Height);
465+ Result.Canvas.Lock;
466+ try
467+ Result.Canvas.Draw(0, 0, ABGRABitmap.Bitmap);
468+ finally
469+ Result.Canvas.Unlock;
470+ end;
471+ finally
472+ end;
473+ end;
474+
475+ procedure AssignBase64ToImage(const ABase64String: AnsiString; const AImage: TImage; const AFastMode: Boolean = False);
476+ var
477+ BGRABitmap: TBGRABitmap;
478+ Stream: TStream;
479+ bmp: TBitmap;
480+ begin
481+ AImage.Picture.Clear;
482+ Stream := CreateStreamFromBase64(ABase64String);
483+ if (DetectFileFormat(Stream) <> ifUnknown) then
484+ begin
485+ BGRABitmap := TBGRABitmap.Create;
486+ try
487+ try
488+ BGRABitmap.LoadFromStream(Stream);
489+ finally
490+ Stream.Free;
491+ end;
492+ if AFastMode then
493+ begin
494+ bmp := BGRABitmapToBitmap(BGRABitmap);
495+ try
496+ AImage.Transparent := bmp.Transparent;
497+ AImage.Picture.Assign(bmp);
498+ finally
499+ bmp.Free;
500+ end;
501+ end
502+ else
503+ begin
504+ Stream := BGRABitmapToPNGStream(BGRABitmap);
505+ try
506+ AImage.Transparent := BGRABitmap.HasTransparentPixels or BGRABitmap.HasSemiTransparentPixels;
507+ AImage.Picture.PNG.LoadFromStream(Stream);
508+ finally
509+ Stream.Free;
510+ end;
511+ end;
512+ finally
513+ BGRABitmap.Free;
514+ end;
515+ end
516+ else
517+ Stream.Free;
518+ end;
519+ {$EndIf}
520+
521+ initialization
522+ {$If defined(UseBGRA)}
523+ BGRASVG.RegisterSvgFormat;
524+ BGRAOpenRaster.RegisterOpenRasterFormat;
525+ BGRAPhoxo.RegisterPhoxoFormat;
526+ BGRAPaintNet.RegisterPaintNetFormat;
527+ {$EndIf}
528+ end.
529+```
530+
531+---
532+*From the Free Pascal wiki, page "Base64", as the Internet Archive kept it on 2026-01-15. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history