delphibase64twebbrowserdelphi-10.3-riotimage

How load a base64 encrypted url in a TWebBrowser or TImage?


I have this url encrypted in base64 that is a animated QRCode.

How i can load it in a TWebBrowser (or TImage)? Thanks in advance.


Edit:

Here was my attempt, but without success:

uses
 IdHTTP, IdSSLOpenSSL, GIFImg, ClipBrd;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Image1: TImage;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function GetStrFromClipbrd: string;
begin
  if Clipboard.HasFormat(CF_TEXT) then
    Result := Clipboard.AsText
  else
  begin
    ShowMessage('There is no text in the Clipboard!');
    Result := '';
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  MS: TMemoryStream;
  IdHTTP1: TIdHTTP;
  GIF: TGIFImage;
begin
  MS := TMemoryStream.Create;
  try
    IdHTTP1 := TIdHTTP.Create;
    try
      GIF := TGIFImage.Create;
      try
        IdHTTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP1);
        IdHTTP1.HandleRedirects := True;
        IdHTTP1.Get(GetStrFromClipbrd, MS);
        MS.Seek(0, soFromBeginning);
        GIF.LoadFromStream(MS);
        Image1.Picture.Assign(GIF);
        (Image1.Picture.Graphic as TGIFImage).Animate := True;
        //(Image1.Picture.Graphic as TGIFImage).AnimationSpeed := 500;
      finally
        FreeAndNil(GIF);
      end;
    finally
      FreeAndNil(IdHTTP1);
    end;
  finally
    FreeAndNil(MS);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form1.DoubleBuffered := True;
end;

end.

Solution

  • data: is not a URL type you can request with TIdHTTP (or any other HTTP library), nor do you need to since all of the data is encoded directly in the URL itself. So simply extract the base64 portion and decode it using any base64 decoder of your choosing.

    Since your code is already using Indy anyway, you could use its TIdDecoderMIME class in the IdCoderMIME unit to decode the base64 data to a binary stream, such as with the TIdDecoderMIME.DecodeStream() class procedure. Then you can load that stream into an appropriate TGraphic descendant (TGIFImage, TBitmap, etc), and then finally you can load that graphic into your TImage.

    For example:

    uses
      IdGlobal, IdGlobalProtocols, IdCoderMIME, IdHTTP, IdSSLOpenSSL,
      Graphics, GIFImg, JPEG, ClipBrd;
    
    function GetStrFromClipbrd: string;
    const
      CTextFormat = {$IFDEF UNICODE}CF_UNICODETEXT{$ELSE}CF_TEXT{$ENDIF};
    begin
      if Clipboard.HasFormat(CTextFormat) then
        Result := Clipboard.AsText
      else
        Result := '';
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      Graphic: TGraphic;
      MS: TMemoryStream;
      IdHTTP1: TIdHTTP;
      URL, ContentType: string;
    begin
      URL := GetStrFromClipbrd;
      if URL = '' then
      begin
        ShowMessage('There is no text in the Clipboard!');
        Exit;
      end;
    
      Graphic := nil;
      try
        MS := TMemoryStream.Create;
        try
          if TextStartsWith(URL, 'data:') then
          begin
            Fetch(URL, ':');
            ContentType := Fetch(URL, ',');
            if not TextEndsWith(ContentType, ';base64') then
            begin
              ShowMessage('Data is not encoded in base64!');
              Exit;
            end;
            SetLength(ContentType, Length(ContentType)-7);
            TIdDecoderMIME.DecodeStream(URL, MS);
            if ContentType = '' then
              ContentType := 'text/plain;charset=US-ASCII';
          end else
          begin
            IdHTTP1 := TIdHTTP.Create;
            try
              IdHTTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP1);
              IdHTTP1.HandleRedirects := True;
              IdHTTP1.Get(URL, MS);
              ContentType := IdHTTP1.Response.ContentType;
            finally
              IdHTTP1.Free;
            end;
          end;
    
          MS.Position := 0;
    
          case PosInStrArray(ExtractHeaderItem(ContentType),
            ['image/gif', 'image/jpeg', 'image/bmp'{, ...}],
            False) of
              0: Graphic := TGIFImage.Create;
              1: Graphic := TJPEGImage.Create;
              2: Graphic := TBitmap.Create;
              // ...
          else
            ShowMessage('Unsupported image type!');
            Exit;
          end;
    
          { the 'data:' URL you provided is malformed, is says the image type
            is 'image/bmp' even though it is actually a GIF and thus should
            say 'image/gif'.  To avoid problems with the above code determining
            the wrong TGraphic class to use in that case, you can instead look
            at the first few bytes of the decoded data to determinate its actual
            image type, eg...
    
            const
              Signature_GIF87a: array[0..5] of Byte = ($47,$49,$46,$38,$37,$61);
              Signature_GIF89a: array[0..5] of Byte = ($47,$49,$46,$38,$39,$61);
              Signature_JPEG:   array[0..2] of Byte = ($FF,$D8,$FF);
              Signature_BMP:    array[0..1] of Byte = ($42,$4D);
              ...
    
            if (MS.Size >= 6) and
               (CompareMem(MS.Memory, @Signature_GIF87a, 6) or
                CompareMem(MS.Memory, @Signature_GIF89a, 6)) then
            begin
              Graphic := TGIFImage.Create;
            end
            else if (MS.Size >= 3) and
                     CompareMem(MS.Memory, @Signature_JPEG, 3) then
            begin
              Graphic := TJPEGImage.Create;
            end
            else if (MS.Size >= 2) and
                     CompareMem(MS.Memory, @Signature_BMP, 2) then
            begin
              Graphic := TBitmap.Create;
            end
            ...
            else
              ShowMessage('Unsupported image type!');
              Exit;
            end;
          }
    
          Graphic.LoadFromStream(MS);
        finally
          MS.Free;
        end;
    
        Image1.Picture.Assign(Graphic);
      finally
        Graphic.Free;
      end;
    
      if Image.Picture.Graphic is TGIFImage then
      begin
        TGIFImage(Image.Picture.Graphic).Animate := True;
        //TGIFImage(Image.Picture.Graphic).AnimationSpeed := 500;
      end;
    end;