Ejemplo n.º 1
0
        private static void Encodedxtcolorblockfaster(GLubyte *blkaddr, GLubyte ***srccolors,
                                                      GLint numxpixels, GLint numypixels, GLuint type)
        {
            GLubyte **bestcolor  = stackalloc GLubyte *[2];
            GLubyte **basecolors = stackalloc GLubyte *[2];
            var       bc1        = stackalloc GLubyte[3];
            var       bc2        = stackalloc GLubyte[3];

            basecolors[0] = bc1;
            basecolors[1] = bc2;
            GLubyte i, j;
            GLuint  highcv;
            var     haveAlpha = GlFalse;

            var lowcv = highcv = (uint)(srccolors[0][0][0] * srccolors[0][0][0] * Redweight +
                                        srccolors[0][0][1] * srccolors[0][0][1] * Greenweight +
                                        srccolors[0][0][2] * srccolors[0][0][2] * Blueweight);

            bestcolor[0] = bestcolor[1] = srccolors[0][0];
            for (j = 0; j < numypixels; j++)
            {
                for (i = 0; i < numxpixels; i++)
                {
                    if ((type != GlCompressedRgbaS3TcDxt1Ext) || (srccolors[j][i][3] <= Alphacut))
                    {
                        var testcv = (uint)(srccolors[j][i][0] * srccolors[j][i][0] * Redweight +
                                            srccolors[j][i][1] * srccolors[j][i][1] * Greenweight +
                                            srccolors[j][i][2] * srccolors[j][i][2] * Blueweight);
                        if (testcv > highcv)
                        {
                            highcv       = testcv;
                            bestcolor[1] = srccolors[j][i];
                        }
                        else if (testcv < lowcv)
                        {
                            lowcv        = testcv;
                            bestcolor[0] = srccolors[j][i];
                        }
                    }
                    else
                    {
                        haveAlpha = GlTrue;
                    }
                }
            }

            for (j = 0; j < 2; j++)
            {
                for (i = 0; i < 3; i++)
                {
                    basecolors[j][i] = bestcolor[j][i];
                }
            }
            bestcolor[0] = basecolors[0];
            bestcolor[1] = basecolors[1];

            Fancybasecolorsearch(srccolors, bestcolor, numxpixels, numypixels);
            Storedxtencodedblock(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type, haveAlpha);
        }
Ejemplo n.º 2
0
 private static void Writedxt5Encodedalphablock(GLubyte *blkaddr, GLubyte alphabase1, GLubyte alphabase2,
                                                GLubyte *alphaenc)
 {
     *blkaddr++ = alphabase1;
     *blkaddr++ = alphabase2;
     *blkaddr++ = (byte)(alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6));
     *blkaddr++ =
         (byte)((alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7));
     *blkaddr++ = (byte)((alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5));
     *blkaddr++ = (byte)(alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6));
     *blkaddr++ =
         (byte)((alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7));
     *blkaddr = (byte)((alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5));
 }
