0

I am trying to generate a PDF from HTML using jspdf plugin. I am stuck with loading Images into PDF. There is a function addImage() in plugin which takes base64 encoding of an image, but converting an image to base64 is not working.

I have used below two ways

//Create canvas, draw image in context and get the data url

imgToDataURL =  function (img, outputFormat){
        var canvas = document.createElement('canvas');
        canvas.width = 20;
        canvas.height = 20;
        var c = canvas.getContext('2d');
        c.height = img.height;
        c.width=img.width;
        c.drawImage(img, 0, 0);
        c.save();
        var dataurl = canvas.toDataURL(outputFormat);
        return dataurl;

    }

var img = new Image();
img.crossOrigin = 'Anonymous';
img.src = "image path"
img.height= 60;
img.width=60;
var dataURL = this.imgToDataURL(img,"image/jpeg");
renderer.pdf.addImage(dataURL, 'png',x+padding,y + this.internal.getLineHeight(),imageWidth,imageHeight);

This is printing wrong dataURL I am getting a white image. If I hard code the base64 code i.e return a hardcoded dataURL then addImage works fine. So the issue is with canvas.toDataURL which is giving me wrong output

this is the 2nd way

convertImgToBase64URL =  function (url, callback, outputFormat){
    var img = new Image();
    img.crossOrigin = 'Anonymous';
    img.onload = function(){
        var canvas = document.createElement('CANVAS'),
        ctx = canvas.getContext('2d'), dataURL;
        canvas.height = this.height;
        canvas.width = this.width;
        ctx.drawImage(this, 0, 0);
        dataURL = canvas.toDataURL(outputFormat);
        callback(dataURL);
        canvas = null; 
    };
    img.src = url;
}

this.convertImgToBase64URL("Image Path",function(base64){

    renderer.pdf.addImage(base64, 'PNG', 20, 20,48,48);
})

I have run this inside a javascript and the onload function is not even running I am not sure what is my mistake is.

Please suggest me what mistake I am doing in either way

  • You have to wait for your images are loaded before drawing them to the canvas context. Also, are you sure you serve the image with correct cross-origin headers? If your server is not set correctly, the `"anonymous"` request will be blocked and your image won't ever load. Beside it, there are few issues in your first snippet (i.e context2d has no width nor height properties, and `save()` is useless here) but none should block your code. – Kaiido Oct 01 '15 at 02:52
  • True, but I am not sure how can I check that whether image is loaded or not. And for few images I do get below exception " Image from origin 'Image server path' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access." So what does this exactly mean. I am a novice in javascript/HTML and all these stuff I am sorry if I am asking any obvious question. – Amit Thatavarti Oct 01 '15 at 16:10
  • well you're lucky I just wrote these question and answer for these exact same cases (you're not the only one in that case) : http://stackoverflow.com/questions/32880641/canvascontext2d-drawimage-issue/32880642#32880642 – Kaiido Oct 01 '15 at 17:24
  • @Kaiido I wrote a similar one but unfortunately the img.onload never get executed. And I am not sure how to set the Access-Control_Allow-Origin" header . One point to note is I am writing everything in a single JS file and adding this file in HTML. Will this be any problem for loading the image ? – Amit Thatavarti Oct 01 '15 at 18:13
  • @Kaiido I am able to get the images now but I am using CORS extension of chrome and enabled cross-origin-resource sharing there. If I disable there then Images are not loading. Can you help me resolving this issue. And the images that I am accessing is in public folder of a server I am able to access the image from web browser – Amit Thatavarti Oct 01 '15 at 20:15
  • Did you read the link in the dupe answer? CORS headers must be supplied by the server. I don't know what your extension pretends to do, but it won't be able to hack it. You are able to display it in an `` element, and even to draw it, but you won't be able to use the `toDataURL()` or `getImageData()` of the canvas anymore. If some of your images are from your server, and some others are from a CORS compliant server, then you could try setting the `img.crossOrigin="anonymous"` by default and add an `onerror=function(){this.crossOrigin=''; this.src=this.src};` for the ones from your server. – Kaiido Oct 02 '15 at 00:55
  • @Kaiido I tried to replace all the server images to local file system images even then I am getting this error Image from origin 'file://' has been blocked from loading by Cross-Origin Resource Sharing policy: Invalid response. Origin 'null' is therefore not allowed access. What does this mean.. my HTML,JS,Images are all on local file system then why am i getting this error. And when you say server is supposed to supply can you provide me an example what and how the changes are to be done at server side( PS we are using PTC integrity server ) – Amit Thatavarti Oct 09 '15 at 03:06
  • images from file system won't ever be served with proper CORS. What you need instead, is that it comes from the same server (if on a local machine, it would be `http://localhost/`), and then don't set the ``'s crossOrigin attribute, or via an external server, sent with `Access-Control-Allow-Origin: *` in the header of the response, and by setting ``'s crossOrigin attribute to `'anonymous'`. I don't know about PTC integrity, but it does looks like an ALM, not a server system. You can have a look at http://enable-cors.org/server.html it may help you set your server correctly – Kaiido Oct 09 '15 at 05:53

1 Answers1

0

In the first you missed assigning an onload function to your image. For that reason, the moment you try to create the dataURL, the image might not be loaded yet, ergo, the blank image. You could try changing the last few lines to this:

...
img.width=60;
img.onload = function () {
  var dataURL = this.imgToDataURL(img,"image/jpeg");
  renderer.pdf.addImage(dataURL, 'png',x+padding,y + this.internal.getLineHeight(),imageWidth,imageHeight);
}
img.src = "image path";

As for the second one, there seems to be a problem with the convertImgToBase64URL() which accepts 3 parameters, but you are passing 2. In you example, outputFormat parameter is undefined.

1cgonza
  • 1,589
  • 10
  • 20
  • you can call `canvas.toDataURL(undefined)` or any other non-valid value, it will fall back to the default `'image/png'` – Kaiido Oct 01 '15 at 03:10
  • I tried to include img.onload in the first one but the onload function never gets executed. I kept an alert statement to knwo the dataURL but I never got that alert. One thing to be noted is all the processing is going in single JS file. I am passing the image source link and height width from other function and calling imgToDataURL function and get the dataURL link. – Amit Thatavarti Oct 01 '15 at 14:40