首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >绘制圆Jimp JavaScript

绘制圆Jimp JavaScript
EN

Stack Overflow用户
提问于 2019-01-14 09:57:22
回答 2查看 1.6K关注 0票数 0

我试着用下面的代码用Jimp在JavaScript中画一个圆。

代码语言:javascript
运行
复制
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");
});

它会产生这样的结果。

问题是,当你放大的时候,它看起来真的很起伏。

我怎样才能使圆圈更平滑、更少起伏呢?

EN

回答 2

Stack Overflow用户

发布于 2019-01-14 10:33:07

您需要创建anti-aliasing。对于黑白来说,这很容易做到,只需基于每个像素到中心的浮动距离来控制每个像素的灰度级别。

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

下面是一个使用Canvas2D应用编程接口的示例,但核心逻辑直接适用于您的代码。

代码语言:javascript
运行
复制
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);
}
代码语言:javascript
运行
复制
<canvas id="c" width="500" height="500"></canvas>

票数 2
EN

Stack Overflow用户

发布于 2019-01-14 10:07:08

我很抱歉这么说,但答案是你真的做不到。问题是,像素是可以绘制的最小单位,您必须绘制它或不绘制它。所以,只要你使用一些raster image format (而不是vector graphics),你就不能在大缩放时画出平滑的线条。

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

有三种可能的解决方法:

  1. 绘制一个大得多的图像,这样你一开始就不需要缩放它(但它将占用更多的空间来绘制一些矢量图形,如SVG (但你必须更改库,这可能不是你最终想要的,因为它还有一些其他问题)
  2. 尝试使用anti-aliasing,这是一个用来颠覆人类视觉的聪明技巧:你在边缘周围绘制一些像素为灰色而不是黑白。它在小缩放时看起来会更好,但在足够大的缩放时,你仍然可以看到实际的细节,魔术就会停止工作。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54174947

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档