0

我正在制作一个Node.js应用程序Jimp。我有一个选择图像的一部分的功能。它在该区域中绘制一个矩形,在中间写入选择的编号,然后在矩形选择的外部绘制虚线边框。虚线边框似乎在增加,我不知道为什么。这是文件的完整代码:

imageManipulationUtil.js

const Jimp = require("jimp");

module.exports = async (readPath, writePath, comments, callback) => {
    const originalImage = await Jimp.read(readPath);
    const font = await Jimp.loadFont(Jimp.FONT_SANS_32_BLACK);
    
    // Please ignore this part. Focus on the other part (the functions I mentioned above).
    const addedWidth = 500;

    const commentsHeight = comments.reduce((commentsHeight, { comment }, i) => {
        comments[i].comment = `${i + 1}. ${comment}`;
        const textWidth = Jimp.measureText(font, comment);
        const textHeight = Jimp.measureTextHeight(font, comment);
        const lines = Math.ceil(textWidth / addedWidth);
        const height = textHeight * lines;
        return commentsHeight + height;
    }, 0);
    const imageHeight = commentsHeight + 10;

    if (imageHeight > originalImage.getHeight())
        originalImage.resize(Jimp.AUTO, imageHeight);

    const newImage = new Jimp(
        originalImage.getWidth() + addedWidth,
        originalImage.getHeight(),
        0xffffffff
    );

    // Some other code for another purpose

    // !!! Important code START !!!
    drawSelectionRects(comments, font, newImage);

    async function drawSelectionRects(comments, font, image) {
        comments.forEach(({ dimensions }) => {
            image.scanQuiet(
                dimensions.x,
                dimensions.y,
                dimensions.width,
                dimensions.height,
                (x, y, idx) => {
                    const color = {
                        r: image.bitmap.data[idx + 0],
                        g: image.bitmap.data[idx + 1],
                        b: image.bitmap.data[idx + 2],
                        a: image.bitmap.data[idx + 3] / 255,
                    };

                    const selectionColor = {
                        r: 187,
                        g: 187,
                        b: 187,
                        a: 187,
                    };

                    const newColor = blendColors(color, selectionColor);

                    const hexColor = Jimp.rgbaToInt(
                        newColor.r,
                        newColor.g,
                        newColor.b,
                        255
                    );

                    image.setPixelColor(hexColor, x, y);
                }
            );

            dashedBorder(
                image,
                { lineDash: [20, 5], lineWidth: 3, color: 0x1a53ffbb },
                dimensions
            );
        });
        comments.forEach(({ dimensions }, i) => {
            const text = `${i + 1}`;

            let textX =
                dimensions.x + (dimensions.width - Jimp.measureText(font, text)) / 2;
            let textY =
                dimensions.y +
                (dimensions.height - Jimp.measureTextHeight(font, text)) / 2;

            image.print(font, textX, textY, text);
        });
    }

    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 };
    }

    function dashedBorder(
        image,
        { lineDash, lineWidth, color },
        { x, y, width, height }
    ) {
        let drawing = true,
            passed = 0;

        color = Jimp.intToRGBA(color);

        // Top border
        for (let i = x; i < x + width; i++) {
            if (drawing) {
                const pixelColor = Jimp.intToRGBA(image.getPixelColor(x, y));

                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 - k
                    );
                }
            }

            passed++;
            if (
                (passed >= lineDash[0] && drawing) ||
                (passed >= lineDash[1] && !drawing)
            ) {
                drawing = !drawing;
                passed = 0;
            }
        }

        drawing = true;

        // Right border
        for (let j = y; j < y + height; j++) {
            if (drawing) {
                const pixelColor = Jimp.intToRGBA(image.getPixelColor(x + width, 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 + k,
                        j
                    );
                }
            }

            passed++;
            if (
                (passed >= lineDash[0] && drawing) ||
                (passed >= lineDash[1] && !drawing)
            ) {
                drawing = !drawing;
                passed = 0;
            }
        }

        drawing = true;

        // Bottom border
        for (let i = x + width; i > x; i--) {
            if (drawing) {
                const pixelColor = Jimp.intToRGBA(image.getPixelColor(i, y + height));

                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
                    );
                }
            }

            passed++;
            if (
                (passed >= lineDash[0] && drawing) ||
                (passed >= lineDash[1] && !drawing)
            ) {
                drawing = !drawing;
                passed = 0;
            }
        }

        drawing = true;

        // Left border
        for (let j = y + height; j > y + lineWidth; j--) {
            if (drawing) {
                const pixelColor = Jimp.intToRGBA(image.getPixelColor(x, 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,
                        j
                    );
                }
            }

            passed++;
            if (
                (passed >= lineDash[0] && drawing) ||
                (passed >= lineDash[1] && !drawing)
            ) {
                drawing = !drawing;
                passed = 0;
            }
        }
    }

    newImage.write(writePath);

    callback();
};
// !!! Important code END !!!