Ejemplo n.º 3
0
        // ReSharper disable once FunctionComplexityOverflow
        private static void Encodedxt5Alpha(GLubyte *blkaddr, GLubyte ***srccolors,
                                            GLint numxpixels, GLint numypixels)
        {
            GLubyte *alphabase = stackalloc GLubyte[2];
            GLubyte *alphause = stackalloc GLubyte[2];
            GLshort *alphatest = stackalloc GLshort[2];
            GLubyte *alphaenc1 = stackalloc GLubyte[16];
            GLubyte *alphaenc2 = stackalloc GLubyte[16];
            GLubyte *alphaenc3 = stackalloc GLubyte[16];
            GLubyte *acutValues = stackalloc GLubyte[7];
            GLubyte  i, j, aindex;
            var      alphaabsmin = GlFalse;
            var      alphaabsmax = GlFalse;
            GLshort  alphadist;

            alphabase[0] = 0xff;
            alphabase[1] = 0x0;
            for (j = 0; j < numypixels; j++)
            {
                for (i = 0; i < numxpixels; i++)
                {
                    if (srccolors[j][i][3] == 0)
                    {
                        alphaabsmin = GlTrue;
                    }
                    else if (srccolors[j][i][3] == 255)
                    {
                        alphaabsmax = GlTrue;
                    }
                    else
                    {
                        if (srccolors[j][i][3] > alphabase[1])
                        {
                            alphabase[1] = srccolors[j][i][3];
                        }
                        if (srccolors[j][i][3] < alphabase[0])
                        {
                            alphabase[0] = srccolors[j][i][3];
                        }
                    }
                }
            }


            if ((alphabase[0] > alphabase[1]) && !(alphaabsmin != 0 && alphaabsmax != 0))
            {
                *blkaddr++ = srccolors[0][0][3];
                blkaddr++;
                *blkaddr++ = 0;
                *blkaddr++ = 0;
                *blkaddr++ = 0;
                *blkaddr++ = 0;
                *blkaddr++ = 0;
                *blkaddr   = 0;
                return;
            }

            uint alphablockerror1 = 0x0;
            var  alphablockerror2 = 0xffffffff;
            var  alphablockerror3 = 0xffffffff;

            if (alphaabsmin != 0)
            {
                alphause[0] = 0;
            }
            else
            {
                alphause[0] = alphabase[0];
            }
            if (alphaabsmax != 0)
            {
                alphause[1] = 255;
            }
            else
            {
                alphause[1] = alphabase[1];
            }
            for (aindex = 0; aindex < 7; aindex++)
            {
                acutValues[aindex] =
                    (byte)((alphause[0] * (2 * aindex + 1) + alphause[1] * (14 - (2 * aindex + 1))) / 14);
            }

            for (j = 0; j < numypixels; j++)
            {
                for (i = 0; i < numxpixels; i++)
                {
                    if (srccolors[j][i][3] > acutValues[0])
                    {
                        alphaenc1[4 * j + i] = 0;
                        alphadist            = (short)(srccolors[j][i][3] - alphause[1]);
                    }
                    else if (srccolors[j][i][3] > acutValues[1])
                    {
                        alphaenc1[4 * j + i] = 2;
                        alphadist            = (short)(srccolors[j][i][3] - (alphause[1] * 6 + alphause[0] * 1) / 7);
                    }
                    else if (srccolors[j][i][3] > acutValues[2])
                    {
                        alphaenc1[4 * j + i] = 3;
                        alphadist            = (short)(srccolors[j][i][3] - (alphause[1] * 5 + alphause[0] * 2) / 7);
                    }
                    else if (srccolors[j][i][3] > acutValues[3])
                    {
                        alphaenc1[4 * j + i] = 4;
                        alphadist            = (short)(srccolors[j][i][3] - (alphause[1] * 4 + alphause[0] * 3) / 7);
                    }
                    else if (srccolors[j][i][3] > acutValues[4])
                    {
                        alphaenc1[4 * j + i] = 5;
                        alphadist            = (short)(srccolors[j][i][3] - (alphause[1] * 3 + alphause[0] * 4) / 7);
                    }
                    else if (srccolors[j][i][3] > acutValues[5])
                    {
                        alphaenc1[4 * j + i] = 6;
                        alphadist            = (short)(srccolors[j][i][3] - (alphause[1] * 2 + alphause[0] * 5) / 7);
                    }
                    else if (srccolors[j][i][3] > acutValues[6])
                    {
                        alphaenc1[4 * j + i] = 7;
                        alphadist            = (short)(srccolors[j][i][3] - (alphause[1] * 1 + alphause[0] * 6) / 7);
                    }
                    else
                    {
                        alphaenc1[4 * j + i] = 1;
                        alphadist            = (short)(srccolors[j][i][3] - alphause[0]);
                    }
                    alphablockerror1 += (uint)(alphadist * alphadist);
                }
            }
            if (alphablockerror1 >= 32)
            {
                alphablockerror2 = 0;
                for (aindex = 0; aindex < 5; aindex++)
                {
                    acutValues[aindex] =
                        (byte)((alphabase[0] * (10 - (2 * aindex + 1)) + alphabase[1] * (2 * aindex + 1)) / 10);
                }
                for (j = 0; j < numypixels; j++)
                {
                    for (i = 0; i < numxpixels; i++)
                    {
                        if (srccolors[j][i][3] == 0)
                        {
                            alphaenc2[4 * j + i] = 6;
                            alphadist            = 0;
                        }
                        else if (srccolors[j][i][3] == 255)
                        {
                            alphaenc2[4 * j + i] = 7;
                            alphadist            = 0;
                        }
                        else if (srccolors[j][i][3] <= acutValues[0])
                        {
                            alphaenc2[4 * j + i] = 0;
                            alphadist            = (short)(srccolors[j][i][3] - alphabase[0]);
                        }
                        else if (srccolors[j][i][3] <= acutValues[1])
                        {
                            alphaenc2[4 * j + i] = 2;
                            alphadist            = (short)(srccolors[j][i][3] - (alphabase[0] * 4 + alphabase[1] * 1) / 5);
                        }
                        else if (srccolors[j][i][3] <= acutValues[2])
                        {
                            alphaenc2[4 * j + i] = 3;
                            alphadist            = (short)(srccolors[j][i][3] - (alphabase[0] * 3 + alphabase[1] * 2) / 5);
                        }
                        else if (srccolors[j][i][3] <= acutValues[3])
                        {
                            alphaenc2[4 * j + i] = 4;
                            alphadist            = (short)(srccolors[j][i][3] - (alphabase[0] * 2 + alphabase[1] * 3) / 5);
                        }
                        else if (srccolors[j][i][3] <= acutValues[4])
                        {
                            alphaenc2[4 * j + i] = 5;
                            alphadist            = (short)(srccolors[j][i][3] - (alphabase[0] * 1 + alphabase[1] * 4) / 5);
                        }
                        else
                        {
                            alphaenc2[4 * j + i] = 1;
                            alphadist            = (short)(srccolors[j][i][3] - alphabase[1]);
                        }
                        alphablockerror2 += (uint)(alphadist * alphadist);
                    }
                }


                if ((alphablockerror2 > 96) && (alphablockerror1 > 96))
                {
                    GLshort blockerrlin1       = 0;
                    GLshort blockerrlin2       = 0;
                    GLubyte nralphainrangelow  = 0;
                    GLubyte nralphainrangehigh = 0;
                    alphatest[0] = 0xff;
                    alphatest[1] = 0x0;
                    for (j = 0; j < numypixels; j++)
                    {
                        for (i = 0; i < numxpixels; i++)
                        {
                            if ((srccolors[j][i][3] > alphatest[1]) &&
                                (srccolors[j][i][3] < (255 - (alphabase[1] - alphabase[0]) / 28)))
                            {
                                alphatest[1] = srccolors[j][i][3];
                            }
                            if ((srccolors[j][i][3] < alphatest[0]) &&
                                (srccolors[j][i][3] > (alphabase[1] - alphabase[0]) / 28))
                            {
                                alphatest[0] = srccolors[j][i][3];
                            }
                        }
                    }
                    if (alphatest[1] <= alphatest[0])
                    {
                        alphatest[0] = 1;
                        alphatest[1] = 254;
                    }
                    for (aindex = 0; aindex < 5; aindex++)
                    {
                        acutValues[aindex] =
                            (byte)((alphatest[0] * (10 - (2 * aindex + 1)) + alphatest[1] * (2 * aindex + 1)) / 10);
                    }

                    for (j = 0; j < numypixels; j++)
                    {
                        for (i = 0; i < numxpixels; i++)
                        {
                            if (srccolors[j][i][3] <= alphatest[0] / 2)
                            {
                            }
                            else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2))
                            {
                            }
                            else if (srccolors[j][i][3] <= acutValues[0])
                            {
                                blockerrlin1      += (short)((srccolors[j][i][3] - alphatest[0]));
                                nralphainrangelow += 1;
                            }
                            else if (srccolors[j][i][3] <= acutValues[1])
                            {
                                blockerrlin1 +=
                                    (short)((srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5));
                                blockerrlin2 +=
                                    (short)((srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5));
                                nralphainrangelow  += 1;
                                nralphainrangehigh += 1;
                            }
                            else if (srccolors[j][i][3] <= acutValues[2])
                            {
                                blockerrlin1 +=
                                    (short)((srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5));
                                blockerrlin2 +=
                                    (short)((srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5));
                                nralphainrangelow  += 1;
                                nralphainrangehigh += 1;
                            }
                            else if (srccolors[j][i][3] <= acutValues[3])
                            {
                                blockerrlin1 +=
                                    (short)((srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5));
                                blockerrlin2 +=
                                    (short)((srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5));
                                nralphainrangelow  += 1;
                                nralphainrangehigh += 1;
                            }
                            else if (srccolors[j][i][3] <= acutValues[4])
                            {
                                blockerrlin1 +=
                                    (short)((srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5));
                                blockerrlin2 +=
                                    (short)((srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5));
                                nralphainrangelow  += 1;
                                nralphainrangehigh += 1;
                            }
                            else
                            {
                                blockerrlin2       += (short)((srccolors[j][i][3] - alphatest[1]));
                                nralphainrangehigh += 1;
                            }
                        }
                    }

                    if (nralphainrangelow == 0)
                    {
                        nralphainrangelow = 1;
                    }
                    if (nralphainrangehigh == 0)
                    {
                        nralphainrangehigh = 1;
                    }
                    alphatest[0] = (short)(alphatest[0] + (blockerrlin1 / nralphainrangelow));
                    if (alphatest[0] < 0)
                    {
                        alphatest[0] = 0;
                    }
                    alphatest[1] = (short)(alphatest[1] + (blockerrlin2 / nralphainrangehigh));
                    if (alphatest[1] > 255)
                    {
                        alphatest[1] = 255;
                    }

                    alphablockerror3 = 0;
                    for (aindex = 0; aindex < 5; aindex++)
                    {
                        acutValues[aindex] =
                            (byte)((alphatest[0] * (10 - (2 * aindex + 1)) + alphatest[1] * (2 * aindex + 1)) / 10);
                    }
                    for (j = 0; j < numypixels; j++)
                    {
                        for (i = 0; i < numxpixels; i++)
                        {
                            if (srccolors[j][i][3] <= alphatest[0] / 2)
                            {
                                alphaenc3[4 * j + i] = 6;
                                alphadist            = srccolors[j][i][3];
                            }
                            else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2))
                            {
                                alphaenc3[4 * j + i] = 7;
                                alphadist            = (short)(255 - srccolors[j][i][3]);
                            }
                            else if (srccolors[j][i][3] <= acutValues[0])
                            {
                                alphaenc3[4 * j + i] = 0;
                                alphadist            = (short)(srccolors[j][i][3] - alphatest[0]);
                            }
                            else if (srccolors[j][i][3] <= acutValues[1])
                            {
                                alphaenc3[4 * j + i] = 2;
                                alphadist            = (short)(srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
                            }
                            else if (srccolors[j][i][3] <= acutValues[2])
                            {
                                alphaenc3[4 * j + i] = 3;
                                alphadist            = (short)(srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
                            }
                            else if (srccolors[j][i][3] <= acutValues[3])
                            {
                                alphaenc3[4 * j + i] = 4;
                                alphadist            = (short)(srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
                            }
                            else if (srccolors[j][i][3] <= acutValues[4])
                            {
                                alphaenc3[4 * j + i] = 5;
                                alphadist            = (short)(srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
                            }
                            else
                            {
                                alphaenc3[4 * j + i] = 1;
                                alphadist            = (short)(srccolors[j][i][3] - alphatest[1]);
                            }
                            alphablockerror3 += (uint)(alphadist * alphadist);
                        }
                    }
                }
            }

            if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3))
            {
                Writedxt5Encodedalphablock(blkaddr, alphause[1], alphause[0], alphaenc1);
            }
            else if (alphablockerror2 <= alphablockerror3)
            {
                Writedxt5Encodedalphablock(blkaddr, alphabase[0], alphabase[1], alphaenc2);
            }
            else
            {
                Writedxt5Encodedalphablock(blkaddr, (GLubyte)alphatest[0], (GLubyte)alphatest[1], alphaenc3);
            }
        }
