0

I am trying to use comicify for a project. You can go to an image on the internet, right click copy, and paste it on this demo page created by the author and it works fine.

Instead of having to paste an image, I am trying to click on a button, pick an image from a div and then convert it. The author kindly gave some directions, but when I try, it throws an error

comicify.php:30 Uncaught TypeError: t.process is not a function
    at comicify (comicify.html:30)
    at start (comicify.html:21)
    at HTMLButtonElement.onclick (comicify.html:6)

If this is just a syntax error, would be nice to get some hints on how to fix it.

Here is my sample code.

function start() {
    //alert("Baah");
    var myImg = $("img").prop("src");
    var myDistance = 50;
    console.log(myImg);
    var f = function(myImg) {
        //do something with returned image

    };
    var c = comicify(myImg, myDistance, f);
};

function comicify(img, dist, outf) {
    var t = this;
    t.srcimg = img;
    t.distance = dist;
    t.outfun = outf;
    t.container = $("<div>"); //$("#resultHolder");
    t.process();


}

comicify.prototype = {
    draw: function(container) {
        var t = this;
        t.container = container;
        var input = $('<input>').val(t.distance).change(function() {
            t.distance = this.value;
            if ('' != t.srcimg[0].src) {
                t.process();
            }
        });

        container.append($('<div>').text("Directions:").append(
            $('<ul>')
            .append($('<li>').text("Set the distance to distance (manitude between color vecotrs) that defines a single (new) color"))
            .append($('<li>').text("Paste an image to the page"))
            .append($('<li>').text("Wait -- you're processing an image in Javascript..."))
        ));
        container.append($('<div>').append($('<span>').text("Distance:").width("400px")).append(input))
        t.srcimg = $('<img>');
        t.srcimg.load(function() {
            t.process()
        });
        container.on('paste', function(evt) {
            return (t.handlePaste(evt));
        });
    },
    handlePaste: function(evt) {
        var t = this;
        var items = evt.originalEvent.clipboardData.items,
            paste;
        for (var i in items) {
            if ('file' == items[i].kind) {
                var fr = new FileReader();
                console.log("Going");
                fr.onload = function(revt) {
                    t.srcimg[0].src = revt.target.result;
                }
                fr.readAsDataURL(items[i].getAsFile());
            }
        }
    },

    process: function() {
        var t = this;
        var canvas = $('<canvas>');
        var w = canvas[0].width = t.srcimg[0].width;
        var h = canvas[0].height = t.srcimg[0].height;
        var prog = $('<span>').text("Processing...");
        t.container.append(prog);
        t.ctx = canvas[0].getContext('2d');
        t.ctx.drawImage(t.srcimg[0], 0, 0);
        t.image = t.ctx.getImageData(0, 0, w, h); //array [4*w*h] of colors RGBA
        t.ctx.clearRect(0, 0, w, h);
        t.mask = Array(w);
        var zz = Array();
        for (var i = 0; i < w * h; i++) {
            zz[i] = i;
        }
        for (var i = 0; i < w; i++) {
            t.mask[i] = Array(h);
            for (var j = 0; j < h; j++) {
                t.mask[i][j] = true;
                var n = Math.floor(w * h * Math.random());
                var z = zz[n];
                zz[n] = zz[i * j];
                zz[i * j] = z;
            }
        }

        var n = 0;
        var err = "";
        var step = (w * h) / 100;
        var progress = 0;
        var fn = function() {
            if (n < (w * h) && err == "") {
                var q = Math.floor(step);
                while (q > 0 && n < (w * h) && err == "") {
                    var x = zz[n];
                    var j = Math.floor(x / w);
                    var i = x % w;

                    if (t.mask[i][j]) {
                        var y = x * 4;
                        var avgct = 0;
                        t.avg = [t.image.data[y++], t.image.data[y++], t.image.data[y++], t.image.data[y++]];
                        try {
                            t.doPoint(i, j); // do all the points next to it too...
                            t.doPaint();
                        } catch (e) {
                            if (!e.message == "Maximum call stack size exceeded") {
                                err = e.message;
                                prog.text(e.message);
                            } else {
                                t.doPaint();
                            } // ignore call stack (we'll try 
                        }
                    }
                    n++;
                    q--;
                }
                progress++;
                if (err == "") {
                    prog.text("Processing " + String(progress) + "%");
                    window.setTimeout(fn, 0.0001);
                }
            } else {
                if (err == "") {
                    prog.remove();
                }
                t.ctx.putImageData(t.image, 0, 0);
                var outImg = $('<img>');
                outImg[0].src = canvas[0].toDataURL();
                t.container.append(outImg);
            }
        };
        window.setTimeout(fn, 4);
    },
    doPaint: function() {
        var t = this;
        var w = t.srcimg[0].width;
        var h = t.srcimg[0].height;
        var avgct = 1;
        for (var i = 0; i < w; i++) {
            for (var j = 0; j < h; j++) {
                var x = 4 * (i + (j * w));
                if (null == t.mask[i][j]) {
                    for (var k = 0; k < 4; k++) {
                        t.avg[k] = ((t.avg[k] * avgct) + t.image.data[x + k]) / (avgct + 1);
                    }
                    avgct++;
                }
            }
        }
        for (var i = 0; i < w; i++) {
            for (var j = 0; j < h; j++) {
                if (null == t.mask[i][j]) {
                    var n = 4 * (i + (j * w));
                    for (var k = 0; k < 4; k++) {
                        t.image.data[n + k] = Math.floor(t.avg[k]);
                    }
                    t.mask[i][j] = 0;
                }
            }
        }
    },

    doPoint: function(i, j) {
        var t = this;
        var w = t.srcimg[0].width;
        var h = t.srcimg[0].height;
        var x = 4 * (i + (j * w));
        var p = [t.image.data[x++], t.image.data[x++], t.image.data[x++], t.image.data[x++]]
        if (t.distance > distance(t.avg, p)) {
            t.mask[i][j] = null;
            if (i + 1 < w && t.mask[i + 1][j]) {
                t.doPoint(i + 1, j)
            }
            if (i - 1 > 0 && t.mask[i - 1][j]) {
                t.doPoint(i - 1, j)
            }
            if (j + 1 < h && t.mask[i][j + 1]) {
                t.doPoint(i, j + 1)
            }
            if (j - 1 > 0 && t.mask[i][j - 1]) {
                t.doPoint(i, j - 1)
            }
        }
        return;
    },
    avgPt: function(i, j, ct) {
        var t = this;
        var w = t.srcimg[0].width;
        var h = t.srcimg[0].height;
        if (i > 0 && j > 0 && i < w && j < h) {
            var x = 4 * (i + (j * w));
            var p = [t.image.data[x++], t.image.data[x++], t.image.data[x++], t.image.data[x++]]
            for (var k = 0; k < 4; k++) {
                t.avg[k] = ((t.avg[k] * ct) + p[k]) / (ct + 1);
            }
        }
    },
    avgct: 0,
    ctx: 0,
    mask: 0,
    image: 0,
    avg: 0,
    srcimg: 0,
    cnv: 0,
    distance: 35,
    container: 0 // container
} // proto

