我试着用下面的代码用Jimp在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");
});它会产生这样的结果。

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

我怎样才能使圆圈更平滑、更少起伏呢?
发布于 2019-01-14 10:33:07
您需要创建anti-aliasing。对于黑白来说,这很容易做到,只需基于每个像素到中心的浮动距离来控制每个像素的灰度级别。
例如,设置中距离为808080的像素应为黑色,距离为250.5的像素应为灰色(~ # 250 )。所以你要做的就是考虑这些浮点数。
下面是一个使用Canvas2D应用编程接口的示例,但核心逻辑直接适用于您的代码。
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);
}<canvas id="c" width="500" height="500"></canvas>
发布于 2019-01-14 10:07:08
我很抱歉这么说,但答案是你真的做不到。问题是,像素是可以绘制的最小单位,您必须绘制它或不绘制它。所以,只要你使用一些raster image format (而不是vector graphics),你就不能在大缩放时画出平滑的线条。
如果你仔细想想,你可能会将问题归咎于缩放应用程序,它不知道图像(圆)的逻辑,并将每个像素映射到许多整个像素。换句话说,你的图像只有500x500像素的信息。您不能可靠地构建5,000x5,000像素的信息(这实际上就是10倍缩放),因为原始图像中没有足够的信息。因此,您(或执行缩放的任何人)必须猜测如何填充缺失的信息,而这种“斩首”是最简单(也是最广泛使用的)猜测算法的结果:只需将每个像素映射到NxN像素上,其中N是缩放因子。
有三种可能的解决方法:
https://stackoverflow.com/questions/54174947
复制相似问题