Ejemplo n.º 4
0
        // ReSharper disable once FunctionComplexityOverflow
        public static void CompressDxtn(GLint width, GLint height,
                                        GLubyte *srcPixData, GLenum destFormat,
                                        GLubyte *dest, GLint dstRowStride)
        {
            const int  srccomps  = 4;
            GLubyte *  blkaddr   = dest;
            GLubyte ***srcpixels = stackalloc GLubyte * *[4];
            GLubyte ** scpp0     = stackalloc GLubyte *[4];
            GLubyte *  scp0      = stackalloc GLubyte[4];
            GLubyte *  scp1      = stackalloc GLubyte[4];
            GLubyte *  scp2      = stackalloc GLubyte[4];
            GLubyte *  scp3      = stackalloc GLubyte[4];

            scpp0[0] = scp0;
            scpp0[1] = scp1;
            scpp0[2] = scp2;
            scpp0[3] = scp3;
            GLubyte **scpp1 = stackalloc GLubyte *[4];
            GLubyte * scp10 = stackalloc GLubyte[4];
            GLubyte * scp11 = stackalloc GLubyte[4];
            GLubyte * scp12 = stackalloc GLubyte[4];
            GLubyte * scp13 = stackalloc GLubyte[4];

            scpp1[0] = scp10;
            scpp1[1] = scp11;
            scpp1[2] = scp12;
            scpp1[3] = scp13;
            GLubyte **scpp2 = stackalloc GLubyte *[4];
            GLubyte * scp20 = stackalloc GLubyte[4];
            GLubyte * scp21 = stackalloc GLubyte[4];
            GLubyte * scp22 = stackalloc GLubyte[4];
            GLubyte * scp23 = stackalloc GLubyte[4];

            scpp2[0] = scp20;
            scpp2[1] = scp21;
            scpp2[2] = scp22;
            scpp2[3] = scp23;
            GLubyte **scpp3 = stackalloc GLubyte *[4];
            GLubyte * scp30 = stackalloc GLubyte[4];
            GLubyte * scp31 = stackalloc GLubyte[4];
            GLubyte * scp32 = stackalloc GLubyte[4];
            GLubyte * scp33 = stackalloc GLubyte[4];

            scpp3[0]     = scp30;
            scpp3[1]     = scp31;
            scpp3[2]     = scp32;
            scpp3[3]     = scp33;
            srcpixels[0] = scpp0;
            srcpixels[1] = scpp1;
            srcpixels[2] = scpp2;
            srcpixels[3] = scpp3;
            GLchan *srcaddr;
            GLint   numxpixels, numypixels;
            GLint   i, j;
            GLint   dstRowDiff;

            switch (destFormat)
            {
            case GlCompressedRgbS3TcDxt1Ext:
            case GlCompressedRgbaS3TcDxt1Ext:
                dstRowDiff = dstRowStride >= (width * 2) ? dstRowStride - (((width + 3) & ~3) * 2) : 0;
                for (j = 0; j < height; j += 4)
                {
                    if (height > j + 3)
                    {
                        numypixels = 4;
                    }
                    else
                    {
                        numypixels = height - j;
                    }
                    srcaddr = srcPixData + j * width * srccomps;
                    for (i = 0; i < width; i += 4)
                    {
                        if (width > i + 3)
                        {
                            numxpixels = 4;
                        }
                        else
                        {
                            numxpixels = width - i;
                        }
                        Extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps);
                        Encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels, destFormat);
                        srcaddr += srccomps * numxpixels;
                        blkaddr += 8;
                    }
                    blkaddr += dstRowDiff;
                }
                break;

            case GlCompressedRgbaS3TcDxt3Ext:
                dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0;
                for (j = 0; j < height; j += 4)
                {
                    if (height > j + 3)
                    {
                        numypixels = 4;
                    }
                    else
                    {
                        numypixels = height - j;
                    }
                    srcaddr = srcPixData + j * width * srccomps;
                    for (i = 0; i < width; i += 4)
                    {
                        if (width > i + 3)
                        {
                            numxpixels = 4;
                        }
                        else
                        {
                            numxpixels = width - i;
                        }
                        Extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps);
                        *blkaddr++ = (byte)((srcpixels[0][0][3] >> 4) | (srcpixels[0][1][3] & 0xf0));
                        *blkaddr++ = (byte)((srcpixels[0][2][3] >> 4) | (srcpixels[0][3][3] & 0xf0));
                        *blkaddr++ = (byte)((srcpixels[1][0][3] >> 4) | (srcpixels[1][1][3] & 0xf0));
                        *blkaddr++ = (byte)((srcpixels[1][2][3] >> 4) | (srcpixels[1][3][3] & 0xf0));
                        *blkaddr++ = (byte)((srcpixels[2][0][3] >> 4) | (srcpixels[2][1][3] & 0xf0));
                        *blkaddr++ = (byte)((srcpixels[2][2][3] >> 4) | (srcpixels[2][3][3] & 0xf0));
                        *blkaddr++ = (byte)((srcpixels[3][0][3] >> 4) | (srcpixels[3][1][3] & 0xf0));
                        *blkaddr++ = (byte)((srcpixels[3][2][3] >> 4) | (srcpixels[3][3][3] & 0xf0));
                        Encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels, destFormat);
                        srcaddr += srccomps * numxpixels;
                        blkaddr += 8;
                    }
                    blkaddr += dstRowDiff;
                }
                break;

            case GlCompressedRgbaS3TcDxt5Ext:
                dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0;
                for (j = 0; j < height; j += 4)
                {
                    if (height > j + 3)
                    {
                        numypixels = 4;
                    }
                    else
                    {
                        numypixels = height - j;
                    }
                    srcaddr = srcPixData + j * width * srccomps;
                    for (i = 0; i < width; i += 4)
                    {
                        if (width > i + 3)
                        {
                            numxpixels = 4;
                        }
                        else
                        {
                            numxpixels = width - i;
                        }
                        Extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps);
                        Encodedxt5Alpha(blkaddr, srcpixels, numxpixels, numypixels);
                        Encodedxtcolorblockfaster(blkaddr + 8, srcpixels, numxpixels, numypixels, destFormat);
                        srcaddr += srccomps * numxpixels;
                        blkaddr += 16;
                    }
                    blkaddr += dstRowDiff;
                }
                break;

            default:
                throw new ArgumentException(string.Format("libdxtn: Bad dstFormat {0} in tx_compress_dxtn\n",
                                                          destFormat));
            }
        }