function distance(a, b) {
    var o = 0;
    for (i = 0; i < 4; i++) {
        o += (a[i] - b[i]) * (a[i] - b[i]);
    }
    return (Math.sqrt(o));
}
<html>
  <body>
    <img src="http://www.famouscastles.net/images/famouscastles/hdr-lichtenstein-castle-small.jpg" />
    <div id="resultHolder"></div>
    <button onclick="start()">Comicify me</button>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script type="text/javascript"></script>
  </body>
</html>
JSmith
  • 4,519
  • 4
  • 29
  • 45
aVC
  • 2,254
  • 2
  • 24
  • 46

2 Answers2

1

It is because you are using comificy.prototype to define the methods, that means process is an instance method.

To solve it just put a new word: var c = new comicify(myImg, myDistance, f);

See: JavaScript: Class.method vs. Class.prototype.method

function start() {
    //alert("Baah");
    var myImg = $("img").prop("src");
    var myDistance = 50;
    console.log(myImg);
    var f = function(myImg) {
        //do something with returned image

    };
    var c = new comicify(myImg, myDistance, f);
};

function comicify(img, dist, outf) {
    var t = this;
    t.srcimg = img;
    t.distance = dist;
    t.outfun = outf;
    t.container = $("<div>"); //$("#resultHolder");
    t.process();
}

