Convert a image url to pdf using jspdf

27,868

Solution 1

Here is my solution for the same problem.

let logo = null;

getDataUri(imgUrl, function(dataUri) {
    logo = dataUri;
    console.log("logo=" + logo);
});

function getDataUri(url, cb)
 {
        var image = new Image();
        image.setAttribute('crossOrigin', 'anonymous'); //getting images from external domain

        image.onload = function () {
            var canvas = document.createElement('canvas');
            canvas.width = this.naturalWidth;
            canvas.height = this.naturalHeight; 

            //next three lines for white background in case png has a transparent background
            var ctx = canvas.getContext('2d');
            ctx.fillStyle = '#fff';  /// set white fill style
            ctx.fillRect(0, 0, canvas.width, canvas.height);

            canvas.getContext('2d').drawImage(this, 0, 0);

            cb(canvas.toDataURL('image/jpeg'));
        };

        image.src = url;
   }

Then to generate the pdf

    var doc = new jsPDF();

    let left = 15;
    let top = 8;
    const imgWidth = 100;
    const imgHeight = 100;

    doc.addImage(logo, 'PNG', left, top, imgWidth, imgHeight);

    doc.output('dataurlnewwindow'); //opens pdf in new tab

Solution 2

I have created the following example: open in fiddle

<html>
<meta charset="utf-8" />
<body>
    <div style='font-size:30px'>
        <button style='font-size:50px' onclick="jsPDFimages()">create pdf</button>
    </div>
</body>
</html>
<script src="https://unpkg.com/jspdf@latest/dist/jspdf.min.js"></script>

<script>
    var imagesList 
    const doc = new jsPDF();
    const imagesWidth = []
    const imgDataList = []
    const img = new Image();
    var ImageToLoad = new Image();
    jsPDFimages()
    function getImageFromUrl(url, callback) {

        ImageToLoad.crossOrigin = "Anonymous";

        ImageToLoad.onError = function () {
            console.log('Cannot load image: "' + url + '"');
        };

        ImageToLoad.onload = function () {
            alert("image is loaded");
        }

        ImageToLoad.onload = function () {
            imagesWidth.push({
                width: ImageToLoad.width,
                height: ImageToLoad.height
            })
            callback(ImageToLoad);
        };
        ImageToLoad.src = url;
        createPDF(ImageToLoad)
    }
    function createPDF(imgData) {
        imgDataList.push(imgData)
        var pwidth = doc.internal.pageSize.getWidth();
        var pheight = doc.internal.pageSize.getHeight();
        var maxWidth = pwidth - 40; // Max width for the image
        var maxHeight = pheight - 40;    // Max height for the image
        var ratio = 0;  // Used for aspect ratio
        var width = imgData.width;    // Current image width
        var height = imgData.height;  // Current image height
        // Check if the current width is larger than the max
        if (width > maxWidth) {
            ratio = maxWidth / width;   // get ratio for scaling image
            // $(this).css("width", maxWidth); // Set new width
            // $(this).css("height", height * ratio);  // Scale height based on ratio
            height = height * ratio;    // Reset height to match scaled image
            width = width * ratio;    // Reset width to match scaled image
        }
        // Check if current height is larger than max
        if (height > maxHeight) {
            ratio = maxHeight / height; // get ratio for scaling image
            // $(this).css("height", maxHeight);   // Set new height
            // $(this).css("width", width * ratio);    // Scale width based on ratio
            width = width * ratio;    // Reset width to match scaled image
            height = height * ratio;    // Reset height to match scaled image
        }
        doc.addImage({
            imageData: imgData,
            x: 20,
            y: 5,
            w: width,
            h: height,
            angle: -20
        });
        if (imgDataList.length !== Object.keys(imagesList).length)
            doc.addPage();
        if (imgDataList.length == Object.keys(imagesList).length) {
            doc.save('sample-file.pdf');
            //window.open(doc.output('bloburl'), '_blank');
        }
    }

    function jsPDFimages() {
        imagesList={ "imag1": "https://as2.ftcdn.net/jpg/00/42/98/87/500_F_42988762_JMNpHWOFWnbtCBZeYsRo5PmzD28rIquS.jpg", "imag2": "https://as2.ftcdn.net/jpg/00/42/98/87/500_F_42988762_JMNpHWOFWnbtCBZeYsRo5PmzD28rIquS.jpg" }
        for (var item in imagesList) {
            getImageFromUrl(imagesList[item], createPDF);
        }
    }
</script>

Also this do the same

