Recent

Author Topic: How to load a BASE64 encoded image to a TImage component  (Read 4139 times)

andersonpem

  • Newbie
  • Posts: 2
How to load a BASE64 encoded image to a TImage component
« on: January 24, 2018, 12:46:54 am »
Hi everyone. This is my very first post. Please don't be angry at me if I look dumb hehe.
I wonder if I could load images on TImage components from a BASE64 encoded string. I have a webservice which list some itens with images. These images are in BASE64.

Is this feasible in Lazarus?  :)

Thanks everyone.
From a brazilian beginner.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 697
    • Lebeau Software
Re: How to load a BASE64 encoded image to a TImage component
« Reply #1 on: January 24, 2018, 01:05:01 am »
Is this feasible in Lazarus?  :)

Of course it is.  There are plenty of base64 decoders available if you look around.  Find one, decode the base64 to binary data, store the data in a TStream like a TMemoryStream, and then load that into the TImage.Picture property as needed
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

Bart

  • Hero Member
  • *****
  • Posts: 3624
    • Bart en Mariska's Webstek
Re: How to load a BASE64 encoded image to a TImage component
« Reply #2 on: January 24, 2018, 02:49:19 pm »
IIRC fpc provides a base64 encoder/decoder.

Bart

GetMem

  • Hero Member
  • *****
  • Posts: 3554
Re: How to load a BASE64 encoded image to a TImage component
« Reply #3 on: January 24, 2018, 03:47:03 pm »
@andersonpem,

Welcome to the forum. Please try attached project:
Code: Pascal  [Select]
  1. uses base64;
  2.  
  3. function StreamToBase64(const AStream: TMemoryStream; out Base64: String): Boolean;
  4. var
  5.   Str: String;
  6. begin
  7.   Result := False;
  8.   if AStream.Size = 0 then
  9.     Exit;
  10.   AStream.Position := 0;
  11.   try
  12.     SetLength(Str, AStream.Size div SizeOf(Char));
  13.     AStream.ReadBuffer(Pointer(Str)^, AStream.Size div SizeOf(Char));
  14.     Base64 := EncodeStringBase64(Str);
  15.     Result := True;
  16.   except
  17.     on E: Exception do
  18.       ShowMessage(E.Message);
  19.   end;
  20. end;
  21.  
  22. function Base64ToStream(const ABase64: String; var AStream: TMemoryStream): Boolean;
  23. var
  24.   Str: String;
  25. begin
  26.   Result := False;
  27.   if Length(Trim(ABase64)) = 0 then
  28.     Exit;
  29.   try
  30.     Str := DecodeStringBase64(ABase64);
  31.     AStream.Write(Pointer(Str)^, Length(Str) div SizeOf(Char));
  32.     AStream.Position := 0;
  33.     Result := True;
  34.   except
  35.     on E: Exception do
  36.       ShowMessage(E.Message);
  37.   end;
  38. end;

Takeda

  • Full Member
  • ***
  • Posts: 157
Re: How to load a BASE64 encoded image to a TImage component
« Reply #4 on: October 01, 2018, 02:45:18 pm »
@andersonpem,

Welcome to the forum. Please try attached project:
Code: Pascal  [Select]
  1. uses base64;
  2.  
  3. function StreamToBase64(const AStream: TMemoryStream; out Base64: String): Boolean;
  4. var
  5.   Str: String;
  6. begin
  7.   Result := False;
  8.   if AStream.Size = 0 then
  9.     Exit;
  10.   AStream.Position := 0;
  11.   try
  12.     SetLength(Str, AStream.Size div SizeOf(Char));
  13.     AStream.ReadBuffer(Pointer(Str)^, AStream.Size div SizeOf(Char));
  14.     Base64 := EncodeStringBase64(Str);
  15.     Result := True;
  16.   except
  17.     on E: Exception do
  18.       ShowMessage(E.Message);
  19.   end;
  20. end;
  21.  
  22. function Base64ToStream(const ABase64: String; var AStream: TMemoryStream): Boolean;
  23. var
  24.   Str: String;
  25. begin
  26.   Result := False;
  27.   if Length(Trim(ABase64)) = 0 then
  28.     Exit;
  29.   try
  30.     Str := DecodeStringBase64(ABase64);
  31.     AStream.Write(Pointer(Str)^, Length(Str) div SizeOf(Char));
  32.     AStream.Position := 0;
  33.     Result := True;
  34.   except
  35.     on E: Exception do
  36.       ShowMessage(E.Message);
  37.   end;
  38. end;

