Beispiel #1
0
        public static byte[] Decompress(byte[] Input, int Width, int Height, bool Alpha)
        {
            byte[] Output = new byte[Width * Height * 4];

            byte[] comp = new byte[4] {
                0xFF, 0xFF, 0xFF, 0xFF
            };

            int bpp = (int)STGenericTexture.GetBytesPerPixel(TEX_FORMAT.R4G4_UNORM);

            for (int Y = 0; Y < Height; Y++)
            {
                for (int X = 0; X < Width; X++)
                {
                    int InputOffset  = (Y * Width + X) * bpp;
                    int OutputOffset = (Y * Width + X) * 4;

                    int pixel = 0;
                    for (int i = 0; i < bpp; i++)
                    {
                        pixel |= Input[InputOffset + i] << (8 * i);
                    }

                    comp[0] = (byte)((pixel & 0xF) * 17);
                    comp[1] = (byte)(((pixel & 0xF0) >> 4) * 17);

                    Output[OutputOffset + 0] = comp[0];
                    Output[OutputOffset + 1] = comp[1];
                    Output[OutputOffset + 2] = comp[2];
                    Output[OutputOffset + 3] = comp[3];
                }
            }

            return(Output);
        }
        public byte[] GenerateMipsAndCompress(Bitmap bitmap, TEX_FORMAT Format, float alphaRef = 0.5f)
        {
            byte[] DecompressedData = BitmapExtension.ImageToByte(bitmap);
            DecompressedData = ConvertBgraToRgba(DecompressedData);

            Bitmap Image = BitmapExtension.GetBitmap(DecompressedData, bitmap.Width, bitmap.Height);

            List <byte[]> mipmaps = new List <byte[]>();

            mipmaps.Add(STGenericTexture.CompressBlock(DecompressedData,
                                                       bitmap.Width, bitmap.Height, Format, alphaRef));

            for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
            {
                if (Image.Width / 2 > 0 && Image.Height / 2 > 0)
                {
                    Image = BitmapExtension.Resize(Image, Image.Width / 2, Image.Height / 2);
                    mipmaps.Add(STGenericTexture.CompressBlock(BitmapExtension.ImageToByte(Image),
                                                               Image.Width, Image.Height, Format, alphaRef));
                }
            }
            Image.Dispose();

            return(Utils.CombineByteArray(mipmaps.ToArray()));
        }