<script src="https://unpkg.com/jspdf@latest/dist/jspdf.min.js"></script>
<script>
    function getDataUri(url,callback)
{
        var image = new Image();
        image.setAttribute('crossOrigin', 'anonymous'); //getting images from external domain
        image.onload = function () {
            var canvas = document.createElement('canvas');
            canvas.width = this.naturalWidth;
            canvas.height = this.naturalHeight; 

            //next three lines for white background in case png has a transparent background
            var ctx = canvas.getContext('2d');
            ctx.fillStyle = '#fff';  /// set white fill style
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            canvas.getContext('2d').drawImage(this, 0, 0);
            // resolve(canvas.toDataURL('image/jpeg'));
            callback(canvas.toDataURL('image/jpeg'));
        };
        image.src = url;  
}

var doc = new jsPDF();

getDataUri("https://as2.ftcdn.net/jpg/00/42/98/87/500_F_42988762_JMNpHWOFWnbtCBZeYsRo5PmzD28rIquS.jpg", createPDF);

function createPDF(logo) {
    doc.addImage(logo, 'jpg', 0, 5, 50, 50);
    doc.save('sample-file.pdf');
}

</script>

or this :)

//Function converts an image URL to a Base 64 string
// "url"       - The URL of the image
// "callback"  - The function that is called on completion.
//               The Base 64 string is passed to the
//               callback as an argument.
function toDataUrl(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.onload = function() {
    var reader = new FileReader();
    reader.onloadend = function() {
      callback(reader.result);
    };
    reader.readAsDataURL(xhr.response);
  };
  xhr.open('GET', url);
  xhr.responseType = 'blob';
  xhr.send();
}

// Create and save  the PDF.
// The argument is the Base64 string for the image.
function makePDF(base64Img) {
  var doc = jsPDF({ // reinitialize doc
    orientation: "portrait",
    unit: "in",
    format: "letter"
  });
	doc.addImage(base64Img, "JPEG", 0, 0, 8.5, 11);
	doc.save();
}

// Convert URL to Base64, then call makePDF function.
toDataUrl("https://as2.ftcdn.net/jpg/00/42/98/87/500_F_42988762_JMNpHWOFWnbtCBZeYsRo5PmzD28rIquS.jpg", makePDF);

// The following is theoretically equivalent, but it
// currently would fail, due to jsPDF not accepting a
//URL string as a parameter.

//makePDF("https://promo.bradbrownmagic.com/pdf-flyer/flyers/poster-dark-cmyk.jpg")
<script src="https://unpkg.com/jspdf@latest/dist/jspdf.min.js"></script>

Solution 3

If you prefer the async/await mechanism, you can modify the function in Craig Howard's answer to return a promise:

function getDataUri(url)
{
    return new Promise(resolve => {
        var image = new Image();
        image.setAttribute('crossOrigin', 'anonymous'); //getting images from external domain

        image.onload = function () {
            var canvas = document.createElement('canvas');
            canvas.width = this.naturalWidth;
            canvas.height = this.naturalHeight; 

            //next three lines for white background in case png has a transparent background
            var ctx = canvas.getContext('2d');
            ctx.fillStyle = '#fff';  /// set white fill style
            ctx.fillRect(0, 0, canvas.width, canvas.height);

            canvas.getContext('2d').drawImage(this, 0, 0);

            resolve(canvas.toDataURL('image/jpeg'));
        };

        image.src = url;
    })
}

This makes the code for adding images to the pdf quite compact:

var doc = new jsPDF();

var logo = await getDataUri(imgUrl);
doc.addImage(logo, 'PNG', left, top, imgWidth, imgHeight);

Share:
27,868
Jeremy Cook
Author by

Jeremy Cook

Husband and da-da, passionate about helping others via the software I write.

Updated on July 09, 2022

Comments

  • Jeremy Cook
    Jeremy Cook almost 2 years
    function convertImgToBase64(url)
    {
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        img = document.createElement('img'),
        img.src = url;
        canvas.height = img.height;
        canvas.width = img.width;
        var dataURL = canvas.toDataURL('image/jpeg')
        alert(dataURL);
        canvas = null; 
        return dataURL;
      }
    
    var imageurl = 'http://qph.is.quoracdn.net/main-qimg-ca033a73e2ea858908c44905d4c25f4b?convert_to_webp=true';
    var som =convertImgToBase64(imageurl);
    doc.addImage(som, 'JPEG', 15, 40, 180, 180);
    doc.output('datauristring');
    

    but nothing happens no pdf is generated ? I am getting the correct base64 code in alert box but image is not generated?

  • Jar
    Jar about 5 years
    I get 'Uncaught TypeError: Cannot read property 'nodeType' of null at isDOMElement (jspdf.debug.js:4199) at Object.jsPDFAPI.addImage (jspdf.debug.js:4534)' when I try to use this answer