Your code and attached file crash when tries to load into TImage
Call me Takeda coz that's my true name.
Pascal coding using Lazarus => "Be native in any where.."

ƪ(˘⌣˘)┐ ƪ(˘⌣˘)ʃ ┌(˘⌣˘)ʃ

GetMem

  • Hero Member
  • *****
  • Posts: 3554
Re: How to load a BASE64 encoded image to a TImage component
« Reply #5 on: October 01, 2018, 02:51:35 pm »
Quote
Your code and attached file crash when tries to load into TImage
The code from my previous post works fine here. What attachment are you talking about? Also can you please specify your Lazarus and FPC version?

Takeda

  • Full Member
  • ***
  • Posts: 157
Re: How to load a BASE64 encoded image to a TImage component
« Reply #6 on: October 01, 2018, 02:56:38 pm »
Quote
Your code and attached file crash when tries to load into TImage
The code from my previous post works fine here. What attachment are you talking about? Also can you please specify your Lazarus and FPC version?

This file https://forum.lazarus.freepascal.org/index.php?action=dlattach;topic=39789.0;attach=24965
I used Lazarus 2.x fixes Branch + FPC 3.2 fixes Branch
Call me Takeda coz that's my true name.
Pascal coding using Lazarus => "Be native in any where.."

ƪ(˘⌣˘)┐ ƪ(˘⌣˘)ʃ ┌(˘⌣˘)ʃ

GetMem

  • Hero Member
  • *****
  • Posts: 3554
Re: How to load a BASE64 encoded image to a TImage component
« Reply #7 on: October 01, 2018, 03:02:48 pm »
Something has changed in FPC, I can also reproduce the issue with FPC trunk. If you know the image type, just save the stream to that image type first, then load it to TImage.

Takeda

  • Full Member
  • ***
  • Posts: 157
Re: How to load a BASE64 encoded image to a TImage component
« Reply #8 on: October 01, 2018, 03:14:32 pm »
Something has changed in FPC, I can also reproduce the issue with FPC trunk. If you know the image type, just save the stream to that image type first, then load it to TImage.

I already modify it, but still "wrong image format".

Code: Pascal  [Select]
  1. procedure TForm1.Button2Click(Sender: TObject);
  2. var
  3.   img: TJPEGImage;
  4.   Stream: TMemoryStream;
  5. begin
  6.   img := TJPEGImage.Create;
  7.   Stream := TMemoryStream.Create;
  8.   Screen.Cursor := crHourGlass;
  9.   try
  10.     Stream.Position := 0;
  11.     if Base64ToStream(Memo1.Text, Stream) then
  12.     begin
  13.       img.LoadFromStream(stream);
  14.       Image2.Picture.Assign(img);
  15.     end;
  16.   finally
  17.     Stream.Free;
  18.     img.Free;
  19.     Screen.Cursor := crDefault;
  20.   end;
  21. end;        
Call me Takeda coz that's my true name.
Pascal coding using Lazarus => "Be native in any where.."

ƪ(˘⌣˘)┐ ƪ(˘⌣˘)ʃ ┌(˘⌣˘)ʃ

GetMem

  • Hero Member
  • *****
  • Posts: 3554
Re: How to load a BASE64 encoded image to a TImage component
« Reply #9 on: October 01, 2018, 05:59:50 pm »
@Takeda
Please test attached project, with FPC 3.1+

Takeda

  • Full Member
  • ***
  • Posts: 157
Re: How to load a BASE64 encoded image to a TImage component
« Reply #10 on: October 02, 2018, 03:20:29 pm »
@Takeda
Please test attached project, with FPC 3.1+

Thank you so much GetMem.. it's work..
Call me Takeda coz that's my true name.
Pascal coding using Lazarus => "Be native in any where.."

ƪ(˘⌣˘)┐ ƪ(˘⌣˘)ʃ ┌(˘⌣˘)ʃ

lainz

  • Hero Member
  • *****
  • Posts: 3453
    • Lainz
Re: How to load a BASE64 encoded image to a TImage component
« Reply #11 on: December 27, 2019, 09:28:19 pm »
Thanks GetMem. Just to say your method works fine with BGRABitmap as well.

Simply replace:

Image1.Picture.LoadFromStream... with FBGRA.LoadFromStream... (where FBGRA is TBGRABitmap object).

Edit: if your base64 comes from a web page, remove the first text, else it will crash:
base64data.Replace('data:image/png;base64,', '')
« Last Edit: December 28, 2019, 12:15:35 am by lainz »