【问题标题】:html5 canvas remove vertical/horizontal line worth of pixelhtml5画布删除垂直/水平线的像素
【发布时间】:2017-07-22 20:15:34
【问题描述】:

我正在为相框实现接缝雕刻算法。

https://en.wikipedia.org/wiki/Seam_carving

我知道这个算法不是很好,因为它从图片中切出一条直线,但好消息是我这样做是为了“相框”,所以你可以想象它会很好地工作。

因此,如果图像的宽度为 100 像素,我想删除第 50 像素处的垂直线。那么它将是 99 像素的宽度。

这是伪代码,我删除了我之前的代码尝试

  1. 将图像加载到画布。
  2. 删除宽度为 1 像素且高度等于加载的图像的垂直线。如果该图像的宽度等于 100,则现在将是 99。
  3. 获取新处理图像的Base64编码字符串。

我想要做的是删除一条宽度为 1 像素且高度等于图像的垂直线,然后将图像绘制到画布并获取 base64 编码的图像。

【问题讨论】:

  • 请将代码中的注释语句作为格式正确的问题添加到上面的正文中。
  • 我要做的是删除一条宽度为1像素且高度等于图像的垂直线,然后将图像绘制到画布并获取base64编码的图像。
  • 请重新阅读我编辑的评论(sry)。

标签: javascript html canvas


【解决方案1】:

您可以使用原始图像作为源,然后将画布设置为最终大小,例如:

var img=new Image; img.onload=carve; img.src = "//i.stack.imgur.com/OqB5r.jpg";

function carve() {
  var ctx = c.getContext("2d");
  var cut = 50;        // we remove [50, 50 + carveWidth>, in this case
  var carveWidth = 16; // exaggerated to show noticeable change
  
  // set final size of canvas:
  c.width = this.width - carveWidth;
  c.height = this.height;
  
  // draw in first half using clip arguments of drawImage()
  ctx.drawImage(this, 0, 0, cut, this.height, 0, 0, cut, this.height);

  // draw in second half, notice we skip cut+carve for source, but not for dest.
  ctx.drawImage(this, cut + carveWidth, 0, this.width, this.height,
                      cut             , 0, this.width, this.height);
                      
  // save out canvas
}
canvas {border:1px solid red} /* to show actual canvas size */
<canvas id=c></canvas>

对于算法,您需要做一些类似的事情,但要使用雕刻路径作为前半部分的蒙版:

  • 以目标尺寸绘制图像(完整)
  • 使用复合模式去除不规则的外观,使用封闭路径剪裁下半部分
  • 使用复合模式destination-over
  • 在图像中绘制减去接缝偏移 - 这将在前半部分后面绘制,从而形成完整的图像

对每个接缝重复。

【讨论】:

  • 我真的很想明白你想说什么,但我无法做到。花了一个多小时。没有。
  • 很抱歉。有什么具体你不明白的地方吗?
【解决方案2】:

这是答案。注意我使用的是 Caman,因此在加载图像时我不会丢失质量,并且由于 caman 非阻塞线程模型,浏览器的线程不会被阻塞。

https://github.com/meltingice/CamanJS

这可能可以在 webworker 中完成,for 循环无论如何都会进行像素迭代。

如果有人有更有效的方法来做到这一点,请提出建议,我将来可能会这样做,但我现在没有时间。

    var canvas = document.createElement("canvas");

    canvas.height = 200;
    canvas.width = 200;
    Caman(canvas, "download.png", function () {



    var ctx = canvas.getContext("2d");

    var oldid = ctx.getImageData(0, 0, 360, 360);

    var newCanvas = document.createElement("canvas");
    var newContext2d = newCanvas.getContext("2d");


    newCanvas.width = 360;
    newCanvas.height = 340;

    var vnewid = newContext2d.createImageData(360, 360);


    var oldArray = Array.from(oldid.data);

    console.log(oldArray);

    var arrayToInsert = [];

    for (var y = 0; y < 360; ++y) {

        for (var x = 0; x < 360; ++x) {
            if (y > 90 && y < 110) { // this is how we remove a horizontal line worth of 20 pixels in width.

            } else {
                var index = (y * 360 + x) * 4; // index of the current pixel
                arrayToInsert.push(oldArray[index]);
                arrayToInsert.push(oldArray[index + 1]);
                arrayToInsert.push(oldArray[index + 2]);
                arrayToInsert.push(oldArray[index + 3]);
            }
        }
    }

    vnewid.data.set(arrayToInsert);
    newContext2d.putImageData(vnewid, 0, 0, 0, 0, 360, 340);

    var newC = newCanvas.toDataURL();
    console.log(newC); 

    // take this console.log base64 and put it here.

   // https://codebeautify.org/base64-to-image-converter
});

这里是html

   <html>
        <head>
            <meta charset="utf-8" />
            <title></title>

            <script type="text/javascript" src="camanjs.js"></script>
        </head>
        <body>
            <img width="200" height="200" id="f1img" src="download.png" />
            <div >
                <canvas id="myCanvas"></canvas>

            </div>

            <script src="index.js"></script>
        </body>

    </html>

【讨论】:

    猜你喜欢
    • 2016-07-13
    • 2017-07-16
    • 2019-05-26
    • 2014-05-04
    • 1970-01-01
    • 2017-08-26
    • 2015-07-27
    • 1970-01-01
    • 2013-10-06
    相关资源
    最近更新 更多