Пример #1
0
        //http://wiki.xentax.com/index.php/Source_VTF
        /// <summary>
        /// Parser VTF format
        /// <br>Supported versions: 7.1 - 7.5 (maybe 7.0)</br>
        /// </summary>
        /// <param name="stream">Stream of input file</param>
        /// <param name="FileName">Name of input file (optional)</param>
        public VTFFile(Stream stream, String FileName = "")
        {
            using (uReader FileStream = new uReader(stream))
            {
                String TempHeader = FileStream.ReadFixedLengthString(Encoding.ASCII, 4);
                if (TempHeader != VTFHeader)
                {
                    throw new Exception("Invalid VTF header. Expected '" + VTFHeader + "', got '" + TempHeader + "'.");
                }

                Header = new VTFHeader();

                UInt32  VersionMajor = FileStream.ReadUInt32();
                UInt32  VersionMinor = FileStream.ReadUInt32();
                Decimal Version      = VersionMajor + (VersionMinor / 10m); // e.g. 7.3
                Header.Version = Version;

                UInt32 headerSize = FileStream.ReadUInt32();
                Width  = FileStream.ReadUInt16();
                Height = FileStream.ReadUInt16();

                Header.Flags = (VTFImageFlag)FileStream.ReadUInt32();

                UInt16 NumFrames  = FileStream.ReadUInt16();
                UInt16 FirstFrame = FileStream.ReadUInt16();

                FileStream.ReadBytes(4); // padding

                Header.Reflectivity = FileStream.ReadVector3D(false);

                FileStream.ReadBytes(4); // padding

                Header.BumpmapScale = FileStream.ReadSingle();

                VTFImageFormat HighResImageFormat = (VTFImageFormat)FileStream.ReadUInt32();
                Byte           MipmapCount        = FileStream.ReadByte();
                VTFImageFormat LowResImageFormat  = (VTFImageFormat)FileStream.ReadUInt32();
                Byte           LowResWidth        = FileStream.ReadByte();
                Byte           LowResHeight       = FileStream.ReadByte();

                UInt16 Depth        = 1;
                UInt32 NumResources = 0;

                if (Version >= 7.2m)
                {
                    Depth = FileStream.ReadUInt16();
                }
                if (Version >= 7.3m)
                {
                    FileStream.ReadBytes(3);
                    NumResources = FileStream.ReadUInt32();
                    FileStream.ReadBytes(8);
                }

                Int32 NumFaces = 1;
                if (Header.Flags.HasFlag(VTFImageFlag.TEXTUREFLAGS_ENVMAP))
                {
                    NumFaces = Version < 7.5m && FirstFrame != 0xFFFF ? 7 : 6;
                }

                VTFImageFormatInfo HighResFormatInfo = VTFImageFormatInfo.FromFormat(HighResImageFormat);
                VTFImageFormatInfo LowResFormatInfo  = VTFImageFormatInfo.FromFormat(LowResImageFormat);

                Int32 ThumbnailSize = LowResImageFormat == VTFImageFormat.IMAGE_FORMAT_NONE ? 0 : LowResFormatInfo.GetSize(LowResWidth, LowResHeight);

                UInt32 ThumbnailOffset = headerSize;
                Int64  DataOffset      = headerSize + ThumbnailSize;

                Resources = new VTFResource[NumResources];
                for (Int32 i = 0; i < NumResources; i++)
                {
                    VTFResourceType type     = (VTFResourceType)FileStream.ReadUInt32();
                    UInt32          DataSize = FileStream.ReadUInt32();
                    switch (type)
                    {
                    case VTFResourceType.LowResImage:
                        // Low res image
                        ThumbnailOffset = DataSize;
                        break;

                    case VTFResourceType.Image:
                        // Regular image
                        DataOffset = DataSize;
                        break;

                    case VTFResourceType.Sheet:
                    case VTFResourceType.CRC:
                    case VTFResourceType.TextureLodSettings:
                    case VTFResourceType.TextureSettingsEx:
                    case VTFResourceType.KeyValueData:
                        // todo
                        Resources[i] = new VTFResource
                        {
                            Type = type,
                            Data = DataSize
                        };
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(type), (uint)type, "Unknown resource type");
                    }
                }

                if (LowResImageFormat != VTFImageFormat.IMAGE_FORMAT_NONE)
                {
                    FileStream.BaseStream.Position = ThumbnailOffset;
                    Int32 thumbSize = LowResFormatInfo.GetSize(LowResWidth, LowResHeight);
                    LowResImage = new VTFImage
                    {
                        Format = LowResImageFormat,
                        Width  = LowResWidth,
                        Height = LowResHeight,
                        Data   = FileStream.ReadBytes(thumbSize)
                    };
                }

                Boolean ConvertToBGRA32 = true;
                Boolean hasAlpha        = true;
                switch (HighResImageFormat)
                {
                //Unity support this formats natively
                case VTFImageFormat.IMAGE_FORMAT_A8:
                case VTFImageFormat.IMAGE_FORMAT_ABGR8888:
                case VTFImageFormat.IMAGE_FORMAT_ARGB8888:
                case VTFImageFormat.IMAGE_FORMAT_BGRA4444:
                case VTFImageFormat.IMAGE_FORMAT_DXT1_ONEBITALPHA:
                case VTFImageFormat.IMAGE_FORMAT_DXT3:
                case VTFImageFormat.IMAGE_FORMAT_DXT5:
                case VTFImageFormat.IMAGE_FORMAT_RGBA8888:
                case VTFImageFormat.IMAGE_FORMAT_BGRA8888:
                case VTFImageFormat.IMAGE_FORMAT_BGRX8888:
                case VTFImageFormat.IMAGE_FORMAT_RGBA16161616F:
                case VTFImageFormat.IMAGE_FORMAT_RGBA16161616:
                    ConvertToBGRA32 = false;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_BGR565:
                case VTFImageFormat.IMAGE_FORMAT_RGB565:
                case VTFImageFormat.IMAGE_FORMAT_DXT1:
                case VTFImageFormat.IMAGE_FORMAT_RGB888:
                    hasAlpha        = false;
                    ConvertToBGRA32 = false;
                    break;
                }

                FileStream.BaseStream.Position = DataOffset;
                Frames = new Texture2D[NumFrames, NumFaces];
                List <Byte>[] FramesData = new List <Byte> [NumFrames];
                for (Int32 MipLevel = MipmapCount - 1; MipLevel >= 0; MipLevel--)
                {
                    for (Int32 FrameID = 0; FrameID < NumFrames; FrameID++)
                    {
                        if (FramesData[FrameID] == null)
                        {
                            FramesData[FrameID] = new List <Byte>();
                        }

                        for (Int32 FaceID = 0; FaceID < NumFaces; FaceID++)
                        {
                            for (Int32 SliceID = 0; SliceID < Depth; SliceID++)
                            {
                                Int32 Wid      = GetMipSize(Width, MipLevel);
                                Int32 Hei      = GetMipSize(Height, MipLevel);
                                Int32 DataSize = HighResFormatInfo.GetSize(Wid, Hei);

                                if (ConvertToBGRA32)
                                {
                                    FramesData[FrameID].InsertRange(0, VTFImageFormatInfo.FromFormat(HighResImageFormat).ConvertToBgra32(FileStream.ReadBytes(DataSize), Wid, Hei));
                                }
                                else
                                {
                                    FramesData[FrameID].InsertRange(0, FileStream.ReadBytes(DataSize));
                                }
                            }
                        }
                    }
                }

                TextureFormat InternalFormat = TextureFormat.BGRA32;
                Boolean       needCompress   = false;
                switch (HighResImageFormat)
                {
                case VTFImageFormat.IMAGE_FORMAT_A8:
                    InternalFormat = TextureFormat.Alpha8;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_ABGR8888:
                case VTFImageFormat.IMAGE_FORMAT_ARGB8888:
                    InternalFormat = TextureFormat.ARGB32;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_BGR565:
                case VTFImageFormat.IMAGE_FORMAT_RGB565:
                    InternalFormat = TextureFormat.RGB565;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_BGRA4444:
                    InternalFormat = TextureFormat.RGBA4444;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_DXT1:
                case VTFImageFormat.IMAGE_FORMAT_DXT1_ONEBITALPHA:
                    InternalFormat = TextureFormat.DXT1;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_DXT3:
                case VTFImageFormat.IMAGE_FORMAT_DXT5:
                    InternalFormat = TextureFormat.DXT5;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_RGB888:
                    InternalFormat = TextureFormat.RGB24;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_RGBA8888:
                    InternalFormat = TextureFormat.RGBA32;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_RGBA16161616F:
                case VTFImageFormat.IMAGE_FORMAT_RGBA16161616:
                    InternalFormat = TextureFormat.RGBAHalf;
                    break;

                default:
                    //needCompress = true;
                    break;
                }

                Boolean mipmaps = MipmapCount > 1;
                for (Int32 FrameID = 0; FrameID < NumFrames; FrameID++)
                {
                    for (Int32 FaceID = 0; FaceID < NumFaces; FaceID++)
                    {
                        Frames[FrameID, FaceID]      = new Texture2D(Width, Height, InternalFormat, mipmaps);
                        Frames[FrameID, FaceID].name = FileName;
                        Frames[FrameID, FaceID].alphaIsTransparency = hasAlpha;
                        Frames[FrameID, FaceID].LoadRawTextureData(FramesData[FrameID].ToArray());
                        Frames[FrameID, FaceID].Apply();

                        if (needCompress)
                        {
                            Frames[FrameID, FaceID].Compress(false);
                            Debug.LogWarning(FileName + " compressed!");
                        }
                    }
                }
            }
        }
Пример #2
0
 /// <summary>
 /// Convert the native format data to a standard 32-bit bgra8888 format.
 /// </summary>
 /// <returns>The data in bgra8888 format.</returns>
 public Byte[] GetBgra32Data()
 {
     return(VTFImageFormatInfo.FromFormat(Format).ConvertToBgra32(Data, Width, Height));
 }