该代码导出了一个带有一些参数的函数。最重要的参数是评论参数(特别是评论的维度)。注释参数是一个对象数组。对象有一个dimensions关键,这是这个问题中的重要关键。

上传的图片: 上传

收到的图片: 收到

让我认为图像正在成倍增加的问题是,在某些地方边框比其他部分更透明。最初我认为这只是因为我使用的图像,但后来我切换它并注意到这是一个真正的问题。

新的完整代码:

const Jimp = require("jimp");

function dashedBorder(
    image,
    { lineDash, lineWidth, color },
    { x, y, width, height }
) {
    let drawing = true,
        passed = 0,
        outsideWidth = lineWidth - 1;

    color = Jimp.intToRGBA(color);

    // Top border
    for (let i = x - outsideWidth; i < x + width + outsideWidth; i++) {
        if (drawing) {
            for (let k = 0; k < lineWidth; k++) {
                image.setPixelColor(
                    Jimp.rgbaToInt(color.r, color.g, color.b, 255),
                    i,
                    y - k
                );
            }
        }

        passed++;
        if (
            (passed >= lineDash[0] && drawing) ||
            (passed >= lineDash[1] && !drawing)
        ) {
            drawing = !drawing;
            passed = 0;
        }
    }

    // Right border
    for (
        let j = y + lineWidth - outsideWidth;
        j < y + height - (lineWidth - outsideWidth);
        j++
    ) {
        if (drawing) {
            for (let k = 0; k < lineWidth; k++) {
                image.setPixelColor(
                    Jimp.rgbaToInt(color.r, color.g, color.b, 255),
                    x + width + k - 1,
                    j
                );
            }
        }

        passed++;
        if (
            (passed >= lineDash[0] && drawing) ||
            (passed >= lineDash[1] && !drawing)
        ) {
            drawing = !drawing;
            passed = 0;
        }
    }

    // Bottom border
    for (let i = x + width + lineWidth - outsideWidth; i > x - lineWidth; i--) {
        if (drawing) {
            for (let k = 0; k < lineWidth; k++) {
                image.setPixelColor(
                    Jimp.rgbaToInt(color.r, color.g, color.b, 255),
                    i,
                    y + height + k - 1
                );
            }
        }

        passed++;
        if (
            (passed >= lineDash[0] && drawing) ||
            (passed >= lineDash[1] && !drawing)
        ) {
            drawing = !drawing;
            passed = 0;
        }
    }

    // Left border
    for (let j = y + height - outsideWidth; j > y; j--) {
        if (drawing) {
            for (let k = 0; k < lineWidth; k++) {
                image.setPixelColor(
                    Jimp.rgbaToInt(color.r, color.g, color.b, 255),
                    x - k,
                    j
                );
            }
        }

        passed++;
        if (
            (passed >= lineDash[0] && drawing) ||
            (passed >= lineDash[1] && !drawing)
        ) {
            drawing = !drawing;
            passed = 0;
        }
    }
}

(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");
})();

图片: 图3

4

0 回答 0