Рисуем круг Jimp JavaScript - PullRequest
       8

Рисуем круг Jimp JavaScript

0 голосов
/ 14 января 2019

Я пытаюсь нарисовать круг в 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");
});

Это производит это.

circle

Проблема в том, что при увеличении изображение выглядит очень прерывистым.

Circle Zoomed

Как сделать круг более плавным и менее изменчивым?

Ответы [ 2 ]

0 голосов
/ 14 января 2019

Вам необходимо создать сглаживание . Это легко сделать для черного и белого, просто контролируя уровень серого каждого пикселя в зависимости от расстояния до центра.

Например, пиксель с расстоянием 250 в вашей настройке должен быть черным, а пиксель с расстоянием 250,5 - серым (~ # 808080). Так что все, что вам нужно сделать, это принять во внимание эти плавающие точки.

Вот пример использования API 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>
0 голосов
/ 14 января 2019

Извините, что говорю это, но ответ в том, что вы не можете этого сделать. Проблема в том, что пиксель - это минимальная единица, которую можно нарисовать, и вы должны либо нарисовать ее, либо нет. Поэтому, если вы используете какой-либо формат растрового изображения (в отличие от векторной графики ), вы не сможете нарисовать плавную линию при большом увеличении.

Если вы подумаете об этом, вы можете обвинить проблему в приложении масштабирования, которое не знает о логике изображения (круга) и отображает каждый пиксель на множество целых пикселей. Иными словами, ваше изображение имеет только 500x500 пикселей информации. Вы не можете надежно построить 5000x5000 пикселей информации (что фактически является 10-кратным увеличением), потому что в исходном изображении недостаточно информации. Таким образом, вам (или тому, кто выполняет масштабирование) приходится угадывать, как заполнить недостающую информацию, и это «измельчение» является результатом самого простого (и наиболее широко используемого) алгоритма угадывания, который есть: просто сопоставьте каждый пиксель на NxN пикселях. где N - коэффициент увеличения.

Существует три возможных обходных пути:

  1. Нарисуйте намного большее изображение, чтобы вам не нужно было увеличивать его в первую очередь (но это займет гораздо больше места везде)

  2. Используйте некоторую векторную графику, например SVG (но вам придется изменить библиотеку, и в конечном итоге это может быть не то, что вам нужно, потому что с этим есть другие проблемы)

  3. Попробуйте использовать сглаживание , который является хитрым трюком, используемым для искажения того, что видят люди: вы рисуете несколько пикселей по краю как серый, а не черно-белый. При небольших увеличениях он будет выглядеть лучше, но при достаточно больших увеличениях вы все равно увидите реальные детали, и магия перестанет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...