Pdf file size too big created using jspdf
Asked Answered
M

6

50

I am using jspdf for creating PDF inside browser. I am having multiple charts having svg as chart Data. For adding data to pdf I am converting svg to png using canvas and then Base64 Data using canvas.toDataURL method. After all this conversions size of the file created by jspdf is huge (about 50 MB). Below is the code for div of chart data and canvas.

newdiv = document.createElement("div");
newdiv.className = "big_Con_graph big_Con_graph0";
newdiv.style.height = "0px";
newdiv.id = "big_Con_graph" + id;

below is the dimensions for SVG chart load.

document.getElementById("big_Con_graph" + id).style.display = "block";
var big_chartReference = FusionCharts("big_myChartId"+id);
if(big_chartReference != null){
    big_chartReference.dispose();
}
var big_width = "1088";
var big_height = "604";

now below is the code for conversion of above graph SVG data and adding to PDF.

var elem_graph = $($('.big_Con_graph,big_Con_graph0')[count]).clone(true);
svgString = $(elem_graph).find("span").html();
var img = document.createElement('img');
var DOMURL = self.URL || self.webkitURL || self;
var svg = new Blob([svgString], {type: "image/svg+xml;charset=utf-8"});
var url = DOMURL.createObjectURL(svg);
img.onload = pdfAfterImageLoad(img,pdf,imgLoadSequence,DOMURL,totalReports,reportName);
img.src = url;

this is the code for PDFAfterImageLoad function:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var png = canvas.toDataURL("image/png");
pdf.addImage(png, 'PNG', leftmargin, 120, 485, 270);

I am using png, so imagequality parameter can not be used.

Can anyone help me decrease the file size?

