HTML5 画布删除垂直/水平线值的像素



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

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

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

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

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

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

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

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

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>

对于算法,您需要执行类似操作,但将雕刻路径用作前半部分的掩码:

  • 以目标大小绘制图像(完整(
  • 使用
  • 复合模式去除不规则的外延,使用闭合路径剪掉后半部分
  • 使用复合模式目标
  • 绘制图像减去接缝偏移量 - 这将在前半部分后面绘制,形成完整的图像

对每个接缝重复此操作。

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

https://github.com/meltingice/CamanJS

这可能可以在 Web worker 中完成,无论如何都会进行像素迭代的 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>

最新更新