Jump to content
Czar

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?

cheers

 

Share this post


Link to post
Share on other sites

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

{ TForm1 }

procedure TForm1.W3Button1Click(Sender: TObject);
var
  LARef : TControlHandle;
begin
  asm
    (@LARef) = document.createElement('a');
    document.body.appendChild(@LARef);
  end;

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

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

procedure TForm1.InitializeObject;
begin
  inherited;
  {$I 'Form1:impl'}
  Image1.LoadFromUrl('logo.png');
end;

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/

 

Share this post


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
  public
    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;
  end;

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

Share this post


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

 

var
  LBitmap:  TBitmap;
  LRect:    TRect;
begin

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

    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');
    w3image1.LoadFromUrl(LEncodedData);

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

  finally
    LBitmap.free;
  end;

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?

Share this post


Link to post
Share on other sites

@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

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites

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)

Share this post


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.

Share this post


Link to post
Share on other sites

This we found our culprit:

procedure TW3CanvasFont.ReadFontInfo;
begin
end;

It doesnt parse the font information and expects to inherit from the container.
This works fine on visual controls (TW3GraphicControl) but will naturally be a problem on a raw device context

Share this post


Link to post
Share on other sites

@Czar Just had a look and found the problem. The code that was in TW3CanvasFont.WriteFontInfo had to be in ReadFontInfo. Also, WriteFontInfo needed to be constructed from the internal variables.

Edit: Fixed now. Gonna be in next update.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×