Skip to content
Snippets Groups Projects
Select Git revision
  • leo
  • dex
  • pendulum
  • master default protected
  • apfelstruder
  • littlerascal
6 results

helpers.js

Blame
  • helpers.js 30.03 KiB
    const pipe = (first, ...more) => more.reduce((acc,curr) => (...arguments) => curr(acc(...arguments)) , first);
    
    const offsetHelper = (distances, offset, width, height) => {
        var w = width;
        var h = height;
        var offset = offset;
        var input = distances;
        var output = new Uint8ClampedArray(4 * h * w);
        for (var row = 0; row < h; ++row) {
        for (var col = 0; col < w; ++col) {
            if (input[(h - 1 - row) * w + col] <= offset) {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
            } else {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
            }
        }
        }
    
        const imgData = new ImageData(output, w, h);
    
        return imgData;
    };
    
    const edgeDetectHelper = imageRGBA => {
        var h = imageRGBA.height;
        var w = imageRGBA.width;
        var input = imageRGBA.data;
        var output = new Uint8ClampedArray(h * w * 4);
        var i00, i0m, i0p, im0, ip0, imm, imp, ipm, ipp, row, col;
        //
        // find edges - interior
        //
        for (row = 1; row < h - 1; ++row) {
        for (col = 1; col < w - 1; ++col) {
            i00 =
            input[(h - 1 - row) * w * 4 + col * 4 + 0] +
            input[(h - 1 - row) * w * 4 + col * 4 + 1] +
            input[(h - 1 - row) * w * 4 + col * 4 + 2];
            i0p =
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 0] +
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 1] +
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 2];
            ip0 =
            input[(h - 2 - row) * w * 4 + col * 4 + 0] +
            input[(h - 2 - row) * w * 4 + col * 4 + 1] +
            input[(h - 2 - row) * w * 4 + col * 4 + 2];
            ipp =
            input[(h - 2 - row) * w * 4 + (col + 1) * 4 + 0] +
            input[(h - 2 - row) * w * 4 + (col + 1) * 4 + 1] +
            input[(h - 2 - row) * w * 4 + (col + 1) * 4 + 2];
            i0m =
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 0] +
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 1] +
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 2];
            im0 =
            input[(h - row) * w * 4 + col * 4 + 0] +
            input[(h - row) * w * 4 + col * 4 + 1] +
            input[(h - row) * w * 4 + col * 4 + 2];
            imm =
            input[(h - row) * w * 4 + (col - 1) * 4 + 0] +
            input[(h - row) * w * 4 + (col - 1) * 4 + 1] +
            input[(h - row) * w * 4 + (col - 1) * 4 + 2];
            imp =
            input[(h - row) * w * 4 + (col + 1) * 4 + 0] +
            input[(h - row) * w * 4 + (col + 1) * 4 + 1] +
            input[(h - row) * w * 4 + (col + 1) * 4 + 2];
            ipm =
            input[(h - 2 - row) * w * 4 + (col - 1) * 4 + 0] +
            input[(h - 2 - row) * w * 4 + (col - 1) * 4 + 1] +
            input[(h - 2 - row) * w * 4 + (col - 1) * 4 + 2];
            if (
            i00 != i0p ||
            i00 != ip0 ||
            i00 != ipp ||
            i00 != i0m ||
            i00 != im0 ||
            i00 != imm ||
            i00 != imp ||
            i00 != ipm
            ) {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
            } else if (i00 == 0) {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
            } else {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
            }
        }
        }
        //
        // left and right edges
        //
        for (row = 1; row < h - 1; ++row) {
        col = w - 1;
        i00 =
            input[(h - 1 - row) * w * 4 + col * 4 + 0] +
            input[(h - 1 - row) * w * 4 + col * 4 + 1] +
            input[(h - 1 - row) * w * 4 + col * 4 + 2];
        i0m =
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 0] +
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 1] +
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 2];
        imm =
            input[(h - row) * w * 4 + (col - 1) * 4 + 0] +
            input[(h - row) * w * 4 + (col - 1) * 4 + 1] +
            input[(h - row) * w * 4 + (col - 1) * 4 + 2];
        ipm =
            input[(h - 2 - row) * w * 4 + (col - 1) * 4 + 0] +
            input[(h - 2 - row) * w * 4 + (col - 1) * 4 + 1] +
            input[(h - 2 - row) * w * 4 + (col - 1) * 4 + 2];
        im0 =
            input[(h - row) * w * 4 + col * 4 + 0] +
            input[(h - row) * w * 4 + col * 4 + 1] +
            input[(h - row) * w * 4 + col * 4 + 2];
        ip0 =
            input[(h - 2 - row) * w * 4 + col * 4 + 0] +
            input[(h - 2 - row) * w * 4 + col * 4 + 1] +
            input[(h - 2 - row) * w * 4 + col * 4 + 2];
        if (i00 != i0m || i00 != ip0 || i00 != ipm || i00 != im0 || i00 != imm) {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else if (i00 == 0) {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        }
        col = 0;
        i00 =
            input[(h - 1 - row) * w * 4 + col * 4 + 0] +
            input[(h - 1 - row) * w * 4 + col * 4 + 1] +
            input[(h - 1 - row) * w * 4 + col * 4 + 2];
        i0p =
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 0] +
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 1] +
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 2];
        imp =
            input[(h - row) * w * 4 + (col + 1) * 4 + 0] +
            input[(h - row) * w * 4 + (col + 1) * 4 + 1] +
            input[(h - row) * w * 4 + (col + 1) * 4 + 2];
        ipp =
            input[(h - 2 - row) * w * 4 + (col + 1) * 4 + 0] +
            input[(h - 2 - row) * w * 4 + (col + 1) * 4 + 1] +
            input[(h - 2 - row) * w * 4 + (col + 1) * 4 + 2];
        im0 =
            input[(h - row) * w * 4 + col * 4 + 0] +
            input[(h - row) * w * 4 + col * 4 + 1] +
            input[(h - row) * w * 4 + col * 4 + 2];
        ip0 =
            input[(h - 2 - row) * w * 4 + col * 4 + 0] +
            input[(h - 2 - row) * w * 4 + col * 4 + 1] +
            input[(h - 2 - row) * w * 4 + col * 4 + 2];
        if (i00 != i0p || i00 != ip0 || i00 != ipp || i00 != im0 || i00 != imp) {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else if (i00 == 0) {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        }
        }
        //
        // top and bottom edges
        //
        for (col = 1; col < w - 1; ++col) {
        row = h - 1;
        i00 =
            input[(h - 1 - row) * w * 4 + col * 4 + 0] +
            input[(h - 1 - row) * w * 4 + col * 4 + 1] +
            input[(h - 1 - row) * w * 4 + col * 4 + 2];
        i0m =
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 0] +
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 1] +
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 2];
        i0p =
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 0] +
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 1] +
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 2];
        imm =
            input[(h - row) * w * 4 + (col - 1) * 4 + 0] +
            input[(h - row) * w * 4 + (col - 1) * 4 + 1] +
            input[(h - row) * w * 4 + (col - 1) * 4 + 2];
        im0 =
            input[(h - row) * w * 4 + col * 4 + 0] +
            input[(h - row) * w * 4 + col * 4 + 1] +
            input[(h - row) * w * 4 + col * 4 + 2];
        imp =
            input[(h - row) * w * 4 + (col + 1) * 4 + 0] +
            input[(h - row) * w * 4 + (col + 1) * 4 + 1] +
            input[(h - row) * w * 4 + (col + 1) * 4 + 2];
        if (i00 != i0m || i00 != i0p || i00 != imm || i00 != im0 || i00 != imp) {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else if (i00 == 0) {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        }
        row = 0;
        i00 =
            input[(h - 1 - row) * w * 4 + col * 4 + 0] +
            input[(h - 1 - row) * w * 4 + col * 4 + 1] +
            input[(h - 1 - row) * w * 4 + col * 4 + 2];
        i0m =
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 0] +
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 1] +
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 2];
        i0p =
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 0] +
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 1] +
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 2];
        ipm =
            input[(h - 2 - row) * w * 4 + (col - 1) * 4 + 0] +
            input[(h - 2 - row) * w * 4 + (col - 1) * 4 + 1] +
            input[(h - 2 - row) * w * 4 + (col - 1) * 4 + 2];
        ip0 =
            input[(h - 2 - row) * w * 4 + col * 4 + 0] +
            input[(h - 2 - row) * w * 4 + col * 4 + 1] +
            input[(h - 2 - row) * w * 4 + col * 4 + 2];
        ipp =
            input[(h - 2 - row) * w * 4 + (col + 1) * 4 + 0] +
            input[(h - 2 - row) * w * 4 + (col + 1) * 4 + 1] +
            input[(h - 2 - row) * w * 4 + (col + 1) * 4 + 2];
        if (i00 != i0m || i00 != i0p || i00 != ipm || i00 != ip0 || i00 != ipp) {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else if (i00 == 0) {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else {
            output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 1] = 255;
            output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        }
        }
        //
        // corners
        //
        row = 0;
        col = 0;
        i00 =
        input[(h - 1 - row) * w * 4 + col * 4 + 0] +
        input[(h - 1 - row) * w * 4 + col * 4 + 1] +
        input[(h - 1 - row) * w * 4 + col * 4 + 2];
        i0p =
        input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 0] +
        input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 1] +
        input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 2];
        ip0 =
        input[(h - 2 - row) * w * 4 + col * 4 + 0] +
        input[(h - 2 - row) * w * 4 + col * 4 + 1] +
        input[(h - 2 - row) * w * 4 + col * 4 + 2];
        ipp =
        input[(h - 2 - row) * w * 4 + (col + 1) * 4 + 0] +
        input[(h - 2 - row) * w * 4 + (col + 1) * 4 + 1] +
        input[(h - 2 - row) * w * 4 + (col + 1) * 4 + 2];
        if (i00 != i0p || i00 != ip0 || i00 != ipp) {
        output[(h - 1 - row) * w * 4 + col * 4 + 0] = 255;
        output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else if (i00 == 0) {
        output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 2] = 255;
        output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else {
        output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 1] = 255;
        output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        }
        row = 0;
        col = w - 1;
        i00 =
        input[(h - 1 - row) * w * 4 + col * 4 + 0] +
        input[(h - 1 - row) * w * 4 + col * 4 + 1] +
        input[(h - 1 - row) * w * 4 + col * 4 + 2];
        i0m =
        input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 0] +
        input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 1] +
        input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 2];
        ip0 =
        input[(h - 2 - row) * w * 4 + col * 4 + 0] +
        input[(h - 2 - row) * w * 4 + col * 4 + 1] +
        input[(h - 2 - row) * w * 4 + col * 4 + 2];
        ipm =
        input[(h - 2 - row) * w * 4 + (col - 1) * 4 + 0] +
        input[(h - 2 - row) * w * 4 + (col - 1) * 4 + 1] +
        input[(h - 2 - row) * w * 4 + (col - 1) * 4 + 2];
        if (i00 != i0m || i00 != ip0 || i00 != ipm) {
        output[(h - 1 - row) * w * 4 + col * 4 + 0] = 255;
        output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else if (i00 == 0) {
        output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 2] = 255;
        output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else {
        output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 1] = 255;
        output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        }
        row = h - 1;
        col = 0;
        i00 =
        input[(h - 1 - row) * w * 4 + col * 4 + 0] +
        input[(h - 1 - row) * w * 4 + col * 4 + 1] +
        input[(h - 1 - row) * w * 4 + col * 4 + 2];
        i0p =
        input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 0] +
        input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 1] +
        input[(h - 1 - row) * w * 4 + (col + 1) * 4 + 2];
        im0 =
        input[(h - row) * w * 4 + col * 4 + 0] +
        input[(h - row) * w * 4 + col * 4 + 1] +
        input[(h - row) * w * 4 + col * 4 + 2];
        imp =
        input[(h - row) * w * 4 + (col + 1) * 4 + 0] +
        input[(h - row) * w * 4 + (col + 1) * 4 + 1] +
        input[(h - row) * w * 4 + (col + 1) * 4 + 2];
        if (i00 != i0p || i00 != im0 || i00 != imp) {
        output[(h - 1 - row) * w * 4 + col * 4 + 0] = 255;
        output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else if (i00 == 0) {
        output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 2] = 255;
        output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else {
        output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 1] = 255;
        output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        }
        row = h - 1;
        col = w - 1;
        i00 =
        input[(h - 1 - row) * w * 4 + col * 4 + 0] +
        input[(h - 1 - row) * w * 4 + col * 4 + 1] +
        input[(h - 1 - row) * w * 4 + col * 4 + 2];
        i0m =
        input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 0] +
        input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 1] +
        input[(h - 1 - row) * w * 4 + (col - 1) * 4 + 2];
        im0 =
        input[(h - row) * w * 4 + col * 4 + 0] +
        input[(h - row) * w * 4 + col * 4 + 1] +
        input[(h - row) * w * 4 + col * 4 + 2];
        imm =
        input[(h - row) * w * 4 + (col - 1) * 4 + 0] +
        input[(h - row) * w * 4 + (col - 1) * 4 + 1] +
        input[(h - row) * w * 4 + (col - 1) * 4 + 2];
        if (i00 != i0m || i00 != im0 || i00 != imm) {
        output[(h - 1 - row) * w * 4 + col * 4 + 0] = 255;
        output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else if (i00 == 0) {
        output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 1] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 2] = 255;
        output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        } else {
        output[(h - 1 - row) * w * 4 + col * 4 + 0] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 1] = 255;
        output[(h - 1 - row) * w * 4 + col * 4 + 2] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + 3] = 255;
        }
    
        const imgData = new ImageData(output, w, h);
    
        return imgData;
    };
    
    const orientEdgesHelper = imageRGBA => {
        var h = imageRGBA.height;
        var w = imageRGBA.width;
        var input = imageRGBA.data;
        var output = new Uint8ClampedArray(h * w * 4);
        var row, col;
        var boundary = 0;
        var interior = 1;
        var exterior = 2;
        var alpha = 3;
        var northsouth = 0;
        var north = 128;
        var south = 64;
        var eastwest = 1;
        var east = 128;
        var west = 64;
        var startstop = 2;
        var start = 128;
        var stop = 64;
        //
        // orient body states
        //
        for (row = 1; row < h - 1; ++row) {
        for (col = 1; col < w - 1; ++col) {
            output[(h - 1 - row) * w * 4 + col * 4 + northsouth] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + eastwest] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + startstop] = 0;
            output[(h - 1 - row) * w * 4 + col * 4 + alpha] = 255;
            if (input[(h - 1 - row) * w * 4 + col * 4 + boundary] != 0) {
            if (
                input[(h - 1 - (row + 1)) * w * 4 + col * 4 + boundary] != 0 &&
                (input[(h - 1 - row) * w * 4 + (col + 1) * 4 + interior] != 0 ||
                input[(h - 1 - (row + 1)) * w * 4 + (col + 1) * 4 + interior] !=
                    0)
            )
                output[(h - 1 - row) * w * 4 + col * 4 + northsouth] |= north;
            if (
                input[(h - 1 - (row - 1)) * w * 4 + col * 4 + boundary] != 0 &&
                (input[(h - 1 - row) * w * 4 + (col - 1) * 4 + interior] != 0 ||
                input[(h - 1 - (row - 1)) * w * 4 + (col - 1) * 4 + interior] !=
                    0)
            )
                output[(h - 1 - row) * w * 4 + col * 4 + northsouth] |= south;
            if (
                input[(h - 1 - row) * w * 4 + (col + 1) * 4 + boundary] != 0 &&
                (input[(h - 1 - (row - 1)) * w * 4 + col * 4 + interior] != 0 ||
                input[(h - 1 - (row - 1)) * w * 4 + (col + 1) * 4 + interior] !=
                    0)
            )
                output[(h - 1 - row) * w * 4 + col * 4 + eastwest] |= east;
            if (
                input[(h - 1 - row) * w * 4 + (col - 1) * 4 + boundary] != 0 &&
                (input[(h - 1 - (row + 1)) * w * 4 + col * 4 + interior] != 0 ||
                input[(h - 1 - (row + 1)) * w * 4 + (col - 1) * 4 + interior] !=
                    0)
            )
                output[(h - 1 - row) * w * 4 + col * 4 + eastwest] |= west;
            }
        }
        }
        //
        // orient edge states
        //
        for (col = 1; col < w - 1; ++col) {
        row = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + northsouth] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + eastwest] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + startstop] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + alpha] = 255;
        if (input[(h - 1 - row) * w * 4 + col * 4 + boundary] != 0) {
            if (
            input[(h - 1 - (row + 1)) * w * 4 + col * 4 + boundary] != 0 &&
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + interior] != 0
            ) {
            output[(h - 1 - row) * w * 4 + col * 4 + northsouth] |= north;
            output[(h - 1 - row) * w * 4 + col * 4 + startstop] |= start;
            }
            if (input[(h - 1 - row) * w * 4 + (col - 1) * 4 + interior] != 0)
            output[(h - 1 - row) * w * 4 + col * 4 + startstop] |= stop;
        }
        row = h - 1;
        output[(h - 1 - row) * w * 4 + col * 4 + northsouth] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + eastwest] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + startstop] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + alpha] = 255;
        if (input[(h - 1 - row) * w * 4 + col * 4 + boundary] != 0) {
            if (input[(h - 1 - row) * w * 4 + (col + 1) * 4 + interior] != 0)
            output[(h - 1 - row) * w * 4 + col * 4 + startstop] |= stop;
            if (
            input[(h - 1 - (row - 1)) * w * 4 + col * 4 + boundary] != 0 &&
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + interior] != 0
            ) {
            output[(h - 1 - row) * w * 4 + col * 4 + northsouth] |= south;
            output[(h - 1 - row) * w * 4 + col * 4 + startstop] |= start;
            }
        }
        }
        for (row = 1; row < h - 1; ++row) {
        col = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + northsouth] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + eastwest] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + startstop] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + alpha] = 255;
        if (input[(h - 1 - row) * w * 4 + col * 4 + boundary] != 0) {
            if (
            input[(h - 1 - row) * w * 4 + (col + 1) * 4 + boundary] != 0 &&
            input[(h - 1 - (row - 1)) * w * 4 + col * 4 + interior] != 0
            ) {
            output[(h - 1 - row) * w * 4 + col * 4 + eastwest] |= east;
            output[(h - 1 - row) * w * 4 + col * 4 + startstop] |= start;
            }
            if (input[(h - 1 - (row + 1)) * w * 4 + col * 4 + interior] != 0)
            output[(h - 1 - row) * w * 4 + col * 4 + startstop] |= stop;
        }
        col = w - 1;
        output[(h - 1 - row) * w * 4 + col * 4 + northsouth] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + eastwest] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + startstop] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + alpha] = 255;
        if (input[(h - 1 - row) * w * 4 + col * 4 + boundary] != 0) {
            if (input[(h - 1 - (row - 1)) * w * 4 + col * 4 + interior] != 0)
            output[(h - 1 - row) * w * 4 + col * 4 + startstop] |= stop;
            if (
            input[(h - 1 - row) * w * 4 + (col - 1) * 4 + boundary] != 0 &&
            input[(h - 1 - (row + 1)) * w * 4 + col * 4 + interior] != 0
            ) {
            output[(h - 1 - row) * w * 4 + col * 4 + eastwest] |= west;
            output[(h - 1 - row) * w * 4 + col * 4 + startstop] |= start;
            }
        }
        }
        //
        // orient corner states (todo)
        //
        row = 0;
        col = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + northsouth] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + eastwest] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + startstop] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + alpha] = 255;
        row = h - 1;
        col = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + northsouth] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + eastwest] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + startstop] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + alpha] = 255;
        row = 0;
        col = w - 1;
        output[(h - 1 - row) * w * 4 + col * 4 + northsouth] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + eastwest] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + startstop] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + alpha] = 255;
        row = h - 1;
        col = w - 1;
        output[(h - 1 - row) * w * 4 + col * 4 + northsouth] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + eastwest] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + startstop] = 0;
        output[(h - 1 - row) * w * 4 + col * 4 + alpha] = 255;
    
        // var display = new Uint8ClampedArray(h*w*4)
        // var r,g,b,i
        // for (row = 0; row < h; ++row) {
        //   for (col = 0; col < w; ++col) {
        //     r = output[(h-1-row)*w*4+col*4+0]
        //     g = output[(h-1-row)*w*4+col*4+1]
        //     b = output[(h-1-row)*w*4+col*4+2]
        //     i = r+g+b
        //     if (i != 0) {
        //        display[(h-1-row)*w*4+col*4+0] = output[(h-1-row)*w*4+col*4+0]
        //        display[(h-1-row)*w*4+col*4+1] = output[(h-1-row)*w*4+col*4+1]
        //        display[(h-1-row)*w*4+col*4+2] = output[(h-1-row)*w*4+col*4+2]
        //        display[(h-1-row)*w*4+col*4+3] = output[(h-1-row)*w*4+col*4+3]
        //        }
        //     else {
        //        display[(h-1-row)*w*4+col*4+0] = 255
        //        display[(h-1-row)*w*4+col*4+1] = 255
        //        display[(h-1-row)*w*4+col*4+2] = 255
        //        display[(h-1-row)*w*4+col*4+3] = 255
        //        }
        //     }
        //  }
    
        const imgData = new ImageData(output, w, h);
    
        return imgData;
    };
    
    const vectorizeHelper = (imageRGBA, vectorFit = 1, sort = true) => {
        var h = imageRGBA.height;
        var w = imageRGBA.width;
        var input = imageRGBA.data;
        var northsouth = 0;
        var north = 128;
        var south = 64;
        var eastwest = 1;
        var east = 128;
        var west = 64;
        var startstop = 2;
        var start = 128;
        var stop = 64;
        var path = [];
        //
        // edge follower
        //
        function follow_edges(row, col) {
        if (
            input[(h - 1 - row) * w * 4 + col * 4 + northsouth] != 0 ||
            input[(h - 1 - row) * w * 4 + col * 4 + eastwest] != 0
        ) {
            path[path.length] = [[col, row]];
            while (1) {
            if (
                input[(h - 1 - row) * w * 4 + col * 4 + northsouth] & north
            ) {
                input[(h - 1 - row) * w * 4 + col * 4 + northsouth] =
                input[(h - 1 - row) * w * 4 + col * 4 + northsouth] &
                ~north;
                row += 1;
                path[path.length - 1][path[path.length - 1].length] = [
                col,
                row
                ];
            } else if (
                input[(h - 1 - row) * w * 4 + col * 4 + northsouth] & south
            ) {
                input[(h - 1 - row) * w * 4 + col * 4 + northsouth] =
                input[(h - 1 - row) * w * 4 + col * 4 + northsouth] &
                ~south;
                row -= 1;
                path[path.length - 1][path[path.length - 1].length] = [
                col,
                row
                ];
            } else if (
                input[(h - 1 - row) * w * 4 + col * 4 + eastwest] & east
            ) {
                input[(h - 1 - row) * w * 4 + col * 4 + eastwest] =
                input[(h - 1 - row) * w * 4 + col * 4 + eastwest] & ~east;
                col += 1;
                path[path.length - 1][path[path.length - 1].length] = [
                col,
                row
                ];
            } else if (
                input[(h - 1 - row) * w * 4 + col * 4 + eastwest] & west
            ) {
                input[(h - 1 - row) * w * 4 + col * 4 + eastwest] =
                input[(h - 1 - row) * w * 4 + col * 4 + eastwest] & ~west;
                col -= 1;
                path[path.length - 1][path[path.length - 1].length] = [
                col,
                row
                ];
            } else break;
            }
        }
        }
        //
        // follow boundary starts
        //
        for (var row = 1; row < h - 1; ++row) {
        col = 0;
        follow_edges(row, col);
        col = w - 1;
        follow_edges(row, col);
        }
        for (var col = 1; col < w - 1; ++col) {
        row = 0;
        follow_edges(row, col);
        row = h - 1;
        follow_edges(row, col);
        }
        //
        // follow interior paths
        //
        for (var row = 1; row < h - 1; ++row) {
        for (var col = 1; col < w - 1; ++col) {
            follow_edges(row, col);
        }
        }
        //
        // vectorize path
        //
        var error = vectorFit;
        var vecpath = [];
        for (var seg = 0; seg < path.length; ++seg) {
        var x0 = path[seg][0][0];
        var y0 = path[seg][0][1];
        vecpath[vecpath.length] = [[x0, y0]];
        var xsum = x0;
        var ysum = y0;
        var sum = 1;
        for (var pt = 1; pt < path[seg].length; ++pt) {
            var xold = x;
            var yold = y;
            var x = path[seg][pt][0];
            var y = path[seg][pt][1];
            if (sum == 1) {
            xsum += x;
            ysum += y;
            sum += 1;
            } else {
            var xmean = xsum / sum;
            var ymean = ysum / sum;
            var dx = xmean - x0;
            var dy = ymean - y0;
            var d = Math.sqrt(dx * dx + dy * dy);
            var nx = dy / d;
            var ny = -dx / d;
            var l = Math.abs(nx * (x - x0) + ny * (y - y0));
            if (l < error) {
                xsum += x;
                ysum += y;
                sum += 1;
            } else {
                vecpath[vecpath.length - 1][
                vecpath[vecpath.length - 1].length
                ] = [xold, yold];
                x0 = xold;
                y0 = yold;
                xsum = xold;
                ysum = yold;
                sum = 1;
            }
            }
            if (pt == path[seg].length - 1) {
            vecpath[vecpath.length - 1][
                vecpath[vecpath.length - 1].length
            ] = [x, y];
            }
        }
        }
        //
        // sort path
        //
        if (vecpath.length > 1 && sort == true) {
        var dmin = w * w + h * h;
        var segmin = null;
        for (var seg = 0; seg < vecpath.length; ++seg) {
            var x = vecpath[seg][0][0];
            var y = vecpath[seg][0][0];
            var d = x * x + y * y;
            if (d < dmin) {
            dmin = d;
            segmin = seg;
            }
        }
        if (segmin != null) {
            var sortpath = [vecpath[segmin]];
            vecpath.splice(segmin, 1);
        }
        while (vecpath.length > 0) {
            var dmin = w * w + h * h;
            var x0 =
            sortpath[sortpath.length - 1][
                sortpath[sortpath.length - 1].length - 1
            ][0];
            var y0 =
            sortpath[sortpath.length - 1][
                sortpath[sortpath.length - 1].length - 1
            ][1];
            segmin = null;
            for (var seg = 0; seg < vecpath.length; ++seg) {
            var x = vecpath[seg][0][0];
            var y = vecpath[seg][0][1];
            var d = (x - x0) * (x - x0) + (y - y0) * (y - y0);
            if (d < dmin) {
                dmin = d;
                segmin = seg;
            }
            }
            if (segmin != null) {
            sortpath[sortpath.length] = vecpath[segmin];
            vecpath.splice(segmin, 1);
            }
        }
        } else if (
        (vecpath.length > 1 && sort == false) ||
        vecpath.length == 1
        )
        sortpath = vecpath;
        else sortpath = [];
    
        return sortpath;
    };
    
    const test = () => console.log("import is working");