parallax / jsPDF

Client-side JavaScript PDF generation for everyone.
https://parall.ax/products/jspdf
MIT License
28.67k stars 4.61k forks source link

Randomly blurred document #2773

Open mathias22osterhagen22 opened 4 years ago

mathias22osterhagen22 commented 4 years ago

I'm using the jsPDF package to generate PDF document based on img from the web page. The img are in a div where they are resized to a lower with and height (but still keeping the same ratio A4).

I do the basic following:

  1. create an empty document
  2. add a page
  3. add the image
  4. save the doc

My problem is that randomly for some reason, the pdf generated is totally blurred. When I click on the picture, it opens the visualizer (viewers) and no pictures are blurred (all based on the same src) only the export is failing.

What could possibly be the reason? If the pictures are loaded well why is it blurred?

funnykanth commented 4 years ago

how are adding the content to the page?

Just be aware that .addHTML() ... is now depricated.

mathias22osterhagen22 commented 4 years ago

Hello @funnykanth, thank you for your answer.

The code is

I put you the entire code I'm using (in vue.js):

  extractPDF: function() {
        let doc = null;

        let isLandscape = page => {
          return this.file.orientation[page] == 90 ||
            this.file.orientation[page] == 270
            ? "l"
            : "p";
        };

        //NOTE: Add all pages:
        let width = 0;
        let height = 0;
        for (var i = 0; i < this.file.checked.length; i++) {
          let page = this.file.checked[i];
          let element = this.$el.querySelector("#page-" + page);

          let orientation = isLandscape(page);
          if (i == 0) {
            doc = new jsPDF({
              orientation: orientation
            });
          } else {
            doc.addPage(null, isLandscape(page));
          }
          width = doc.internal.pageSize.getWidth();
          height = doc.internal.pageSize.getHeight();
          if (orientation == "p") {
            if (this.file.orientation[page] == 0)
              doc.addImage(element, "JPEG", 0, 0, width, height);
            else if (this.file.orientation[page] == 180)
              doc.addImage(
                element,
                "JPEG",
                width,
                -height,
                width,
                height,
                null,
                null,
                -180
              );
          } else if (orientation == "l") {
            if (this.file.orientation[page] == 90)
              doc.addImage(
                element,
                "JPEG",
                0,
                -width,
                height,
                width,
                null,
                null,
                -90
              );
            else if (this.file.orientation[page] == 270)
              doc.addImage(
                element,
                "JPEG",
                width,
                -(width - height),
                height,
                width,
                null,
                null,
                -270
              );
          }
        }
        //NOTE: Convert to pdf and save
        doc.save(this.file.name + this.indexValue + ".pdf");
    },

Basically its addImage function used.

HackbrettXXX commented 4 years ago

Can you condense your code into a minimal repro? Optimally, include one of the images that is blurred. Please also test with the current master branch.

mathias22osterhagen22 commented 4 years ago

Sure: https://github.com/mathias22osterhagen22/jsPDF-issues2773

Problem is that the image is not blurred all time, I even didn't succeed thousands of times to reproduce. It just occurs randomly on my user's side.

I would want to know in which case jsPDF could add a blurred image to be added to the document.

HackbrettXXX commented 4 years ago

I've tried your sample a couple of times but I can't reproduce the issue. I assume this is some kind of browser or timing issue. In which browser could you reproduce it? If I'm not able to reproduce the issue, I'm afraid I can't do much about this. Especially since I think this is not a bug in jsPDF. Maybe you can try debugging yourself?

mathias22osterhagen22 commented 4 years ago

They are using Chrome in a really special environment that I can't access (computers made to only remote windows access session), I tried to debug with puppeteer, like keep repeating the action in a loop. Impossible to reproduce.

I was thinking too that could be a browser timing issue, in chrome you can debug turning your connection slower : image

Still the same, jsPdf is always waiting at the end of the download before generating the pdf.

I was maybe expecting chrome to cache the images "sometimes" because in fact they are already loaded twice on the same page (one time for the page and another for the "viewers" in a div hidden (not really clean but easier to fix)) and then by clicking on the "export button" it makes a "get" request for each image (jsPdf fire it). Then could it be possible than chrome answer to jsPdf some low-quality image cached instead of making a real get?

This issue is really curious I think to solve it would make everybody get some knowledge haha.

mathias22osterhagen22 commented 4 years ago

Dear @HackbrettXXX , we finnaly succed to find the problem this morning you will never guess.

Indeed it's not linked with the jsPDF library even if this blur document made me thought that. There is what happened :

  1. The user go on the website that is protected by a self security, the user then accept the untrusted certificate
  2. The user go to process the file (convert img to pdf) he can see the dashboard that you can find above in our discussion. He can see well the pictures nothing to signal.
  3. After X time the browser (chrome) "UNACCEPT" automatically in background the untrusted certificate.
  4. Click on the extract button result into a 404 error: image
  5. The result document is completely blur: image

The point was that I was thinking that if jsPDF get a 0k image by the ajax call it would result into an empty document, I don't know at all how jsPDF could get this low version image.

I'm supposing that the library is making some cache of the already loaded picture? Else it means that is chrome that give to the lib some thumbnail cache instead of a 0k image data.

I let this issue open just time that someone answers about this two last questions.

HackbrettXXX commented 4 years ago

Glad you found the root of the issue. jsPDF caches the image only if the same image is included multiple times into one PDF. Otherwise it does a fresh XHR.

mathias22osterhagen22 commented 4 years ago

Otherwise it does a fresh XHR.

Sorry to re-open, but how it is possible that I get a blurry image if it does a fresh XHR? Example:

Is there an explanation? Is jsPdf having a special behavior if the data from the HXR are 0k size? Like trying to manage in another way to get the image bytes?

jsPDF caches the image only if the same image is included multiple times into one PDF.

PS: I tried adding 3 times in a row the same image (on one new page each time) it makes a fresh HXR each time without caching. image

HackbrettXXX commented 4 years ago

I think someone needs to have a closer look at this. However, this currently has no high priority for the next release, as there are far more important open issues. I'm gonna reopen this so it is not forgotten.

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 90 days with no activity. It will be closed soon. Please comment/reopen if this issue is still relevant.

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 90 days with no activity. It will be closed soon. Please comment/reopen if this issue is still relevant.