【问题标题】:Draw Circle Jimp JavaScript画圆 Jimp JavaScript
【发布时间】:2019-01-14 01:57:21
【问题描述】:

我正在尝试使用下面的代码在 JavaScript 中使用 Jimp 绘制一个圆圈。

const Jimp = require("jimp");

const size = 500;
const black = [0, 0, 0, 255];
const white = [255, 255, 255, 255];
new Jimp(size, size, (err, image) => {
    for (let x = 0; x < size; x++) {
        for (let y = 0; y < size; y++) {
            const colorToUse = distanceFromCenter(size, x, y) > size / 2 ? black : white;
            const color = Jimp.rgbaToInt(...colorToUse);
            image.setPixelColor(color, x, y);
        }
    }
    image.write("circle.png");
});

它会产生这个。

问题是,当你放大时,它看起来很不稳定。

我怎样才能使圆圈更平滑,更不波涛汹涌?

【问题讨论】:

  • 你的代码没有设置任何抗锯齿,听起来正常你没有。

标签: javascript algorithm geometry


【解决方案1】:

您需要创建anti-aliasing。只需根据像素到中心的浮动距离来控制每个像素的灰度级别,就可以轻松实现黑白。

例如,设置中距离为 250 的像素应为黑色,但距离为 250.5 的像素应为灰色 (~ #808080)。 所以你所要做的就是考虑这些浮点数。

这是一个使用 Canvas2D API 的示例,但核心逻辑直接适用于您的代码。

const size = 500;
const rad = size / 2;
const black = 0xFF000000; //[0, 0, 0, 255];
const white = 0xFFFFFFFF; //[255, 255, 255, 255];

const img = new ImageData(size, size);
const data = new Uint32Array(img.data.buffer);

for (let x = 0; x < size; x++) {
  for (let y = 0; y < size; y++) {
    const dist = distanceFromCenter(rad, x, y);
    let color;
    if (dist >= rad + 1) color = black;
    else if (dist <= rad) color = white;
    else {
      const mult = (255 - Math.floor((dist - rad) * 255)).toString(16).padStart(2, 0);
      color = '0xff' + mult.repeat(3); // grayscale 0xffnnnnnn
    }
    // image.setPixelColor(color, x, y);
    data[(y * size) + x] = Number(color);
  }
}
//image.write("circle.png");
c.getContext('2d').putImageData(img, 0, 0);


function distanceFromCenter(rad, x, y) {
  return Math.hypot(rad - x, rad - y);
}
&lt;canvas id="c" width="500" height="500"&gt;&lt;/canvas&gt;

【讨论】:

    【解决方案2】:

    我很抱歉这么说,但答案是你真的做不到。问题是像素是可以绘制的最小单位,您必须绘制或不绘制它。因此,只要您使用一些raster image format(而不是vector graphics),您就无法在大变焦下绘制平滑线。

    如果您考虑一下,您可能会将问题归咎于缩放应用程序,该应用程序不了解图像(圆圈)的逻辑并将每个像素映射到许多完整像素。换句话说,您的图像只有 500x500 像素的信息。您无法从中可靠地构建 5,000x5,000 像素的信息(这实际上是 10 倍缩放),因为原始图像中没有足够的信息。因此,您(或进行缩放的任何人)必须猜测如何填充缺失的信息,而这种“斩波”是最简单(也是最广泛使用)的猜测算法的结果:只需将每个像素映射到 NxN 像素上其中N 是缩放系数。

    有三种可能的解决方法:

    1. 绘制一个更大的图像,这样您就不需要一开始就对其进行缩放(但它会占用更多空间)

    2. 使用一些矢量图形,如 SVG(但您必须更改库,最终可能不是您想要的,因为还有其他一些问题)

    3. 尝试使用anti-aliasing,这是一个巧妙的技巧,可以颠覆人类的观察方式:在边缘周围绘制一些像素,使其变为灰色而不是黑白。它在小变焦下看起来会更好,但在足够大的变焦下,您仍然会看到实际的细节,并且魔法将停止工作。

    【讨论】:

      猜你喜欢
      • 2015-09-30
      • 1970-01-01
      • 1970-01-01
      • 2021-02-16
      • 2014-08-13
      • 2021-10-01
      • 2015-02-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多