TWebImageControl resizing image fails

In my previous post I already metioned that OnLoaded isn't firing. So in order to change the size of the image I set a timer of 500ms and try to manipulate the image then.

In the timer event I then tried

WebImageControl1.ResizeImage(NewWidth,NewHeight)

but this gives error:

Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

So I tried

WebImageControl1.Width := NewWidth;
WebImageControl1.Height := NewHeight;

And also tried:

WebImageControl1.ElementHandle.style.setProperty('width','50');
WebImageControl1.ElementHandle.style.setProperty('height','50');

And also tried:

WebImageControl1.Picture.Width := NewWidth;
WebImageControl1.Picture.Height := NewHeight;

But nothing does anything at all to the image. It just stays unchanged.

So, what is the correct way to change the dimensions? It can't be that complicated...

I cannot see a problem.
Sample project attached.Project1.zip (211.8 KB)

Your sample uses

webimagecontrol1.URL := 'data:image/png;base64,' + GetBase64Image(webimagecontrol1.ElementHandle, 100,100);

To be honest, I would have never expected that instead of using Width/Height or ResizeImage of the component I need to do this rather unusual method. This is not the expected Delphi way...

And even if I knew that there exists a function GetBase64Image in WebLib.WebTools, it is declared there as function GetBase64Image(AImage: TJSHTMLElement): string; with no sizing parameters at all. Only a closer research in the Core Source instead of the Component Library Source reveals this declaration: function GetBase64Image(AImage: TJSHTMLElement; AWidth: integer = 0; AHeight: integer = 0): string;. So how should one know that this function exist with these parameters?

Now, while the small sample project works with respect to resizing, in my app it fails in the call to GetBase64Image in the line that says var dataURL = canvas.toDataURL("image/png");

this.GetBase64Image = function (AImage, AWidth, AHeight) {
    var Result = "";
    var s = "";
    var m = null;
    s = "";
    m = AImage;
    function getBase64Image(img) {
      var canvas = document.createElement("canvas");
      if (AWidth == 0) {
        canvas.width = img.width; }
        else {
        canvas.width = AWidth; }
      if (AHeight == 0) {
      canvas.height = img.height; }
      else {
        canvas.height = AHeight; }
      var ctx = canvas.getContext("2d");
      if ((AWidth == 0) || (AHeight == 0)) {
         ctx.drawImage(img, 0, 0); }
      else {
         ctx.drawImage(img, 0, 0, AWidth, AHeight); }
      var dataURL = canvas.toDataURL("image/png");       <<====== Error
      return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
    }
    s = getBase64Image(m);
    Result = s;
    return Result;
  };

With this error:

What does this error mean and how can I prevent this?

Edit: To also get this error in the sample app, the only change needed to be made is to not load a local image but a remote image from a server, as shown here:

Test3.zip (218.3 KB)

The image initially loads fine but then errors on resize.

Background:

It is a security measure, you are not supposed to 'steal' images from other domains that block their resources for cross-domain accesses.

After reading the Stackoverflow article and some rounds of keyword-bingo, I found that adding the crossorigin="anonymous" attribute to the image tag solves the problem. For readers unfamiliar with setting attributes, it goes like this:

  // ADD THIS BEFORE LOADING AN IMAGE
  webimagecontrol1.ElementHandle.setAttribute('crossorigin','anonymous');

  webimagecontrol1.URL :=
     'https://www.tmssoftware.com/site/img/logo_tms_software.png'

Now resizing is possible. Of course, in order for this to work, on the server the beloved CORS has to be enabled...

Now that this is solved, I still have to say that doing:

webimagecontrol1.URL := 'data:image/png;base64,' + GetBase64Image(webimagecontrol1.ElementHandle, NewWidth, NewHeight);

in order to resize an image is by far not the usual Delphi way and very contra-intuitive. Please TMS, put it on the list of feature requests to find a more Delphi style way, like e.g. setting the usual Width/Height properties of the TWebImageControl.

In v1.6.2.0, WebImageControl1.ResizeImage(NewWidth,NewHeight) should do it now.