parallax / jsPDF

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

RangeError: offset is out of bounds: Some PNG filters are not processable #3004

Open tarekis opened 3 years ago

tarekis commented 3 years ago

Adding PNGs via addImage with certain filters throws an error:

offset is out of bounds RangeError: offset is out of bounds
    at Uint8Array.set (<anonymous>)
    at applyPngFilterMethod (http://raw.githack.com/MrRio/jsPDF/master/dist/jspdf.umd.js:21341:18)
    at compressBytes (http://raw.githack.com/MrRio/jsPDF/master/dist/jspdf.umd.js:21280:15)
    at Object.jsPDFAPI.processPNG (http://raw.githack.com/MrRio/jsPDF/master/dist/jspdf.umd.js:21650:23)
    at Object.processImageData (http://raw.githack.com/MrRio/jsPDF/master/dist/jspdf.umd.js:10309:56)
    at Object.jsPDFAPI.addImage (http://raw.githack.com/MrRio/jsPDF/master/dist/jspdf.umd.js:10245:36)
    at eval (eval at <anonymous> (http://raw.githack.com/MrRio/jsPDF/master/examples/js/editor.js:177:11), <anonymous>:2:5)
    at http://raw.githack.com/MrRio/jsPDF/master/examples/js/editor.js:177:11 RangeError: offset is out of bounds
    at Uint8Array.set (<anonymous>)
    at applyPngFilterMethod (png_support.js:167)
    at compressBytes (png_support.js:106)
    at Object.jsPDFAPI.processPNG (png_support.js:477)
    at Object.processImageData (addimage.js:883)
    at Object.jsPDFAPI.addImage (addimage.js:819)
    at eval (eval at <anonymous> (editor.js:177), <anonymous>:2:5)
    at editor.js:177

Please bear with me, I am certainly no expert on images, but I'd like to relay my findings on this error.
Some PNG images cannot be processed if they are directly added with addImage via URL (previously I have included them by creating a data URL from a canvas). The issue is this code that seems to apply PNG filters: https://github.com/MrRio/jsPDF/blob/82d3b7d72861e06c4c167ec562715c6734c3f709/src/modules/png_support.js#L167

Previous method VS new method for context Previous method ```typescript public static imageToDataUrl( image: HTMLImageElement, width: number = image.naturalWidth, height: number = image.naturalHeight, mode: 'contain' | 'scale' = 'contain' ): string { const canvas = document.createElement('canvas'); canvas.height = height; canvas.width = width; const context = canvas.getContext('2d'); context.clearRect(0, 0, width, height); const imgAr = +Big(image.naturalWidth).div(image.naturalHeight); const destinationAr = +Big(width).div(height); if (mode === 'scale' || imgAr === destinationAr) { context.drawImage(image, 0, 0, width, height); } else if (mode === 'contain') { if (imgAr < destinationAr) { const scaledWidth = +Big(height).times(imgAr); context.drawImage(image, +Big(width - scaledWidth).div(2), 0, scaledWidth, height); } else { const scaledHeight = +Big(width).div(imgAr); context.drawImage(image, 0, +Big(height - scaledHeight).div(2), width, scaledHeight); } } return canvas.toDataURL('image/png'); } [...] const image = await PDFCreator.loadImage(imageURL); pdf.addImage(PDFCreator.imageToDataUrl(image), [...]); ``` New method ```typescript pdf.addImage(imageURL, [...]); ``` This was changed because now this generation happens in a offloaded worker, which no longer can access canvases BTW.

This can be worked around by changing the image source to a JPEG, that still works.
This does not occur on all PNG images, but only on certain ones, what exactly determines it will fail I don't know, but it seems it has nothing to do with the image mode (indexed/RGB/CMYK all seem to behave the same), I have tested a series of images for products where you can see the material the products are made of, all with the same material pattern fail, some other material patterns all work, which means of images by the same source - that probably have different filters because of the different materials - some fail and some don't

I have uploaded one failing image to imgur, you can replicate the error by opening the live demo and adding this code:

var doc = new jsPDF();
doc.addImage("https://i.imgur.com/LcEVqn4.png", 15, 40, 180, 180);
michaelzangerle commented 3 years ago

I just tried to replicate this issue and played a bit around with the image in Gimp. I found out that the image in question has Indexed as Image > Mode set. Setting it to RGB and exporting it (not just saving - maybe that makes a difference as well) with the default gimp settings seems to prevent the error from happening.

var doc = new jsPDF();
doc.addImage("https://i.imgur.com/ry7GVJ6.png", 15, 40, 180, 180);

I have no idea what making this change means in context of the code, but it would be nice if this could be solved in the code :see_no_evil:

HackbrettXXX commented 3 years ago

@michaelzangerle could you may try to fix this in the code? Since you already found out the reason for the issue, I think it should not be that hard to fix this in code.

michaelzangerle commented 3 years ago

@HackbrettXXX I just tried a bit around with GIMP as I am also affected by this issue in a project and had similar issues in the past. But I am afraid I am no JS developer and have no idea what this change of the image mode means in terms of the code here. Sorry :see_no_evil: If I can be of some help otherwise I will gladly do so.

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.

Bogghi commented 1 year ago

Hi, i've encountered this issue in my code with this specific image. Has anyone found a solution? I'm not clear on what i have to do with the image, since the problem seems to be there. carFilter

tarekis commented 1 year ago

As @michaelzangerle has stated above, you need to change the color profile of your image to work, that is the current workaround. E.g. changing the mode in GIMP works, whatever other image manipulation program you‘d use probably has a similar feature.

Bogghi commented 1 year ago

@tarekis sorry for the late answer, being busy at work. That really helped and made me go throw the issue.

Thank you so much for the clarification.

skostojohn commented 4 months ago

I am also encountering this issue. The fix using GIMP to update the image worked for me, but it would be great to get this fixed if possible!