Search code examples
javascriptcanvasthree.jsjpeg

SOI not found from saved canvas image


I have an experimental application using Three.js, in which I am allowing the user to save a diagram he draws on a canvas element as a JPEG. I am doing so by using:

<a id="download" download="PathPlanner.jpg">Download as image</a>

function download() {
var dt = canvas.toDataURL('PathPlanner/jpeg');
this.href = dt;
}
document.getElementById('download').addEventListener('click', download, false);

while making sure that

preserveDrawingBuffer: true

This works fine, and the saved jpeg image may look something like this:

enter image description here

I am then experimenting with this package, which accepts an image and finds the shortest distance between two points following any particular line color. Path-from-image package uses jpeg-js to encode and decode images.

As far as I know the 0th and first bytes of a JPEG image are always 0xFF and 0xD8, However, I keep getting the following error on the saved .jpg image file:

Uncaught Error: SOI not found at constructor.parse

I am using the example code from path-from-image package to test it's functionality in my application. The code is:

        const fs = require('fs');
        const jpeg = require('jpeg-js');
        const PathFromImage = require('path-from-image');

        const redPointCoords = [0, -16];
        const bluePointCoords = [0, 0];

        const image = jpeg.decode(fs.readFileSync('Images/PathPlanner.jpg'), true);
        const pathFromImage = new PathFromImage({
            width: image.width,
            height: image.height,
            imageData: image.data,
            colorPatterns: [{ r: [128], g: [128], b: [128] }], // 
             description of the gray color
        });
        const path = pathFromImage.path(redPointCoords, bluePointCoords);
        console.log(path);

The error is pointing to const image = jpeg.decode(fs.readFileSync(''), true);

While the error is generated here:

        var fileMarker = readUint16();
        if (fileMarker != 0xFFD8) { // SOI (Start of Image)
            throw new Error("SOI not found");
        }

This is Line 598 in jpeg-js/lib/decoder.js.

The package works well with other images but not with the image I am allowing the user to save.

Any pointers on how to overcome this issue?


Solution

  • The documentation about .toDataURL() says: canvas.toDataURL(type, encoderOptions);. In your example of code,

    var dt = canvas.toDataURL('PathPlanner/jpeg');` 
    

    this method gets wrong mime-type, thus it produces PNG as default, which should be 'image/jpeg', and the result will be like that:

    var dt = canvas.toDataURL('image/jpeg');