0

我正在制作一个用于图像处理的Node.js应用程序。Jimp我想根据矩形本身的参数(x、y、宽度和高度)在矩形上制作虚线边框。我希望边框尽可能接近 Web 浏览器的虚线边框。我的意思是它向上、向右、向下,最后向左。我还需要一个offset变量来让它稍微向外一点,但我想我做到了(如果你认为有办法改善偏移,请告诉我)。问题是我使用scanQuietfromJimp并且我无法后退(即 -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");
})();
4

0 回答 0