Source code
/* lisa.js */

var img;
var triangles = [];
var num_splits = 1;
var max_splits = 14;
var is_updating;

function preload() {
    img = loadImage("lisa.png");
}

function setup() {
    var canvas = createCanvas(500,500);
    canvas.parent("lisa-holder");

    img.loadPixels();

    noStroke();
    noLoop();
}

function draw() {
    background(250, 250, 255);
    var t1 = new Triangle(0,0, width,0, width,height);
    var t2 = new Triangle(0,0, 0,height, width,height);

    t1.set_avg_color(img);
    t2.set_avg_color(img);

    triangles.push(t1);
    triangles.push(t2);

    recursive_split(t1, num_splits);
    recursive_split(t2, num_splits);

    /* prevent the sketch from updating while we are still processing the triangles */
    is_updating = true;
    for(let i = 0; i < triangles.length; i++) {
        var t = triangles[i];
        t.show();
    }
    is_updating = false;
}

function mouseMoved() {
    /* prevent the sketch from updating while we are still processing the triangles */
    if (is_updating == false) {
        if (mouseX < img.width) {
            num_splits = floor((mouseX / img.width) * max_splits)
        } else { num_splits = max_splits }
        triangles = []
        redraw()
    }
}

/*  Recursively split each triangle into 2, n amount of times */
function recursive_split(triangle, n) {
    if(n > max_splits) {
        return;
    }
    n--;
    
    /* Base case */
    if(n <= 0) {
        return;
    }

    /* Create vectors from points A,B,C of given triangle */
    var a = new Point(triangle.x1, triangle.y1);
    var b = new Point(triangle.x2, triangle.y2);
    var c = new Point(triangle.x3, triangle.y3);
    var ab = createVector(a.x - b.x, a.y - b.y);
    var ac = createVector(a.x - c.x, a.y - c.y);
    var bc = createVector(b.x - c.x, b.y - c.y);


    /* Find hypotenuse of given triangle */
    if(approx_equal(PI / 2, ab.angleBetween(ac), 20)) {
        /* BC is hypotenuse */
        var halfway = new Point(~~((b.x + c.x) / 2), ~~((b.y + c.y) / 2));
        var split1 = new Triangle(a.x,a.y, b.x,b.y, halfway.x,halfway.y);
        var split2 = new Triangle(a.x,a.y, c.x,c.y, halfway.x,halfway.y);

        if(n == 1) {
            split1.set_avg_color(img);
            split2.set_avg_color(img);
            triangles.push(split1);
            triangles.push(split2);
        }

        recursive_split(split1, n);
        recursive_split(split2, n);

    }    
    else if(approx_equal(PI / 2, ab.angleBetween(bc), 20)) {
        /* AC is hypotenuse */
        var halfway = new Point(~~((a.x + c.x) / 2), ~~((a.y + c.y) / 2));
        var split1 = new Triangle(a.x,a.y, b.x,b.y, halfway.x,halfway.y);
        var split2 = new Triangle(b.x,b.y, c.x,c.y, halfway.x,halfway.y);

        if(n == 1) {
            split1.set_avg_color(img);
            split2.set_avg_color(img);
            triangles.push(split1);
            triangles.push(split2);

        }

        recursive_split(split1, n);
        recursive_split(split2, n);
    }
    else if(approx_equal(PI / 2, ac.angleBetween(bc), 20)) {
        /* AB is hypotenuse */
        var halfway = new Point(~~((a.x + b.x) / 2), ~~((a.y + b.y) / 2));
        var split1 = new Triangle(a.x,a.y, c.x,c.y, halfway.x,halfway.y);
        var split2 = new Triangle(b.x,b.y, c.x,c.y, halfway.x,halfway.y);

        if(n == 1) {
            split1.set_avg_color(img);
            split2.set_avg_color(img);
            triangles.push(split1);
            triangles.push(split2);
        }

        recursive_split(split1, n);
        recursive_split(split2, n);
    }
    else {
        alert("Cannot split further");
        return;
    }
}

/*  Returns true if actual value is within a percentage tolerence of
    a desired value
*/
function approx_equal(desired, actual, tolerance_percent) {
    var diff = Math.abs(desired - actual);
    var tolerance = tolerance_percent / 100 * desired;
    return diff < tolerance;
}

class Point {
    constructor(x,y) {
        this.x = Math.floor(x);
        this.y = Math.floor(y);
    }
}

class Triangle {
    constructor(x1,y1,x2,y2,x3,y3) {
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
        this.x3 = x3;
        this.y3 = y3;

        this.r = 0;
        this.g = 0;
        this.b = 0;
    }

    /*  Set the color of the triangle to the average of the pixels defined 
        by the triangle 
    */
    set_avg_color(image) {
        /* loop through square of pixels defined by points of triangle */   
        var min_x = Math.min(this.x1, this.x2, this.x3);
        var min_y = Math.min(this.y1, this.y2, this.y3);
        var max_x = Math.max(this.x1, this.x2, this.x3);
        var max_y = Math.max(this.y1, this.y2, this.y3);

        var r_tot = 0;
        var g_tot = 0;
        var b_tot = 0;
        var total = 0;

        for(let i = min_x; i < max_x; i++) {
            for(let j = min_y; j < max_y; j++) {
                /* if coordinate is within the triangle */
                if(this.is_inside(i,j)) {
                    var index = (i + j * img.width) * 4;

                    r_tot += image.pixels[index];
                    g_tot += image.pixels[index + 1];
                    b_tot += image.pixels[index + 2];
                    total++;
                }
            }
        }

        var r_avg = r_tot / total;
        var g_avg = g_tot / total;
        var b_avg = b_tot / total;

        this.r = r_avg;
        this.g = g_avg;
        this.b = b_avg;
    }

    show() {
        fill(this.r,this.g,this.b);
        stroke(this.r, this.g, this.b);
        triangle(this.x1,this.y1,this.x2,this.y2,this.x3,this.y3);
    }

    /*  Check whether (x,y) lies inside the triangle */
    is_inside(x,y) {
        /* Calculate area of current triangle ABC */
        var A = area(this.x1,this.y1,this.x2,this.y2,this.x3,this.y3);

        /* Calculate area of (x,y)BC */
        var A1 = area(x,y,this.x2,this.y2,this.x3,this.y3);

        /* Calculate area of A(x,y)C */
        var A2 = area(this.x1,this.y1,x,y,this.x3,this.y3);

        /* Calculate area of AB(x,y) */
        var A3 = area(this.x1,this.y1,this.x2,this.y2,x,y);

        /* Check if sum of A1, A2, and A3 are the same as A */
        return (A == A1 + A2 + A3);
    }
};

/*  Returns the area of triangle */
function area(x1, y1, x2, y2, x3, y3) {
    var side_ab = Math.sqrt(Math.pow(x1-x2,2) + Math.pow(y1-y2,2));
    var side_ac = Math.sqrt(Math.pow(x1-x3,2) + Math.pow(y1-y3,2));
    var side_bc = Math.sqrt(Math.pow(x2-x3,2) + Math.pow(y2-y3,2));
    var s = (side_ab + side_ac + side_bc) / 2;
    return Math.sqrt(s*((s-side_ab)*(s-side_ac)*(s-side_bc)));
}



/* Prevents up and down arrow from moving page up and down */
window.addEventListener("keydown", function(e) {
    // space and arrow keys
    if([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
        e.preventDefault();
    }
}, false);