Beispiel #3
0
        public STGenericTexture CreateGenericTexture(string Path)
        {
            STGenericTexture tex = new STGenericTexture();

            switch (System.IO.Path.GetExtension(Path))
            {
            case ".dds":
                tex.LoadDDS(Path);
                break;

            case ".tga":
                tex.LoadTGA(Path);
                break;

            default:
                tex.LoadBitmap(Path);
                break;
            }
            return(tex);
        }
        public static byte[] GenerateMipsAndCompress(Bitmap bitmap, uint MipCount, TEX_FORMAT Format, float alphaRef = 0.5f, STCompressionMode CompressionMode = STCompressionMode.Fast)
        {
            byte[] DecompressedData = BitmapExtension.ImageToByte(bitmap);
            DecompressedData = ConvertBgraToRgba(DecompressedData);

            Bitmap Image = BitmapExtension.GetBitmap(DecompressedData, bitmap.Width, bitmap.Height);

            List <byte[]> mipmaps = new List <byte[]>();

            for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
            {
                int width  = Math.Max(1, bitmap.Width >> mipLevel);
                int height = Math.Max(1, bitmap.Height >> mipLevel);

                Image = BitmapExtension.Resize(Image, width, height);
                mipmaps.Add(STGenericTexture.CompressBlock(BitmapExtension.ImageToByte(Image),
                                                           Image.Width, Image.Height, Format, alphaRef, CompressionMode));
            }
            Image.Dispose();

            return(Utils.CombineByteArray(mipmaps.ToArray()));
        }
        public static byte[] GetImageData(STGenericTexture texture, byte[] ImageData, int ArrayLevel, int MipLevel, int target = 1)
        {
            uint bpp       = STGenericTexture.GetBytesPerPixel(texture.Format);
            uint blkWidth  = STGenericTexture.GetBlockWidth(texture.Format);
            uint blkHeight = STGenericTexture.GetBlockHeight(texture.Format);
            uint blkDepth  = STGenericTexture.GetBlockDepth(texture.Format);

            uint blockHeight     = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(texture.Height, blkHeight));
            uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;

            uint Pitch         = 0;
            uint DataAlignment = 512;
            uint TileMode      = 0;

            int linesPerBlockHeight = (1 << (int)BlockHeightLog2) * 8;

            uint ArrayOffset = 0;

            for (int arrayLevel = 0; arrayLevel < texture.ArrayCount; arrayLevel++)
            {
                uint SurfaceSize      = 0;
                int  blockHeightShift = 0;

                List <uint> MipOffsets = new List <uint>();

                for (int mipLevel = 0; mipLevel < texture.MipCount; mipLevel++)
                {
                    uint width  = (uint)Math.Max(1, texture.Width >> mipLevel);
                    uint height = (uint)Math.Max(1, texture.Height >> mipLevel);
                    uint depth  = (uint)Math.Max(1, texture.Depth >> mipLevel);

                    uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;

                    if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight)
                    {
                        blockHeightShift += 1;
                    }


                    uint width__  = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth);
                    uint height__ = TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight);

                    //Calculate the mip size instead
                    byte[] AlignedData = new byte[(TegraX1Swizzle.round_up(SurfaceSize, DataAlignment) - SurfaceSize)];
                    SurfaceSize += (uint)AlignedData.Length;
                    MipOffsets.Add(SurfaceSize);

                    //Get the first mip offset and current one and the total image size
                    int msize = (int)((MipOffsets[0] + ImageData.Length - MipOffsets[mipLevel]) / texture.ArrayCount);

                    byte[] data_ = Utils.SubArray(ImageData, ArrayOffset + MipOffsets[mipLevel], (uint)msize);

                    try
                    {
                        Pitch        = TegraX1Swizzle.round_up(width__ * bpp, 64);
                        SurfaceSize += Pitch * TegraX1Swizzle.round_up(height__, Math.Max(1, blockHeight >> blockHeightShift) * 8);

                        Console.WriteLine($"{width} {height} {blkWidth} {blkHeight} {target} {bpp} {TileMode} {(int)Math.Max(0, BlockHeightLog2 - blockHeightShift)} {data_.Length}");
                        byte[] result = TegraX1Swizzle.deswizzle(width, height, depth, blkWidth, blkHeight, blkDepth, target, bpp, TileMode, (int)Math.Max(0, BlockHeightLog2 - blockHeightShift), data_);
                        //Create a copy and use that to remove uneeded data
                        byte[] result_ = new byte[size];
                        Array.Copy(result, 0, result_, 0, size);
                        result = null;

                        if (ArrayLevel == arrayLevel && MipLevel == mipLevel)
                        {
                            return(result_);
                        }
                    }
                    catch (Exception e)
                    {
                        System.Windows.Forms.MessageBox.Show($"Failed to swizzle texture {texture.Text}!");
                        Console.WriteLine(e);

                        return(new byte[0]);
                    }
                }

                ArrayOffset += (uint)(ImageData.Length / texture.ArrayCount);
            }
            return(new byte[0]);
        }
        public static List <uint[]> GenerateMipSizes(TEX_FORMAT Format, uint Width, uint Height, uint Depth, uint SurfaceCount, uint MipCount, uint ImageSize)
        {
            List <uint[]> MipMapSizes = new List <uint[]>();

            uint bpp       = STGenericTexture.GetBytesPerPixel(Format);
            uint blkWidth  = STGenericTexture.GetBlockWidth(Format);
            uint blkHeight = STGenericTexture.GetBlockHeight(Format);
            uint blkDepth  = STGenericTexture.GetBlockDepth(Format);

            uint blockHeight     = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(Height, blkHeight));
            uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;

            uint Pitch         = 0;
            uint DataAlignment = 512;

            int linesPerBlockHeight = (1 << (int)BlockHeightLog2) * 8;

            uint ArrayCount = SurfaceCount;

            uint ArrayOffset = 0;

            for (int arrayLevel = 0; arrayLevel < ArrayCount; arrayLevel++)
            {
                uint SurfaceSize      = 0;
                int  blockHeightShift = 0;

                uint[] MipOffsets = new uint[MipCount];

                for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
                {
                    uint width  = (uint)Math.Max(1, Width >> mipLevel);
                    uint height = (uint)Math.Max(1, Height >> mipLevel);
                    uint depth  = (uint)Math.Max(1, Depth >> mipLevel);

                    uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;

                    if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight)
                    {
                        blockHeightShift += 1;
                    }

                    uint width__  = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth);
                    uint height__ = TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight);

                    //Calculate the mip size instead
                    byte[] AlignedData = new byte[(TegraX1Swizzle.round_up(SurfaceSize, DataAlignment) - SurfaceSize)];
                    SurfaceSize         += (uint)AlignedData.Length;
                    MipOffsets[mipLevel] = (SurfaceSize);

                    //Get the first mip offset and current one and the total image size
                    int msize = (int)((MipOffsets[0] + ImageSize - MipOffsets[mipLevel]) / ArrayCount);

                    Pitch        = TegraX1Swizzle.round_up(width__ * bpp, 64);
                    SurfaceSize += Pitch * TegraX1Swizzle.round_up(height__, Math.Max(1, blockHeight >> blockHeightShift) * 8);
                }
                ArrayOffset += (uint)(ImageSize / ArrayCount);

                MipMapSizes.Add(MipOffsets);
            }

            return(MipMapSizes);
        }