Maund answered 7/6, 2016 at 11:10 Comment(8)
Do you convert to base64 because jspdf requires that?Langston
i dont have image stored at my end by clicking of button i m getting svg data and converting it to png by canvas,so the whole process requires base64 data.even i can't store all graph data at client storage.Maund
I see. And why are you using png instead of jpeg? Using jpeg with quality modifier would have helped (see developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/…)Langston
yes but jpeg gives poor quality as used with quality parameter also.even i want to zoom in and zoom out with pdf which is not possible with jpeg.Maund
What are the dimensions of this image? Can you show us what the image contains/does it apply to any image you add? Can you show us the code you use to add it to jspdf? (and your onload callback is used in the wrong way, should a function reference; now it's a call using the result of that for onload).Hypesthesia
Thanks for the update. It still a bit unclear what the pdfAfterImageLoad is doing. And as I mentioned above it is used incorrectly. It is now called and the result of it (which may be none) is set as the handler function to onload. Also, if the image does not load in time drawImage will fail below. The drawing operations need to be inside (or invoked from) the onload handler function.Hypesthesia
@K3N i have appended the code for pdfafter image load as it just add the image on pdf.nothing elseMaund
I reckon you will have to use image/jpeg and test possible and suitable quality parameter!Deserving
A
112

You need to compress the images in the PDF's that you are generating. Try using Deflate.js and adler32cs.js and use the compress parameter in both jsPDF and addImage functions that you are using. For eg :

var doc = new jsPDF('p', 'pt','a4',true);

make sure you set the last parameter as 'true' refer to : https://github.com/MrRio/jsPDF/blob/ddbfc0f0250ca908f8061a72fa057116b7613e78/jspdf.js#L146

Go through it and you can clearly see that the last parameter is for enabling compression.

Also use :

pdf.addImage(png, 'PNG', leftmargin, 120, 485, 270,'','FAST');

instead of

pdf.addImage(png, 'PNG', leftmargin, 120, 485, 270);

you can choose between NONE, FAST, MEDIUM and SLOW, whichever suits you best.

Annuitant answered 20/6, 2016 at 6:12 Comment(9)
this works. Am getting one border line at the bottom - using jspdf addimag. how to remove that lineBlowgun
anyway the horizontal line is not printed on the paper.Blowgun
I am creating pdf from a custom graph. I am able to generate pdf using jspdf. But color of graph and font color from the web page are replicating on the pdf. (box-shadow effect is missing from graph and graph is looking blur). How can i fix it.?Maseru
@HemantKumar can you give the link with the jsfiddle.so i can guide you with the solution..actually svg that charts generates creates the problem.we need to eliminate some tag or correct it,Maund
Ok. Sure I'll try to jsfiddle it. I'll figure out how to set it in jsfiddle.Maseru
why didn't it work for chrome? although it worked before without compressing pdf as you solution said.Gaffer
This is not working, tested in Edge and Firefox, adding compression changes nothing, Im not using node.jsParthenia
Hi @Parthenia I'm sure the OP doesn't make use of node.js either. As for the solution provided, it works for the scenario mentioned in the post, i.e decreasing the size of a png using compression in the addImage(). If your problem is different and if you are using jpeg, please use the compression as suggested in a couple of other solutions. Just be mindful that using compression with jpeg will result in poor image quality but will cut down on the pdf drastically.Annuitant
for real? 28 MB to 300KbJodhpurs
L
25

If you add several images to one document, use

pdf.addImage(png, 'PNG', leftmargin, 120, 485, 270, undefined,'FAST');

not

pdf.addImage(png, 'PNG', leftmargin, 120, 485, 270,'','FAST');

otherwise the first image will substitute all others.

Ladawnladd answered 9/12, 2016 at 21:13 Comment(3)
yes..it was just example given,, pdf.addImage(png, 'PNG', leftmargin, 120, 485, 270, undefined,'FAST'); in that undefined one,you have to specify different name everytime whenever you add the image.as per API it is the Alias name.which has to be unique per image.Maund
Just jumping on to say the above example also reduced my 4Mb PDF (11 pages, with 10 charts per page) down to 977kb. Thank you so much for this tip!Glandulous
I have tried doc.addImage(imgData, "JPEG", 140, 15, 300, 300, "alias1",undefined, 'SLOW'); but I am getting error Uncaught Error: getJpegSize could not find the size of the imageHaystack
C
7

Perfect. PDF size 90mb to 3mb with great quality.

pdf.addImage(png, 'PNG', 0, 0, 485, 270, undefined,'FAST');

Citronella answered 2/3, 2020 at 1:57 Comment(1)
please elaborate more on your answer, I can't see any var pdf in the OPRosariarosario
C
1

In my case did not work with compress parameter. So, I resized the current image on my own with the following function:

function resizeBase64Img(base64, width, height) {
    var canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    var context = canvas.getContext("2d");
    var deferred = $.Deferred();
    $("<img/>").attr("src", "data:image/gif;base64," + base64).load(function() {
        context.scale(width/this.width,  height/this.height);
        context.drawImage(this, 0, 0); 
        deferred.resolve($("<img/>").attr("src", canvas.toDataURL()));               
    });
    return deferred.promise();    
}

And call it as follows:

//select my image in base64
var imageStr64 = "/9j/4RiDRXhpZgAATU0AKgA...";
//resize image, add image and create the pdf
resizeBase64Img(imageStr64, 1000, 1000).then(function(newImg){
    doc.addImage($(newImg).attr('src'), 15, 90, 180,180);
    doc.save('mypdf.pdf');
});

You can play with 'width' and 'height' parameters in resizeBase64Img function in order to generate heavy pdf with better or worst image quality.

Chalmer answered 8/5, 2018 at 12:16 Comment(0)
L
0

Have you tried canvg? It's not very likely that it will decrease the filesize, but at least you can try.

See a snippet in this reply.

Langston answered 15/6, 2016 at 17:28 Comment(1)
yes i m already using canvg for IE and safari browsers.but its related with any file size decrease.Maund
P
0

I've tried the compress parameter and passing compression:'MEDIUM' toe the addImage method as suggested but nothing happened

What worked for me was converting the canvas to DataUrl base64 string and passing a compression value

pdf.addImage({ imageData: canvas.toDataURL('image/jpeg', 0.6),format: 'JPEG', x: 2, y: 100, width: newImageWidth, height: newImageHeight});

This way the image is compressed before it is added to the PDF

Parthenia answered 16/7, 2021 at 12:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.