comicify.prototype = {
    draw: function(container) {
        var t = this;
        t.container = container;
        var input = $('<input>').val(t.distance).change(function() {
            t.distance = this.value;
            if ('' != t.srcimg[0].src) {
                t.process();
            }
        });

        container.append($('<div>').text("Directions:").append(
            $('<ul>')
            .append($('<li>').text("Set the distance to distance (manitude between color vecotrs) that defines a single (new) color"))
            .append($('<li>').text("Paste an image to the page"))
            .append($('<li>').text("Wait -- you're processing an image in Javascript..."))
        ));
        container.append($('<div>').append($('<span>').text("Distance:").width("400px")).append(input))
        t.srcimg = $('<img>');
        t.srcimg.load(function() {
            t.process()
        });
        container.on('paste', function(evt) {
            return (t.handlePaste(evt));
        });
    },
    handlePaste: function(evt) {
        var t = this;
        var items = evt.originalEvent.clipboardData.items,
            paste;
        for (var i in items) {
            if ('file' == items[i].kind) {
                var fr = new FileReader();
                console.log("Going");
                fr.onload = function(revt) {
                    t.srcimg[0].src = revt.target.result;
                }
                fr.readAsDataURL(items[i].getAsFile());
            }
        }
    },

    process: function() {
        var t = this;
        var canvas = $('<canvas>');
        var w = canvas[0].width = t.srcimg[0].width;
        var h = canvas[0].height = t.srcimg[0].height;
        var prog = $('<span>').text("Processing...");
        t.container.append(prog);
        t.ctx = canvas[0].getContext('2d');
        t.ctx.drawImage(t.srcimg[0], 0, 0);
        t.image = t.ctx.getImageData(0, 0, w, h); //array [4*w*h] of colors RGBA
        t.ctx.clearRect(0, 0, w, h);
        t.mask = Array(w);
        var zz = Array();
        for (var i = 0; i < w * h; i++) {
            zz[i] = i;
        }
        for (var i = 0; i < w; i++) {
            t.mask[i] = Array(h);
            for (var j = 0; j < h; j++) {
                t.mask[i][j] = true;
                var n = Math.floor(w * h * Math.random());
                var z = zz[n];
                zz[n] = zz[i * j];
                zz[i * j] = z;
            }
        }

        var n = 0;
        var err = "";
        var step = (w * h) / 100;
        var progress = 0;
        var fn = function() {
            if (n < (w * h) && err == "") {
                var q = Math.floor(step);
                while (q > 0 && n < (w * h) && err == "") {
                    var x = zz[n];
                    var j = Math.floor(x / w);
                    var i = x % w;

                    if (t.mask[i][j]) {
                        var y = x * 4;
                        var avgct = 0;
                        t.avg = [t.image.data[y++], t.image.data[y++], t.image.data[y++], t.image.data[y++]];
                        try {
                            t.doPoint(i, j); // do all the points next to it too...
                            t.doPaint();
                        } catch (e) {
                            if (!e.message == "Maximum call stack size exceeded") {
                                err = e.message;
                                prog.text(e.message);
                            } else {
                                t.doPaint();
                            } // ignore call stack (we'll try 
                        }
                    }
                    n++;
                    q--;
                }
                progress++;
                if (err == "") {
                    prog.text("Processing " + String(progress) + "%");
                    window.setTimeout(fn, 0.0001);
                }
            } else {
                if (err == "") {
                    prog.remove();
                }
                t.ctx.putImageData(t.image, 0, 0);
                var outImg = $('<img>');
                outImg[0].src = canvas[0].toDataURL();
                t.container.append(outImg);
            }
        };
        window.setTimeout(fn, 4);
    },
    doPaint: function() {
        var t = this;
        var w = t.srcimg[0].width;
        var h = t.srcimg[0].height;
        var avgct = 1;
        for (var i = 0; i < w; i++) {
            for (var j = 0; j < h; j++) {
                var x = 4 * (i + (j * w));
                if (null == t.mask[i][j]) {
                    for (var k = 0; k < 4; k++) {
                        t.avg[k] = ((t.avg[k] * avgct) + t.image.data[x + k]) / (avgct + 1);
                    }
                    avgct++;
                }
            }
        }
        for (var i = 0; i < w; i++) {
            for (var j = 0; j < h; j++) {
                if (null == t.mask[i][j]) {
                    var n = 4 * (i + (j * w));
                    for (var k = 0; k < 4; k++) {
                        t.image.data[n + k] = Math.floor(t.avg[k]);
                    }
                    t.mask[i][j] = 0;
                }
            }
        }
    },

    doPoint: function(i, j) {
        var t = this;
        var w = t.srcimg[0].width;
        var h = t.srcimg[0].height;
        var x = 4 * (i + (j * w));
        var p = [t.image.data[x++], t.image.data[x++], t.image.data[x++], t.image.data[x++]]
        if (t.distance > distance(t.avg, p)) {
            t.mask[i][j] = null;
            if (i + 1 < w && t.mask[i + 1][j]) {
                t.doPoint(i + 1, j)
            }
            if (i - 1 > 0 && t.mask[i - 1][j]) {
                t.doPoint(i - 1, j)
            }
            if (j + 1 < h && t.mask[i][j + 1]) {
                t.doPoint(i, j + 1)
            }
            if (j - 1 > 0 && t.mask[i][j - 1]) {
                t.doPoint(i, j - 1)
            }
        }
        return;
    },
    avgPt: function(i, j, ct) {
        var t = this;
        var w = t.srcimg[0].width;
        var h = t.srcimg[0].height;
        if (i > 0 && j > 0 && i < w && j < h) {
            var x = 4 * (i + (j * w));
            var p = [t.image.data[x++], t.image.data[x++], t.image.data[x++], t.image.data[x++]]
            for (var k = 0; k < 4; k++) {
                t.avg[k] = ((t.avg[k] * ct) + p[k]) / (ct + 1);
            }
        }
    },
    avgct: 0,
    ctx: 0,
    mask: 0,
    image: 0,
    avg: 0,
    srcimg: 0,
    cnv: 0,
    distance: 35,
    container: 0 // container
} // proto

