java - Pixelart 的抗锯齿算法

标签 java algorithm pixel antialiasing downsampling

我有一个图像,或者 Pixelart,因为没有更好的词,非常小。它实际上只是一个大约这个大小的数字数组:new int[150][10]。我在这个数组上画直线和曲线,主要是在黑色背景上画一种颜色。它旨在稍后控制 LED-Strip。所以现在我正在寻找一种方法来消除我绘制的线条、曲线和形状的锯齿。我只想输入我的数组,有点像这样:

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

    // do magic here

    return result;
}

我偶然发现了 Wu 的抗锯齿功能,但据我所知它仅用于绘制线条。如果有人可以提示我应该寻找哪种算法,我将不胜感激。

我还读到抗锯齿效果可以通过下采样来实现。因为在具有更高分辨率的阵列中创建直线和曲线对我来说没有问题,所以这也是一个选项。但是我不知道如何执行下采样,而且我在互联网上可以找到的所有关于它的东西总是适用于 Image- Objects 并使用库,这当然是没有选择的,因为我不是使用实际图像。 我想要一个像这样的下采样函数:

// 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;
}

再说一次,如果有人对我有什么好主意,我可以研究什么样的算法,我将非常感激。

最佳答案

我查看了双线性插值,正如评论中所建议的那样。这就是我想出的。当结果维度恰好是原始维度的一半时,该算法仅适用于降尺度。因为在缩小过程中丢失了很多亮度,所以我再次调亮所有像素。仍然需要一个更好的解决方案,但它现在有效。

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;
}

关于java - Pixelart 的抗锯齿算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56229861/

相关文章:

c++ - 移动窗口 RMQ 性能改进

algorithm - 哈密​​顿循环的帕默算法

C# GDI - 如何检查像素是否不透明?

java - Windows 7配置上带有HBase的Titan

java - 使用票证服务器生成主 ID?

java - 为什么我的反射加载奇怪的类?

c++ - 生成二维非退化点集 - C++

c++ - 从 SDL_Surface 读取像素并转换为颜色值

c++ - Windows中获取屏幕坐标像素数据的简单方法

java - 使用导航组件多次触发 LiveData 观察者