0

我正在尝试生成图像的 mipmap。像素存储为 byte[] 格式为 {r,g,b,a,r,g,b,a,r,g,b,a ... }

它试图做的是获取图像中的每组四个像素并找到这四个像素的平均值,然后将其放入新图像中。

为示例纹理创建所有 mipmap 的结果在这里:http: //imgur.com/KdEEzAw

如果有一种方法可以在不使用我自己的算法且不使用 directx 或任何东西(我没有使用 mipmap 进行渲染,我将它们保存到文件中)的情况下创建 mipmap,那就太好了

public static byte[] mipmap(byte[] inPixels, int width, int height)
{
    // add one to width and height incase they are 1
    byte[] outPixels = new byte[((width + 1) / 2) * ((height + 1) / 2) * 4];
    for (int y = 0; y < height; y += 2)
    {
        for (int x = 0; x < width; x += 2)
        {
            // get the four red values
            int[] r = new int[4];
            r[0] = (int)inPixels[x + y * width + 0]; // top left
            r[1] = (int)inPixels[(x + 1) + y * width + 0]; // top right
            r[2] = (int)inPixels[(x + 1) + (y + 1) * width + 0]; // bottom right
            r[3] = (int)inPixels[x + (y + 1) * width + 0]; // bottom left

            // get the four green values
            int[] g = new int[4];
            g[0] = (int)inPixels[x + y * width + 1]; // top left
            g[1] = (int)inPixels[(x + 1) + y * width + 1]; // top right
            g[2] = (int)inPixels[(x + 1) + (y + 1) * width + 1]; // bottom right
            g[3] = (int)inPixels[x + (y + 1) * width + 1]; // bottom left

            // get the four blue values
            int[] b = new int[4];
            b[0] = (int)inPixels[x + y * width + 2]; // top left
            b[1] = (int)inPixels[(x + 1) + y * width + 2]; // top right
            b[2] = (int)inPixels[(x + 1) + (y + 1) * width + 2]; // bottom right
            b[3] = (int)inPixels[x + (y + 1) * width + 2]; // bottom left

            // get the four alpha values
            int[] a = new int[4];
            a[0] = (int)inPixels[x + y * width + 3]; // top left
            a[1] = (int)inPixels[(x + 1) + y * width + 3]; // top right
            a[2] = (int)inPixels[(x + 1) + (y + 1) * width + 3]; // bottom right
            a[3] = (int)inPixels[x + (y + 1) * width + 3]; // bottom left

            // the index in the new image, we divide by 2 because the image is half the size of the original image
            int index = (x + y * width) / 2;
            outPixels[index + 0] = (byte)((r[0] + r[1] + r[2] + r[3]) / 4);
            outPixels[index + 1] = (byte)((g[0] + g[1] + g[2] + g[3]) / 4);
            outPixels[index + 2] = (byte)((b[0] + b[1] + b[2] + b[3]) / 4);
            outPixels[index + 3] = (byte)((a[0] + a[1] + a[2] + a[3]) / 4);
        }
    }
    return outPixels;
}
4

1 回答 1

0

我认为问题出在这里:

inPixels[x + y * width + 0]

通常,当一个数组元素是一个像素,只有一个元素是一个像素的一个通道时,这运行正确。所以每个像素开始一个 (x + (y * width)) * 4所以它应该是这样的:

inPixels[((x + y * width) * 4) + 0]

我写了一些优化代码,也许你会得到一些额外的想法,但我没有测试它:

public static byte[] mipmap(byte[] inPixels, int width, int height)
{
    // add one to width and height incase they are 0
    byte[] outPixels = new byte[((width / 2) * (height / 2)) * 4];

    // the offsets of the neighbor pixels (with *4 for the channel)
    // this will automatically select a channel of a pixel one line down.
    int[] neighborOffsets = new int[] { 0 * 4, 1 * 4, width * 4, (width + 1) * 4 };

    // an 'offset for output buffer'
    int outputOffset = 0;

    // an 'offset for input buffer'
    int inputOffset = 0;

    for (int y = 0; y < height / 2; y++)
    {
        for (int x = 0; x < width / 2; x++)
        {

            // calculate the average of each channel
            for (int channelIndex = 0; channelIndex < 4; channelIndex++)
            {
                int totalValue = 0;

                for (int offset = 0; offset < 4; offset++)
                    totalValue = (int)inPixels[inputOffset + neighborOffsets[offset] + channelIndex];

                // write it to the ouput buffer and increase the offset.
                outPixels[outputOffset++] = (byte)(totalValue / 4);

            }
            // set the input offset on the next pixel. The next pixel is current + 2.
            inputOffset += 2 * 4; // *4 for the channelcount (*4 will be optimized by the compiler)
        }
        inputOffset += width * 4; // skip an extra line. *4 for the channelcount (*4 will be optimized by the compiler)
    }

    return outPixels;
}

它可能有一些小错误,但它的运行速度可能是它的 4 倍。尽量避免乘法的冗余。

于 2013-09-16T10:17:35.190 回答