Esempio n. 1
0
        private static byte[] DxtEncode(Bitmap img, bool dxt1, DxtAlphaMode dxtAlpha)
        {
            int         width       = img.Width;
            int         height      = img.Height;
            PixelFormat pixelFormat = img.PixelFormat;
            BitmapData  imgData     = img.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, pixelFormat);

            byte[] data = new byte[imgData.Height * imgData.Stride];
            Marshal.Copy(imgData.Scan0, data, 0, data.Length);
            img.UnlockBits(imgData);

            return(DxtEncode(data, width, height, dxtAlpha, pixelFormat));
        }
Esempio n. 2
0
        private static byte[] DxtEncode(byte[] data, int width, int height, DxtAlphaMode dxtAlpha = DxtAlphaMode.DXT5, PixelFormat pixelFormat = PixelFormat.Format32bppArgb)
        {
            int bpp = 3;

            if (pixelFormat == PixelFormat.Format32bppArgb)
            {
                bpp = 4;
            }

            byte[] Out       = new byte[((width / 4 * (height / 4)) * (dxtAlpha != DxtAlphaMode.None ? 16 : 8))];
            int    outOffset = 0;

            for (int tileY = 0; tileY < height / 4; tileY++)
            {
                for (int tileX = 0; tileX < width / 4; tileX++)
                {
                    byte[] block = new byte[8];

                    //Calculo de Luminância mín/máx
                    byte minLuma = 0xff;
                    byte maxLuma = 0;

                    byte minR = 0, maxR = 0;
                    byte minG = 0, maxG = 0;
                    byte minB = 0, maxB = 0;

                    for (int y = 0; y < 4; y++)
                    {
                        for (int x = 0; x < 4; x++)
                        {
                            int offset = ((tileX * 4) + x + (((tileY * 4) + y) * width)) * bpp;

                            byte r = data[offset + 2];
                            byte g = data[offset + 1];
                            byte b = data[offset];

                            byte luma = (byte)(0.257f * r + 0.504f * g + 0.098f * b + 16);
                            if (luma < minLuma)
                            {
                                minR = r;
                                minG = g;
                                minB = b;

                                minLuma = luma;
                            }
                            if (luma > maxLuma)
                            {
                                maxR = r;
                                maxG = g;
                                maxB = b;

                                maxLuma = luma;
                            }
                        }
                    }

                    block[2] = (byte)((minB >> 3) | ((minG & 0x1C) << 3));
                    block[3] = (byte)(((minG & 0xE0) >> 5) | (minR & 0xF8));
                    block[0] = (byte)((maxB >> 3) | ((maxG & 0x1C) << 3));
                    block[1] = (byte)(((maxG & 0xE0) >> 5) | (maxR & 0xF8));

                    Color[] pixelColor = new Color[4];
                    ushort  c0         = Read16(block, 0);
                    ushort  c1         = Read16(block, 2);
                    pixelColor[0] = GetColorFromBgr565(c0);
                    pixelColor[1] = GetColorFromBgr565(c1);
                    pixelColor[2] = ProcessDxt1ColorChannel(2, c0, c1, true);
                    pixelColor[3] = ProcessDxt1ColorChannel(3, c0, c1, true);

                    for (int y = 0; y < 4; y++)
                    {
                        for (int x = 0; x < 4; x++)
                        {
                            int imageOffset = ((tileX * 4) + x + (((tileY * 4) + y) * width)) * bpp;

                            byte r = data[imageOffset + 2];
                            byte g = data[imageOffset + 1];
                            byte b = data[imageOffset];

                            int luma = (int)(0.257f * r + 0.504f * g + 0.098f * b + 16);

                            int minDiff = 0xff;
                            int index   = 0;
                            for (int i = 0; i < 4; i++)
                            {
                                int testLuma = (int)(0.257f * pixelColor[i].R + 0.504f * pixelColor[i].G +
                                                     0.098f * pixelColor[i].B + 16);
                                int diff = Math.Abs(testLuma - luma);
                                if (diff < minDiff)
                                {
                                    minDiff = diff;
                                    index   = i;
                                }
                            }

                            block[4 + y] |= (byte)(index << (x * 2));
                        }
                    }

                    byte[] alphaBlock = new byte[8];
                    if (dxtAlpha == DxtAlphaMode.DXT3)
                    {
                        for (int y = 0; y < 4; y++)
                        {
                            for (int x = 0; x < 4; x++)
                            {
                                int imageOffset = ((tileX * 4) + x + (((tileY * 4) + y) * width)) * bpp;

                                byte a = (byte)(data[imageOffset + 3] >> 4);

                                alphaBlock[(y * 2) + (x / 2)] |= (byte)(a << ((x % 2) * 4));
                            }
                        }

                        Buffer.BlockCopy(alphaBlock, 0, Out, outOffset, alphaBlock.Length);
                        outOffset += alphaBlock.Length;
                    }
                    else if (dxtAlpha == DxtAlphaMode.DXT5)
                    {
                        byte minAlpha = 0xff;
                        byte maxAlpha = 0;

                        for (int y = 0; y < 4; y++)
                        {
                            for (int x = 0; x < 4; x++)
                            {
                                int offset = ((tileX * 4) + x + (((tileY * 4) + y) * width)) * bpp;

                                byte a = data[offset + 3];

                                if (a < minAlpha)
                                {
                                    minAlpha = a;
                                }
                                if (a > maxAlpha)
                                {
                                    maxAlpha = a;
                                }
                            }
                        }

                        byte[] alpha = new byte[8];
                        alpha[0]      = minAlpha;
                        alpha[1]      = maxAlpha;
                        alphaBlock[0] = alpha[0];
                        alphaBlock[1] = alpha[1];
                        Dxt5CalculateAlphas(alpha);

                        uint alphaVal         = 0;
                        byte shift            = 0;
                        int  alphaBlockOffset = 2;
                        for (int y = 0; y < 4; y++)
                        {
                            for (int x = 0; x < 4; x++)
                            {
                                int imageOffset = ((tileX * 4) + x + (((tileY * 4) + y) * width)) * bpp;

                                byte a = data[imageOffset + 3];

                                int  minDiff = 0xff;
                                byte index   = 0;
                                for (int i = 0; i < 8; i++)
                                {
                                    int diff = Math.Abs(alpha[i] - a);
                                    if (diff < minDiff)
                                    {
                                        minDiff = diff;
                                        index   = (byte)i;
                                    }
                                }

                                alphaVal |= (uint)((index & 7) << shift);
                                shift    += 3;
                                if (shift == 24)
                                {
                                    Buffer.BlockCopy(BitConverter.GetBytes(alphaVal), 0, alphaBlock, alphaBlockOffset, 3);
                                    alphaVal          = 0;
                                    shift             = 0;
                                    alphaBlockOffset += 3;
                                }
                            }
                        }

                        Buffer.BlockCopy(alphaBlock, 0, Out, outOffset, alphaBlock.Length);
                        outOffset += alphaBlock.Length;
                    }

                    Buffer.BlockCopy(block, 0, Out, outOffset, block.Length);
                    outOffset += block.Length;
                }
            }
            return(Out);
        }