function distance(a, b) {
    var o = 0;
    for (i = 0; i < 4; i++) {
        o += (a[i] - b[i]) * (a[i] - b[i]);
    }
    return (Math.sqrt(o));
}
<html>
  <body>
    <img src="http://www.famouscastles.net/images/famouscastles/hdr-lichtenstein-castle-small.jpg" />
    <div id="resultHolder"></div>
    <button onclick="start()">Comicify me</button>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  </body>
</html>
lmarqs
  • 1,469
  • 13
  • 16
0

The above answer was not working for me - I had Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D' in the console.

I have made a very few changes and it worked for me.

Note: It will not work in plain HTML file, it will give you the CORS error. Create a simple nodejs or php app and try to run the code as a project

Thanks @imarqs @aVC

<script>
function start() {
    //alert("Baah");
    // var myImg = $("#cart_let").prop("src");
    var myImg = new Image();
    myImg.src = "assets/img/mti.png";
    // myImg.crossOrigin = "Anonymous";

    var myDistance = 100;
    console.log(myImg);
    var f = function(myImg) {
        //do something with returned image
        console.log("returned "+myImg)
    };
    console.log("start")
    var c = new comicify(myImg, myDistance, f);
};

function comicify(img, dist, outf) {
    var t = this;
    t.srcimg = img;
    t.distance = dist;
    t.outfun = outf;
    t.container = $("#resultHolder");
    console.log("before pro")
    t.process();
}