Ejemplo n.º 5
0
        // ReSharper disable once FunctionComplexityOverflow
        private static void Fancybasecolorsearch(GLubyte ***srccolors, GLubyte **bestcolor,
                                                 GLint numxpixels, GLint numypixels)
        {
            GLint   i, j;
            GLint * blockerrlin0 = stackalloc GLint[3];
            GLint * blockerrlin1 = stackalloc GLint[3];
            GLint **blockerrlin  = stackalloc GLint *[2];

            blockerrlin[0] = blockerrlin0;
            blockerrlin[1] = blockerrlin1;
            GLubyte * nrcolor           = stackalloc GLubyte[2];
            GLint *   pixerrorcolorbest = stackalloc GLint[3];
            GLubyte   enc = 0;
            GLubyte **cv  = stackalloc GLubyte *[4];
            GLubyte * cv0 = stackalloc GLubyte[4];
            GLubyte * cv1 = stackalloc GLubyte[4];
            GLubyte * cv2 = stackalloc GLubyte[4];
            GLubyte * cv3 = stackalloc GLubyte[4];

            cv[0] = cv0;
            cv[1] = cv1;
            cv[2] = cv2;
            cv[3] = cv3;
            GLubyte **testcolor = stackalloc GLubyte *[2];
            GLubyte * tc0       = stackalloc GLubyte[3];
            GLubyte * tc1       = stackalloc GLubyte[3];

            testcolor[0] = tc0;
            testcolor[1] = tc1;

            if (((bestcolor[0][0] & 0xf8) << 8 | (bestcolor[0][1] & 0xfc) << 3 | bestcolor[0][2] >> 3) <
                ((bestcolor[1][0] & 0xf8) << 8 | (bestcolor[1][1] & 0xfc) << 3 | bestcolor[1][2] >> 3))
            {
                testcolor[0][0] = bestcolor[0][0];
                testcolor[0][1] = bestcolor[0][1];
                testcolor[0][2] = bestcolor[0][2];
                testcolor[1][0] = bestcolor[1][0];
                testcolor[1][1] = bestcolor[1][1];
                testcolor[1][2] = bestcolor[1][2];
            }
            else
            {
                testcolor[1][0] = bestcolor[0][0];
                testcolor[1][1] = bestcolor[0][1];
                testcolor[1][2] = bestcolor[0][2];
                testcolor[0][0] = bestcolor[1][0];
                testcolor[0][1] = bestcolor[1][1];
                testcolor[0][2] = bestcolor[1][2];
            }

            for (i = 0; i < 3; i++)
            {
                cv[0][i] = testcolor[0][i];
                cv[1][i] = testcolor[1][i];
                cv[2][i] = (byte)((testcolor[0][i] * 2 + testcolor[1][i]) / 3);
                cv[3][i] = (byte)((testcolor[0][i] + testcolor[1][i] * 2) / 3);
            }

            blockerrlin[0][0] = 0;
            blockerrlin[0][1] = 0;
            blockerrlin[0][2] = 0;
            blockerrlin[1][0] = 0;
            blockerrlin[1][1] = 0;
            blockerrlin[1][2] = 0;

            nrcolor[0] = 0;
            nrcolor[1] = 0;

            for (j = 0; j < numypixels; j++)
            {
                for (i = 0; i < numxpixels; i++)
                {
                    var   pixerrorbest = 0xffffffff;
                    GLint colors;
                    for (colors = 0; colors < 4; colors++)
                    {
                        var colordist   = srccolors[j][i][0] - (cv[colors][0]);
                        var pixerror    = (uint)(colordist * colordist * Redweight);
                        var pixerrorred = (uint)colordist;
                        colordist = srccolors[j][i][1] - (cv[colors][1]);
                        pixerror += (uint)(colordist * colordist * Greenweight);
                        var pixerrorgreen = (uint)colordist;
                        colordist = srccolors[j][i][2] - (cv[colors][2]);
                        pixerror += (uint)(colordist * colordist * Blueweight);
                        var pixerrorblue = (uint)colordist;
                        if (pixerror < pixerrorbest)
                        {
                            enc                  = (byte)colors;
                            pixerrorbest         = pixerror;
                            pixerrorcolorbest[0] = (int)pixerrorred;
                            pixerrorcolorbest[1] = (int)pixerrorgreen;
                            pixerrorcolorbest[2] = (int)pixerrorblue;
                        }
                    }
                    GLint z;
                    if (enc == 0)
                    {
                        for (z = 0; z < 3; z++)
                        {
                            blockerrlin[0][z] += 3 * pixerrorcolorbest[z];
                        }
                        nrcolor[0] += 3;
                    }
                    else if (enc == 2)
                    {
                        for (z = 0; z < 3; z++)
                        {
                            blockerrlin[0][z] += 2 * pixerrorcolorbest[z];
                        }
                        nrcolor[0] += 2;
                        for (z = 0; z < 3; z++)
                        {
                            blockerrlin[1][z] += 1 * pixerrorcolorbest[z];
                        }
                        nrcolor[1] += 1;
                    }
                    else if (enc == 3)
                    {
                        for (z = 0; z < 3; z++)
                        {
                            blockerrlin[0][z] += 1 * pixerrorcolorbest[z];
                        }
                        nrcolor[0] += 1;
                        for (z = 0; z < 3; z++)
                        {
                            blockerrlin[1][z] += 2 * pixerrorcolorbest[z];
                        }
                        nrcolor[1] += 2;
                    }
                    else if (enc == 1)
                    {
                        for (z = 0; z < 3; z++)
                        {
                            blockerrlin[1][z] += 3 * pixerrorcolorbest[z];
                        }
                        nrcolor[1] += 3;
                    }
                }
            }
            if (nrcolor[0] == 0)
            {
                nrcolor[0] = 1;
            }
            if (nrcolor[1] == 0)
            {
                nrcolor[1] = 1;
            }
            for (j = 0; j < 2; j++)
            {
                for (i = 0; i < 3; i++)
                {
                    var newvalue = testcolor[j][i] + blockerrlin[j][i] / nrcolor[j];
                    if (newvalue <= 0)
                    {
                        testcolor[j][i] = 0;
                    }
                    else if (newvalue >= 255)
                    {
                        testcolor[j][i] = 255;
                    }
                    else
                    {
                        testcolor[j][i] = (byte)newvalue;
                    }
                }
            }

            if ((Math.Abs(testcolor[0][0] - testcolor[1][0]) < 8) &&
                (Math.Abs(testcolor[0][1] - testcolor[1][1]) < 4) &&
                (Math.Abs(testcolor[0][2] - testcolor[1][2]) < 8))
            {
                var coldiffred   = (byte)Math.Abs(testcolor[0][0] - testcolor[1][0]);
                var coldiffgreen = (byte)(2 * Math.Abs(testcolor[0][1] - testcolor[1][1]));
                var coldiffblue  = (byte)Math.Abs(testcolor[0][2] - testcolor[1][2]);
                var coldiffmax   = coldiffred;
                if (coldiffmax < coldiffgreen)
                {
                    coldiffmax = coldiffgreen;
                }
                if (coldiffmax < coldiffblue)
                {
                    coldiffmax = coldiffblue;
                }
                if (coldiffmax > 0)
                {
                    GLubyte factor;
                    if (coldiffmax > 4)
                    {
                        factor = 2;
                    }
                    else if (coldiffmax > 2)
                    {
                        factor = 3;
                    }
                    else
                    {
                        factor = 4;
                    }
                    GLubyte ind0;
                    GLubyte ind1;
                    if (testcolor[1][1] >= testcolor[0][1])
                    {
                        ind1 = 1;
                        ind0 = 0;
                    }
                    else
                    {
                        ind1 = 0;
                        ind0 = 1;
                    }
                    if ((testcolor[ind1][1] + factor * coldiffgreen) <= 255)
                    {
                        testcolor[ind1][1] += (byte)(factor * coldiffgreen);
                    }
                    else
                    {
                        testcolor[ind1][1] = 255;
                    }
                    if ((testcolor[ind1][0] - testcolor[ind0][1]) > 0)
                    {
                        if ((testcolor[ind1][0] + factor * coldiffred) <= 255)
                        {
                            testcolor[ind1][0] += (byte)(factor * coldiffred);
                        }
                        else
                        {
                            testcolor[ind1][0] = 255;
                        }
                    }
                    else
                    {
                        if ((testcolor[ind0][0] + factor * coldiffred) <= 255)
                        {
                            testcolor[ind0][0] += (byte)(factor * coldiffred);
                        }
                        else
                        {
                            testcolor[ind0][0] = 255;
                        }
                    }
                    if ((testcolor[ind1][2] - testcolor[ind0][2]) > 0)
                    {
                        if ((testcolor[ind1][2] + factor * coldiffblue) <= 255)
                        {
                            testcolor[ind1][2] += (byte)(factor * coldiffblue);
                        }
                        else
                        {
                            testcolor[ind1][2] = 255;
                        }
                    }
                    else
                    {
                        if ((testcolor[ind0][2] + factor * coldiffblue) <= 255)
                        {
                            testcolor[ind0][2] += (byte)(factor * coldiffblue);
                        }
                        else
                        {
                            testcolor[ind0][2] = 255;
                        }
                    }
                }
            }

            if (((testcolor[0][0] & 0xf8) << 8 | (testcolor[0][1] & 0xfc) << 3 | testcolor[0][2] >> 3) <
                ((testcolor[1][0] & 0xf8) << 8 | (testcolor[1][1] & 0xfc) << 3 | testcolor[1][2]) >> 3)
            {
                for (i = 0; i < 3; i++)
                {
                    bestcolor[0][i] = testcolor[0][i];
                    bestcolor[1][i] = testcolor[1][i];
                }
            }
            else
            {
                for (i = 0; i < 3; i++)
                {
                    bestcolor[0][i] = testcolor[1][i];
                    bestcolor[1][i] = testcolor[0][i];
                }
            }
        }
