Jump to content

Save tw3image to desktop?

Recommended Posts

Colleagues have asked me if it possible to set a system where-by franchisees can edit text for social media ads. i.e., I display an image in their browser, they can edit the text and when they are done a PNG or JPG can be downloaded.


I am just not sure about the last step - downloading. I know javascript is not supposed to access local machine but there must be a way to do it - my question is how easy is it to implement and can someone point me in the right direction?



Link to post
Share on other sites
  • Moderators

just downloading an image which is displayed in the browser :   (code based on link in prev post)

{ TForm1 }

procedure TForm1.W3Button1Click(Sender: TObject);
  LARef : TControlHandle;
    (@LARef) = document.createElement('a');

  // Setup values
  LARef.style := "display: none";

  // Wait for the obj to appear in the DOM
  LARef.readyExecute( procedure ()
    LARef.href := Image1.ToDataUrl;
    LARef.download := 'alogo2.png';
    // Invoke click on link

procedure TForm1.InitializeObject;
  {$I 'Form1:impl'}

ends up in the standard download directory. Isn't that what you want ?

doesn't work from within ide or from file, server only

(on server works fine using Chrome and Firefox, still looking at Edge)   http://www.lynkfs.com/Experiments/imgupload2/


Link to post
Share on other sites

Have a look in SmartCL.System, scroll down to line 1113, there you will find the class TW3URLObject:


  TW3URLObject = static class
    class function  GetObjectURL(const Text, Encoding, ContentType, Charset: string): string; overload;
    class function  GetObjectURL(const Text: string): string; overload;
    class function  GetObjectURL(const Stream: TStream): string; overload;
    class function  GetObjectURL(const Data: TAllocation): string; overload;
    class procedure RevokeObjectURL(const ObjectUrl: string);

    // This cause a download in the browser of an object-url
    class procedure Download(const ObjectURL: string; Filename: string); overload;
    class procedure Download(const ObjectURL: string; Filename: string;
          const OnStarted: TProcedureRefS); overload;

This should make it easier. Also look at TAllocationHelper, which targets TAllocation - used by TMemoryStream and TBinaryData (system.memory.buffer).

Link to post
Share on other sites

Ok this driving me to distraction. The sample above work great so I thought I would add text to my image


  LBitmap:  TBitmap;
  LRect:    TRect;

  LBitmap := TBitmap.Create;
    LBitmap.Allocate(640, 480);
    LRect := TRect.Create(0, 0, LBitmap.width-1, LBitmap.Height-1);
    LBitmap.Canvas.Brush.Color := clRed;

    LBitmap.Canvas.Font.size := 28;
    LBitmap.Canvas.TextOut(10,10, 'It displays text but in small font', clblack);

    var LEncodedData:= LBitmap.Canvas.ToDataURL('image/png');

    TW3URLObject.Download( LEncodedData, 'picture.png');


it seems font.size or font.color have no influence on the textout. Which is confusing. Is it a bug or am I missing something? In which case how can I set the font name, size and color?

Link to post
Share on other sites
  • Administrators
44 minutes ago, Czar said:

@jartoI have tried a bunch of things but I cannot change size, style or anything related to the default font when using text out. Are you able to doa quick example? As 

LBitmap.Canvas.Font.size := 28;

doesn't work

I'm travelling for five days, so I can't help you now. Can @lennarthelp?

Link to post
Share on other sites
  • Moderators

afaics needs a bit of work from the dev team

in the meantime this is a workable workaround

    LBitmap.Canvas.Context.DC.font := '68px serif';  // or 'italic bold 88px "Tangerine", serif';
    LBitmap.Canvas.TextOut(10,70, 'It displays text but in small font', clblue);

(or alternatively add a TCanvas.SetSize procedure or helper)

Link to post
Share on other sites

Hm, this is strange. The exposed "font" property of TBitmap is just a proxy, it relays the font property of TW3Canvas - which is the HTML5 canvas for that context. The canvas/bitmap stuff was a bit tricky because under HTML5 its completely opposite of what we have in Delphi or FPC. We are used to creating a bitmap and then attaching a TCanvas to that bitmap -- but in html5 the canvas holds the data while the context delegates access. But then again, everything in the JS world is topsy turvey at times. Its a bit like going from ordinary physics to quantum physics - you can throw your old notions of solid reality out the window :)

This should be easy enough to fix. The legacy unit was initially something I made for a demo earlier, but since it made porting delphi code easier I figured it could also help others. This is why it has escaped the more hard-core testing that we did on the visual components and low-level namespaces.

But ok, lets fix this and get it out :)

Also -- there is no need to go via the handle, the old "font" text property was just renamed to "FontStyle" since that's what it does.
We had to do this to make room for TFont.

Link to post
Share on other sites
  • 2 weeks later...
  • 2 weeks later...
  • 2 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...