Алгоритм сглаживания для Pixelart - PullRequest
0 голосов
/ 21 мая 2019

У меня есть изображение или Pixelart из-за отсутствия лучшего слова, очень маленького размера. На самом деле это просто массив чисел примерно такого размера: new int[150][10]. Я рисую линии и кривые на этом массиве, в основном один цвет на черном фоне. Он предназначен для управления светодиодной полосой позже. Поэтому сейчас я ищу метод сглаживания линий, кривых и фигур, которые я рисую. Я просто хочу ввести свой массив, вроде этого:

int[][] antiAlias(int[][] image) {
    int[][] result = new int[image.length][image[0].length];

    // do magic here

    return result;
}

Я наткнулся на сглаживание Ву, но, насколько я могу судить, это только для рисования линий. Я был бы очень признателен, если бы кто-нибудь дал мне подсказку о том, какой алгоритм мне следует искать.

Я также читал, что эффект сглаживания может быть достигнут с помощью понижающей дискретизации. Поскольку для меня не составит труда создать линии и кривые в массиве с более высоким разрешением, это также может быть вариантом. Но я понятия не имею, как выполнить понижающую дискретизацию, и все, что я могу найти в Интернете об этом, всегда работает с Image - Объекты и использует библиотеки, что, конечно, не вариант, так как я не использую фактическое изображение. Я хотел бы, чтобы функция понижающей дискретизации была такой:

// scale should be power of 2 (I guess??)
int[][] downsample(int[][] image, int scale) {
    int[][] result = new int[image.length / 2][image[0].length / 2];

    // do magic here

    if (scale > 2) return downsample(result, scale / 2);
    return result;
}

Опять же, если у кого-нибудь есть хорошая идея для меня, какие алгоритмы я мог бы рассмотреть, я был бы очень признателен.

1 Ответ

0 голосов
/ 22 мая 2019

Я посмотрел на билинейную интерполяцию, как это было предложено в комментариях. Это то, что я придумал. Алгоритм работает только для уменьшения масштаба, когда размеры результатов составляют ровно половину оригинала. Поскольку во время процесса уменьшения масштаба теряется много яркости, я снова осветляю все пиксели. Для этого еще нужно лучшее решение, но пока оно работает.

int[][] bilinearDownscale(int[][] original, int scale, boolean brighten) {
    int[][] result = new int[original.length / 2][original[0].length / 2];

    // the four pixels from which we derive our downscaled pixel
    // i = 0 -> red, i = 1 -> green, i = 2 -> blue
    int a[] = new int[3];
    int b[] = new int[3];
    int c[] = new int[3];
    int d[] = new int[3];
    for (int x = 0; x < result.length; x++) {
        for (int y = 0; y < result[0].length; y++) {

            // get the individual color values of the old pixels
            a[0] = (original[x * 2][y * 2]) >> 16 & 0xFF;
            b[0] = (original[x * 2 + 1][y * 2]) >> 16 & 0xFF;
            c[0] = (original[x * 2][y * 2 + 1]) >> 16 & 0xFF;
            d[0] = (original[x * 2 + 1][y * 2 + 1]) >> 16 & 0xFF;

            a[1] = (original[x * 2][y * 2]) >> 8 & 0xFF;
            b[1] = (original[x * 2 + 1][y * 2]) >> 8 & 0xFF;
            c[1] = (original[x * 2][y * 2 + 1]) >> 8 & 0xFF;
            d[1] = (original[x * 2 + 1][y * 2 + 1]) >> 8 & 0xFF;

            a[2] = original[x * 2][y * 2] & 0xFF;
            b[2] = original[x * 2 + 1][y * 2] & 0xFF;
            c[2] = original[x * 2][y * 2 + 1] & 0xFF;
            d[2] = original[x * 2 + 1][y * 2 + 1] & 0xFF;

            // get the individually interpolated color values
            int red = (int) (0.25 * (a[0] + b[0] + c[0] + d[0]));
            int green = (int) (0.25 * (a[1] + b[1] + c[1] + d[1]));
            int blue = (int) (0.25 * (a[2] + b[2] + c[2] + d[2]));

            // apply saturation if so desired
            if (brighten) {
                float hsb[] = Color.RGBtoHSB(red, green, blue, null);
                hsb[2] = -((hsb[2] - 1) * (hsb[2] - 1)) + 1;

                // compute the new color value
                result[x][y] = Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]);
            } else {

                // compute the new color value
                result[x][y] = (red << 16) | (green << 8) | blue;
            }
        }
    }

    // yay recursion
    if (scale > 2) {
        return bilinearDownscale(result, scale / 2, brighten);
    }
    return result;
}
...