首页 > 解决方案 > 通过javascript图像到卡通

问题描述

我正在尝试将comicify用于一个项目。你可以去网上找一张图片,右键复制,然后粘贴到作者创建的这个演示页面上,效果很好。

我无需粘贴图像,而是尝试单击按钮,从 div 中选择图像,然后进行转换。作者好心给了一些指导,但是当我尝试时,它会抛出错误

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)

如果这只是一个语法错误,最好能得到一些关于如何修复它的提示。

这是我的示例代码。

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>

标签: javascriptjquery

解决方案


这是因为您正在使用comificy.prototype定义方法,这意味着process它是一个实例方法。

要解决它,只需输入new一句话:var c = new comicify(myImg, myDistance, f);

请参阅: JavaScript:Class.method 与 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>


推荐阅读