我正在制作一个用于图像处理的Node.js
应用程序。Jimp
我想根据矩形本身的参数(x、y、宽度和高度)在矩形上制作虚线边框。我希望边框尽可能接近 Web 浏览器的虚线边框。我的意思是它向上、向右、向下,最后向左。我还需要一个offset
变量来让它稍微向外一点,但我想我做到了(如果你认为有办法改善偏移,请告诉我)。问题是我使用scanQuiet
fromJimp
并且我无法后退(即 -width 或 -height)。对于底部的虚线,我需要向后移动宽度(-width
),对于左侧 - 向后移动高度(-height
)。我怎么做?我可以做吗scanQuiet
倒退?有没有更好的方法来做虚线边框?
注意:我有一个名为的函数blendColors
,我将在下面的代码中包含它。
代码:
function dashedBorder(
image,
{ lineDash, lineWidth, color },
{ x, y, width, height }
) {
let drawing = true,
passed = 0,
offset = lineWidth - 1;
color = Jimp.intToRGBA(color);
// Top border
image.scanQuiet(x - offset, y - offset, width, 1, (x, y) => {
if (drawing) {
const pixelColor = Jimp.intToRGBA(image.getPixelColor(x, y));
const newColor = blendColors(pixelColor, color);
for (let i = 0; i < lineWidth; i++) {
image.setPixelColor(
Jimp.rgbaToInt(newColor.r, newColor.g, newColor.b, 255),
x,
y + i
);
}
}
passed++;
if (
(passed >= lineDash[0] && drawing) ||
(passed >= lineDash[1] && !drawing)
) {
drawing = !drawing;
passed = 0;
}
});
drawing = true;
// Right border
image.scanQuiet(
x + width + offset,
y + lineWidth + offset,
1,
height - lineWidth * 2,
(x, y) => {
if (drawing) {
const pixelColor = Jimp.intToRGBA(image.getPixelColor(x, y));
const newColor = blendColors(pixelColor, color);
for (let i = 0; i < lineWidth; i++) {
image.setPixelColor(
Jimp.rgbaToInt(newColor.r, newColor.g, newColor.b, 255),
x - i,
y
);
}
}
passed++;
if (
(passed >= lineDash[0] && drawing) ||
(passed >= lineDash[1] && !drawing)
) {
drawing = !drawing;
passed = 0;
}
}
);
drawing = true;
// Bottom border
image.scanQuiet(
x + width + offset,
y + height + offset,
-width,
-1,
(x, y) => {
if (drawing) {
const pixelColor = Jimp.intToRGBA(image.getPixelColor(x, y));
const newColor = blendColors(pixelColor, color);
for (let i = 0; i < lineWidth; i++) {
image.setPixelColor(
Jimp.rgbaToInt(newColor.r, newColor.g, newColor.b, 255),
x,
y - i
);
}
}
passed++;
if (
(passed >= lineDash[0] && drawing) ||
(passed >= lineDash[1] && !drawing)
) {
drawing = !drawing;
passed = 0;
}
}
);
drawing = true;
// Left border
image.scanQuiet(
x - offset,
y + height - lineWidth - offset,
1,
-height + lineWidth * 2,
(x, y) => {
if (drawing) {
const pixelColor = Jimp.intToRGBA(image.getPixelColor(x, y));
const newColor = blendColors(pixelColor, color);
for (let i = 0; i < lineWidth; i++) {
image.setPixelColor(
Jimp.rgbaToInt(newColor.r, newColor.g, newColor.b, 255),
x + i,
y
);
}
}
passed++;
if (
(passed >= lineDash[0] && drawing) ||
(passed >= lineDash[1] && !drawing)
) {
drawing = !drawing;
passed = 0;
}
}
);
}
function blendColors(c1, c2) {
const stepPoint = c2.a / 255;
const r = c1.r + stepPoint * (c2.r - c1.r);
const g = c1.g + stepPoint * (c2.g - c1.g);
const b = c1.b + stepPoint * (c2.b - c1.b);
return { r, g, b };
}
(async () => {
let image = await Jimp.read("./test.png");
dashedBorder(
image,
{ lineWidth: 3, lineDash: [20, 5], color: 0x1a53ffbb },
{ x: 0, y: 0, width: image.bitmap.width, height: image.bitmap.height }
);
image.write("./test-border.png");
})();
注意:忽略第二张图片中间的数字。
更新:新代码
const Jimp = require("jimp");
function dashedBorder(
image,
{ lineDash, lineWidth, color },
{ x, y, width, height }
) {
let drawing = true,
passed = 0,
offset = lineWidth - 1;
color = Jimp.intToRGBA(color);
// Top border
for (let i = x; i < x + width; i++) {
if (drawing) {
const pixelColor = Jimp.intToRGBA(image.getPixelColor(x, y - offset));
const newColor = blendColors(pixelColor, color);
for (let k = 0; k < lineWidth; k++) {
image.setPixelColor(
Jimp.rgbaToInt(newColor.r, newColor.g, newColor.b, 255),
i,
y - offset + k
);
}
}
passed++;
if (
(passed >= lineDash[0] && drawing) ||
(passed >= lineDash[1] && !drawing)
) {
drawing = !drawing;
passed = 0;
}
}
// Right border
for (let j = y; j < y + height; j++) {
if (drawing) {
const pixelColor = Jimp.intToRGBA(
image.getPixelColor(x + width + offset, y)
);
const newColor = blendColors(pixelColor, color);
for (let k = 0; k < lineWidth; k++) {
image.setPixelColor(
Jimp.rgbaToInt(newColor.r, newColor.g, newColor.b, 255),
x + width + offset - k,
j
);
}
}
passed++;
if (
(passed >= lineDash[0] && drawing) ||
(passed >= lineDash[1] && !drawing)
) {
drawing = !drawing;
passed = 0;
}
}
// Bottom border
for (let i = x + width - (lineWidth - offset); i > x; i--) {
if (drawing) {
const pixelColor = Jimp.intToRGBA(
image.getPixelColor(i, y + height + offset)
);
const newColor = blendColors(pixelColor, color);
for (let k = 0; k < lineWidth; k++) {
image.setPixelColor(
Jimp.rgbaToInt(newColor.r, newColor.g, newColor.b, 255),
i,
y + height - k + offset
);
}
}
passed++;
if (
(passed >= lineDash[0] && drawing) ||
(passed >= lineDash[1] && !drawing)
) {
drawing = !drawing;
passed = 0;
}
}
// Left border
for (let j = y + height - (lineWidth - offset); j > y; j--) {
if (drawing) {
const pixelColor = Jimp.intToRGBA(image.getPixelColor(x - offset, j));
const newColor = blendColors(pixelColor, color);
for (let k = 0; k < lineWidth; k++) {
image.setPixelColor(
Jimp.rgbaToInt(newColor.r, newColor.g, newColor.b, 255),
x + k - offset,
j
);
}
}
passed++;
if (
(passed >= lineDash[0] && drawing) ||
(passed >= lineDash[1] && !drawing)
) {
drawing = !drawing;
passed = 0;
}
}
}
function blendColors(c1, c2) {
const stepPoint = c2.a / 255;
const r = c1.r + stepPoint * (c2.r - c1.r);
const g = c1.g + stepPoint * (c2.g - c1.g);
const b = c1.b + stepPoint * (c2.b - c1.b);
return { r, g, b };
}
(async () => {
let image = await Jimp.read("./test.png");
dashedBorder(
image,
{ lineWidth: 3, lineDash: [20, 5], color: 0x1a53ffbb },
{ x: 0, y: 0, width: image.bitmap.width, height: image.bitmap.height }
);
image.write("./test-border.png");
})();