Ejemplo n.º 6
0
        private static void Storedxtencodedblock(GLubyte *blkaddr, GLubyte ***srccolors, GLubyte **bestcolor,
                                                 GLint numxpixels, GLint numypixels, GLuint type, GLboolean haveAlpha)
        {
            GLint     i, j, colors;
            GLuint    pixerror, pixerrorbest;
            GLint     colordist;
            GLuint    bits = 0, bits2 = 0;
            GLubyte   enc = 0;
            GLubyte **cv  = stackalloc GLubyte *[4];
            GLubyte * cv0 = stackalloc GLubyte[4];
            GLubyte * cv1 = stackalloc GLubyte[4];
            GLubyte * cv2 = stackalloc GLubyte[4];
            GLubyte * cv3 = stackalloc GLubyte[4];

            cv[0] = cv0;
            cv[1] = cv1;
            cv[2] = cv2;
            cv[3] = cv3;

            bestcolor[0][0] = (byte)(bestcolor[0][0] & 0xf8);
            bestcolor[0][1] = (byte)(bestcolor[0][1] & 0xfc);
            bestcolor[0][2] = (byte)(bestcolor[0][2] & 0xf8);
            bestcolor[1][0] = (byte)(bestcolor[1][0] & 0xf8);
            bestcolor[1][1] = (byte)(bestcolor[1][1] & 0xfc);
            bestcolor[1][2] = (byte)(bestcolor[1][2] & 0xf8);

            var color0 = (ushort)(bestcolor[0][0] << 8 | bestcolor[0][1] << 3 | bestcolor[0][2] >> 3);
            var color1 = (ushort)(bestcolor[1][0] << 8 | bestcolor[1][1] << 3 | bestcolor[1][2] >> 3);

            if (color0 < color1)
            {
                var tempcolor = color0;
                color0 = color1;
                color1 = tempcolor;
                var colorptr = bestcolor[0];
                bestcolor[0] = bestcolor[1];
                bestcolor[1] = colorptr;
            }


            for (i = 0; i < 3; i++)
            {
                cv[0][i] = bestcolor[0][i];
                cv[1][i] = bestcolor[1][i];
                cv[2][i] = (byte)((bestcolor[0][i] * 2 + bestcolor[1][i]) / 3);
                cv[3][i] = (byte)((bestcolor[0][i] + bestcolor[1][i] * 2) / 3);
            }

            uint testerror = 0;

            for (j = 0; j < numypixels; j++)
            {
                for (i = 0; i < numxpixels; i++)
                {
                    pixerrorbest = 0xffffffff;
                    for (colors = 0; colors < 4; colors++)
                    {
                        colordist = srccolors[j][i][0] - cv[colors][0];
                        pixerror  = (uint)(colordist * colordist * Redweight);
                        colordist = (srccolors[j][i][1] - cv[colors][1]);
                        pixerror += (uint)(colordist * colordist * Greenweight);
                        colordist = srccolors[j][i][2] - cv[colors][2];
                        pixerror += (uint)(colordist * colordist * Blueweight);
                        if (pixerror < pixerrorbest)
                        {
                            pixerrorbest = pixerror;
                            enc          = (byte)colors;
                        }
                    }
                    testerror += pixerrorbest;
                    bits      |= (uint)(enc << (2 * (j * 4 + i)));
                }
            }
            for (i = 0; i < 3; i++)
            {
                cv[2][i] = (byte)((bestcolor[0][i] + bestcolor[1][i]) / 2);

                /* this isn't used. Looks like the black color constant can only be used
                 * with RGB_DXT1 if I read the spec correctly (note though that the radeon gpu disagrees,
                 * it will decode 3 to black even with DXT3/5), and due to how the color searching works
                 * it won't get used even then */
                cv[3][i] = 0;
            }
            uint testerror2 = 0;

            for (j = 0; j < numypixels; j++)
            {
                for (i = 0; i < numxpixels; i++)
                {
                    pixerrorbest = 0xffffffff;
                    if ((type == GlCompressedRgbaS3TcDxt1Ext) && (srccolors[j][i][3] <= Alphacut))
                    {
                        enc          = 3;
                        pixerrorbest = 0; /* don't calculate error */
                    }
                    else
                    {
                        /* we're calculating the same what we have done already for colors 0-1 above... */
                        for (colors = 0; colors < 3; colors++)
                        {
                            colordist = srccolors[j][i][0] - cv[colors][0];
                            pixerror  = (uint)(colordist * colordist * Redweight);
                            colordist = srccolors[j][i][1] - cv[colors][1];
                            pixerror += (uint)(colordist * colordist * Greenweight);
                            colordist = srccolors[j][i][2] - cv[colors][2];
                            pixerror += (uint)(colordist * colordist * Blueweight);
                            if (pixerror < pixerrorbest)
                            {
                                pixerrorbest = pixerror;
                                /* need to exchange colors later */
                                if (colors > 1)
                                {
                                    enc = (byte)colors;
                                }
                                else
                                {
                                    enc = (byte)(colors ^ 1);
                                }
                            }
                        }
                    }
                    testerror2 += pixerrorbest;
                    bits2      |= (uint)(enc << (2 * (j * 4 + i)));
                }
            }


            /* finally we're finished, write back colors and bits */
            if ((testerror > testerror2) || (haveAlpha != GlFalse))
            {
                *blkaddr++ = (byte)(color1 & 0xff);
                *blkaddr++ = (byte)(color1 >> 8);
                *blkaddr++ = (byte)(color0 & 0xff);
                *blkaddr++ = (byte)(color0 >> 8);
                *blkaddr++ = (byte)(bits2 & 0xff);
                *blkaddr++ = (byte)((bits2 >> 8) & 0xff);
                *blkaddr++ = (byte)((bits2 >> 16) & 0xff);
                *blkaddr   = (byte)(bits2 >> 24);
            }
            else
            {
                *blkaddr++ = (byte)(color0 & 0xff);
                *blkaddr++ = (byte)(color0 >> 8);
                *blkaddr++ = (byte)(color1 & 0xff);
                *blkaddr++ = (byte)(color1 >> 8);
                *blkaddr++ = (byte)(bits & 0xff);
                *blkaddr++ = (byte)((bits >> 8) & 0xff);
                *blkaddr++ = (byte)((bits >> 16) & 0xff);
                *blkaddr   = (byte)(bits >> 24);
            }
        }