3

I'm trying to draw text on a canvas, convert that to an image, and then convert that to a PDF. Most of it is pretty straightforward, but jsPDF seems to always convert the images to PDFs at a ratio of 72 pixels per inch. This produces very blurry, low-resolution images, certainly not suitable for text.

blurry text of "test"

This is what generates that:

const size = [8.5, 11]; // Size in inches
const canvas = document.createElement("canvas");
canvas.width = size[0] * 72;
canvas.height = size[1] * 72;
const context = canvas.getContext("2d");
context.font = "12pt Arial";
context.textBaseline = "top";
context.fillText("test", 200, 100);
const image = canvas.toDataURL("image/png");

const pageOptions = {
    unit: "px",
    format: size.map(s => s * 72),
};
const doc = new jsPDF(pageOptions);
doc.addImage(image, "PNG", 0, 0, size[0] * 72, size[1] * 72);
doc.output('dataurlnewwindow');

If I change all the instances of 72 to say, 300, it will generate an absolutely huge image. If I change only the canvas size to 300 and the font size accordingly but leave everything with jsPDF at 72, it will do exactly what I want in Firefox, if a bit slow, but the resulting PDF will never actually render in Chrome. What's the problem with this code in Chromium-based browsers, and how do I fix it? Or is there a better way to do this?

Ullallulloo
  • 1,105
  • 4
  • 16
  • 31
  • There is a [userUnit](https://artskydj.github.io/jsPDF/docs/jsPDF.html) option which you can use to specify the quality. – Reyno May 12 '22 at 13:46
  • @Reyno I've heard of that, but the documentation literally just says "Please inform yourself before you use it." and doesn't actually inform about it. I can't find any examples of that actually being used. – Ullallulloo May 12 '22 at 13:50

1 Answers1

0

You can set it when you create the object:

const doc = new jsPDF({
  unit: 'px', // set the units of measurement to px
  format: 'letter', // set the 'paper' size
  userUnit: 72, // set the DPI here. Web uses 72 but you can change to 150 or 300
})
PA.
  • 28,486
  • 9
  • 71
  • 95
Melongro
  • 15
  • 4
  • @PA. Thank you for the edit - I was just about to fix the formatting/spacing :) – Melongro May 12 '22 at 14:32
  • 1
    This doesn't seem to change anything. If the image is `72` pixels per inch, it's still blurry, and if it's 300, Chrome still fails to render it. – Ullallulloo May 12 '22 at 15:35
  • Have you looked at Jeny's or Dhanik's answer here: https://stackoverflow.com/questions/29166163/jspdf-addhtml-exporting-low-quality-image-to-pdf – Melongro May 12 '22 at 19:48
  • Also, what version(s) of jspdf are you trying? Are you using html2canvas or other add-ons, if so which ones and what version? – Melongro May 12 '22 at 19:55
  • 1
    I'm using jsPDF 2.5.1. I tried using html2canvas indirectly through the `.html()` method, but I couldn't get it to render anything and `context.fillText()` does the same thing for me. I don't see much difference in approach with those answers. Jeny's just lets html2canvas pick the size instead of doing it manually and Dhanik is basically doing what I'm doing that works in Firefox but not Chrome. – Ullallulloo May 13 '22 at 20:36