comicify.prototype = {
    draw: function(container) {
        var t = this;
        t.container = container;
        var input = $('<input>').val(t.distance).change(function() {
            t.distance = this.value;
            if ('' != t.srcimg.src) {
                t.process();
            }
        });

        container.append($('<div>').text("Directions:").append(
            $('<ul>')
                .append($('<li>').text("Set the distance to distance (manitude between color vecotrs) that defines a single (new) color"))
                .append($('<li>').text("Paste an image to the page"))
                .append($('<li>').text("Wait -- you're processing an image in Javascript..."))
        ));
        container.append($('<div>').append($('<span>').text("Distance:").width("400px")).append(input))
        t.srcimg = $('<img>');
        t.srcimg.load(function() {
            t.process()
        });
        container.on('paste', function(evt) {
            return (t.handlePaste(evt));
        });
    },
    handlePaste: function(evt) {
        var t = this;
        var items = evt.originalEvent.clipboardData.items,
            paste;
        for (var i in items) {
            if ('file' == items[i].kind) {
                var fr = new FileReader();
                console.log("Going");
                fr.onload = function(revt) {
                    t.srcimg.src = revt.target.result;
                }
                fr.readAsDataURL(items[i].getAsFile());
            }
        }
    },

    process: function() {
        console.log("inside pro")
        var t = this;
        var canvas = $('<canvas>');
        var w = canvas[0].width = t.srcimg.width;
        var h = canvas[0].height = t.srcimg.height;
        console.log("pro read prop")
        var prog = $('<span>').text("Processing...");
        t.container.append(prog);
        console.log("show pro")
        t.ctx = canvas[0].getContext('2d');
        console.log("pro read 2")
        t.ctx.drawImage(t.srcimg, 0, 0);
        console.log("pro read 3")
        t.image = t.ctx.getImageData(0, 0, w, h); //array [4*w*h] of colors RGBA
        console.log("pro read 4")
        t.ctx.clearRect(0, 0, w, h);
        console.log("pro read n")
        t.mask = Array(w);
        var zz = Array();
        for (var i = 0; i < w * h; i++) {
            zz[i] = i;
        }
        console.log('procee')
        for (var i = 0; i < w; i++) {
            t.mask[i] = Array(h);
            for (var j = 0; j < h; j++) {
                t.mask[i][j] = true;
                var n = Math.floor(w * h * Math.random());
                var z = zz[n];
                zz[n] = zz[i * j];
                zz[i * j] = z;
            }
        }
        console.log('procee2')

        var n = 0;
        var err = "";
        var step = (w * h) / 100;
        var progress = 0;
        var fn = function() {
            if (n < (w * h) && err == "") {
                var q = Math.floor(step);
                while (q > 0 && n < (w * h) && err == "") {
                    var x = zz[n];
                    var j = Math.floor(x / w);
                    var i = x % w;

                    if (t.mask[i][j]) {
                        var y = x * 4;
                        var avgct = 0;
                        t.avg = [t.image.data[y++], t.image.data[y++], t.image.data[y++], t.image.data[y++]];
                        try {
                            t.doPoint(i, j); // do all the points next to it too...
                            t.doPaint();
                        } catch (e) {
                            if (!e.message == "Maximum call stack size exceeded") {
                                err = e.message;
                                console.log("here")
                                prog.text(e.message);
                            } else {
                                t.doPaint();
                            } // ignore call stack (we'll try
                        }
                    }
                    n++;
                    q--;
                }
                progress++;
                if (err == "") {
                    prog.text("Processing " + String(progress) + "%");
                    window.setTimeout(fn, 0.0001);
                }
            } else {
                if (err == "") {
                    prog.remove();
                }
                t.ctx.putImageData(t.image, 0, 0);
                var outImg = $('<img>');
                outImg[0].src = canvas[0].toDataURL();
                t.container.append(outImg);
            }
        };
        window.setTimeout(fn, 4);
    },
    doPaint: function() {
        var t = this;
        var w = t.srcimg.width;
        var h = t.srcimg.height;
        var avgct = 1;
        for (var i = 0; i < w; i++) {
            for (var j = 0; j < h; j++) {
                var x = 4 * (i + (j * w));
                if (null == t.mask[i][j]) {
                    for (var k = 0; k < 4; k++) {
                        t.avg[k] = ((t.avg[k] * avgct) + t.image.data[x + k]) / (avgct + 1);
                    }
                    avgct++;
                }
            }
        }
        for (var i = 0; i < w; i++) {
            for (var j = 0; j < h; j++) {
                if (null == t.mask[i][j]) {
                    var n = 4 * (i + (j * w));
                    for (var k = 0; k < 4; k++) {
                        t.image.data[n + k] = Math.floor(t.avg[k]);
                    }
                    t.mask[i][j] = 0;
                }
            }
        }
    },

    doPoint: function(i, j) {
        var t = this;
        var w = t.srcimg.width;
        var h = t.srcimg.height;
        var x = 4 * (i + (j * w));
        var p = [t.image.data[x++], t.image.data[x++], t.image.data[x++], t.image.data[x++]]
        if (t.distance > distance(t.avg, p)) {
            t.mask[i][j] = null;
            if (i + 1 < w && t.mask[i + 1][j]) {
                t.doPoint(i + 1, j)
            }
            if (i - 1 > 0 && t.mask[i - 1][j]) {
                t.doPoint(i - 1, j)
            }
            if (j + 1 < h && t.mask[i][j + 1]) {
                t.doPoint(i, j + 1)
            }
            if (j - 1 > 0 && t.mask[i][j - 1]) {
                t.doPoint(i, j - 1)
            }
        }
        return;
    },
    avgPt: function(i, j, ct) {
        var t = this;
        var w = t.srcimg.width;
        var h = t.srcimg.height;
        if (i > 0 && j > 0 && i < w && j < h) {
            var x = 4 * (i + (j * w));
            var p = [t.image.data[x++], t.image.data[x++], t.image.data[x++], t.image.data[x++]]
            for (var k = 0; k < 4; k++) {
                t.avg[k] = ((t.avg[k] * ct) + p[k]) / (ct + 1);
            }
        }
    },
    avgct: 0,
    ctx: 0,
    mask: 0,
    image: 0,
    avg: 0,
    srcimg: 0,
    cnv: 0,
    distance: 35,
    container: 0 // container
} // proto

function distance(a, b) {
    var o = 0;
    for (i = 0; i < 4; i++) {
        o += (a[i] - b[i]) * (a[i] - b[i]);
    }
    return (Math.sqrt(o));
}
Khan Sharukh
  • 1,151
  • 12
  • 21