0

I have a string, recived by my app from web-browser. String contains PNG image, and encoded to base64.

It isn't my stupid idea, convert image to base64 string )) That doing web-broser. HTML5 canvas object doing that, when need to send image to somewhere.

So, how to decode this string to image?

In Delphi I written my web-server, that recives data.

In PHP this can be solved like that:

function base64_to_jpeg( $base64_string, $output_file ) {
    $ifp = fopen( $output_file, "wb" ); 
    fwrite( $ifp, base64_decode( $base64_string) ); 
    fclose( $ifp ); 
    return( $output_file ); 
}

$image = base64_to_jpeg( $my_base64_string, 'tmp.jpg' );

but in delphi, after decoding:

  if (sImg <> EmptyStr) then
  begin
    Coder := TIdDecoderMIME.Create(nil);
    MS := TMemoryStream.Create;
    try
      Coder.DecodeStream(sImg, MS);
      MS.SaveToFile(myDir + '1.png');
    finally
      FreeAndNil(MS);
      FreeAndNil(Coder);
    end;
  end;

I have a black square of Malevich.

Also I tried functions from EncdDesd module of RTL,

  if (sImg <> EmptyStr) then
  begin
    MS := TMemoryStream.Create;
    SS := TStringStream.Create(sImg);
    try
      DecodeStream(SS, MS);
      MS.SaveToFile(myDir + '1.png');
    finally
      FreeAndNil(MS);
      FreeAndNil(SS);
    end;
  end;

I got the same result.

I wrote web-extension for get some info from user web-browser, and web-server using TidHTTPServer. From JS I capture the web-screenshot, and remove some data from exe, after that, I send this string to the server:

var Img = capture().toDataURL();
var Img = Img.replace('data:image/png;base64,','');

     if (FLA.AddNewURL(sN,sD,sU,sI,Img)) {
      window.close();
     } else {
      alert('can not establish connection!');
     };

...

AddNewURL: function (aName, aDesc,sURL, aOwnerId,aImg) {
    var http = new XMLHttpRequest();
    var params = 'Owner=' + aOwnerId + '&Name=' + aName + '&Desc=' + aDesc+ '&URL=' + sURL;
    if (aImg) {
      params = params +'&Img='+aImg;
    };
        http.open("POST", "http://" + this.host + ":" + this.port + "/addurl", false);
        http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
        http.send(params);
    return (http.status === 200);
},

My web-server recives this data like that:

  if (ARequestInfo.Document = '/addurl') then
  begin
    Id := ARequestInfo.Params.Values['Owner'];
    sName := ARequestInfo.Params.Values['Name'];
    sDesc := ARequestInfo.Params.Values['Desc'];
    sURL := ARequestInfo.Params.Values['URL'];
    sImg := ARequestInfo.Params.Values['Img'];
    RootLI := nil;
    LinksManager.FindByID(Id, RootLI);
    if Assigned(RootLI) then
    begin
      LI := TLinkItem.Create(nil);
      LI.name := sName;
      LI.Description := sDesc;
      LI.URL := sURL;
      if (sImg <> EmptyStr) then
      begin
        MS := TMemoryStream.Create;
        SS := TStringStream.Create(sImg);
        try
          DecodeStream(SS, MS);
          MS.SaveToFile(myDir + '1.png');
        finally
          FreeAndNil(MS);
          FreeAndNil(SS);
        end;
      end;
      RootLI.Add(LI, True);
      AResponseInfo.ResponseText := 'OK';
    end
    else
      AResponseInfo.ResponseText := 'FAIL';
  end;

After all of that I have image, that contains only black color.

Community
  • 1
  • 1
Alexandr
  • 338
  • 1
  • 4
  • 16
  • What have you tried and what didn't work? There's plenty of resources out there explaining how to do so, and some here on Stack Overflow too. You should do your research and only ask question here when you get stumped. – Jerry Dodge Nov 16 '13 at 23:15
  • Much better, now it's an adequate question. – Jerry Dodge Nov 16 '13 at 23:44
  • In the [`question you linked`](http://stackoverflow.com/questions/15153776/convert-base64-string-to-an-image-file) is mentioned that you need to strip out the `data:image/png;base64,`. Is that string part of your input stream ? If so, did you do the same ? If not, how are you receiveing those data; how do you download that stream ? What is the encoding of your content ? There's a lot of missing details in your question at this time. @Jerry, now we have a proof that Alexandr tried to write a code, but we need to get mainly the information about that incomming stream. – TLama Nov 17 '13 at 00:09
  • @TLama A great deal better than the original though – Jerry Dodge Nov 17 '13 at 03:51
  • @TLama, I'm dooing that in JS before sending data to the server. See 1st post for more... – Alexandr Nov 17 '13 at 07:59
  • Is the exact same string decoded correctly in PHP? – Runner Nov 17 '13 at 08:46
  • I can see some problems with TStringStream and maybe encoding. Why don't you decode directly from string to TMemoryStream. – Runner Nov 17 '13 at 08:48

1 Answers1

0

I solved my problem by other way. In JS I send data via headers(Ajax.setRequestHeader), and the file I send in the POST stream. After that DecodeStream, from EncdDecd is working correctly, I got the image from string.

        Id := ARequestInfo.RawHeaders.Values['OwnerId'];
        sName := ARequestInfo.RawHeaders.Values['Name'];
        sDesc := ARequestInfo.RawHeaders.Values['Desc'];
        sURL := ARequestInfo.RawHeaders.Values['URL'];
...
          if (ARequestInfo.PostStream <> nil) then //We have the image!
          begin
            MS := TMemoryStream.Create;
            MS2 := TMemoryStream.Create;
            try
              MS2.LoadFromStream(ARequestInfo.PostStream);
              DecodeStream(MS2, MS);
              MS.SaveToFile(myDir + '1.png');
            finally
              FreeAndNil(MS);
              FreeAndNil(MS2);
            end;
          end;

Also you can try mixed of alternative multipart/form-data encoding. But Indy doesn't have implemented classes for parsing recived data in this format.

Alexandr
  • 338
  • 1
  • 4
  • 16
  • 1
    Actually, Indy does have a class for decoding `multipart/...` data - `TIdMessageDecoderMIME`. It was not originally intended to be used with `TIdHTTPServer`, only with email, but it can be used with `TIdHTTPServer` with some manual coding. Examples of that have been posted many times before, so search around. MIME parsing will be expanded on and generalized much more in Indy 11, including built-in support for parsing `multipart/form-data` in `TIdHTTPServer`. But `TIdMessageDecoderMIME` is adequate in the meantime. – Remy Lebeau Nov 17 '13 at 23:59
  • Indy 11 does not exist, it has not even been started yet. The current version is 10.6. You will have to use `TIdMessageDecoderMIME` for now. – Remy Lebeau Nov 18 '13 at 19:20