예제 #1
0
        private static unsafe int WriteDdsHeader(ValveTextureFile vtf, int mip, byte[] buffer)
        {
            var header = new DdsHeader();

            int  blockSize;
            uint fourCC;

            switch (vtf.Header.HiResFormat)
            {
            case TextureFormat.DXT1:
                blockSize = 8;
                fourCC    = 0x31545844;
                break;

            case TextureFormat.DXT3:
                blockSize = 16;
                fourCC    = 0x33545844;
                break;

            case TextureFormat.DXT5:
                blockSize = 16;
                fourCC    = 0x35545844;
                break;

            default:
                throw new NotImplementedException();
            }

            header.dwWidth  = (uint)Math.Max(1, vtf.Header.Width >> mip);
            header.dwHeight = (uint)Math.Max(1, vtf.Header.Height >> mip);

            header.dwSize              = (uint)Marshal.SizeOf(typeof(DdsHeader));
            header.dwFlags             = DdsHeaderFlags.CAPS | DdsHeaderFlags.HEIGHT | DdsHeaderFlags.WIDTH | DdsHeaderFlags.PIXELFORMAT;
            header.dwPitchOrLinearSize = (uint)(Math.Max(1, (vtf.Header.Width + 3) / 4) * blockSize);
            header.dwDepth             = 1;
            header.dwMipMapCount       = 1;
            header.dwCaps              = DdsCaps.TEXTURE;
            header.ddspf.dwSize        = (uint)Marshal.SizeOf(typeof(DdsPixelFormat));
            header.ddspf.dwFlags       = DdsPixelFormatFlags.FOURCC;
            header.ddspf.dwFourCC      = fourCC;

            fixed(byte *bufferPtr = buffer)
            {
                var magicPtr  = (uint *)bufferPtr;
                var headerPtr = (DdsHeader *)(bufferPtr + sizeof(uint));

                *magicPtr  = 0x20534444;
                *headerPtr = header;
            }

            return((int)header.dwSize + sizeof(uint));
        }
예제 #2
0
파일: DDS.cs 프로젝트: yarligayan/libTech
        public static unsafe int WriteDdsHeader(ValveTextureFile VTF, int Mip, byte[] Buffer)
        {
            DdsHeader Header = new DdsHeader();

            int  BlockSize;
            uint FourCC;

            switch (VTF.Header.HiResFormat)
            {
            case TextureFormat.DXT1:
                BlockSize = 8;
                FourCC    = 0x31545844;
                break;

            case TextureFormat.DXT3:
                BlockSize = 16;
                FourCC    = 0x33545844;
                break;

            case TextureFormat.DXT5:
                BlockSize = 16;
                FourCC    = 0x35545844;
                break;

            default:
                throw new NotImplementedException();
            }

            Header.dwWidth  = (uint)Math.Max(1, VTF.Header.Width >> Mip);
            Header.dwHeight = (uint)Math.Max(1, VTF.Header.Height >> Mip);

            Header.dwSize              = (uint)Marshal.SizeOf(typeof(DdsHeader));
            Header.dwFlags             = DdsHeaderFlags.CAPS | DdsHeaderFlags.HEIGHT | DdsHeaderFlags.WIDTH | DdsHeaderFlags.PIXELFORMAT;
            Header.dwPitchOrLinearSize = (uint)(Math.Max(1, (VTF.Header.Width + 3) / 4) * BlockSize);
            Header.dwDepth             = 1;
            Header.dwMipMapCount       = 1;
            Header.dwCaps              = DdsCaps.TEXTURE;
            Header.ddspf.dwSize        = (uint)Marshal.SizeOf(typeof(DdsPixelFormat));
            Header.ddspf.dwFlags       = DdsPixelFormatFlags.FOURCC;
            Header.ddspf.dwFourCC      = FourCC;

            fixed(byte *bufferPtr = Buffer)
            {
                uint *     MagicPtr  = (uint *)bufferPtr;
                DdsHeader *HeaderPtr = (DdsHeader *)(bufferPtr + sizeof(uint));

                *MagicPtr  = 0x20534444;
                *HeaderPtr = Header;
            }

            return((int)Header.dwSize + sizeof(uint));
        }
예제 #3
0
        private string GetPngUrl(HttpListenerRequest request, string path, ValveTextureFile vtf, string mapName = null)
        {
            var queryStringBuilder = new StringBuilder();

            if (vtf.MipmapCount > 1)
            {
                AppendToQueryString(queryStringBuilder, "mipmap");
            }
            if (vtf.FrameCount > 1)
            {
                AppendToQueryString(queryStringBuilder, "frame");
            }
            if (vtf.FaceCount > 1)
            {
                AppendToQueryString(queryStringBuilder, "face");
            }
            if (vtf.ZSliceCount > 1)
            {
                AppendToQueryString(queryStringBuilder, "zslice");
            }

            return($"http://{request.Url.Authority}{UrlPrefix}/{GetProviderPrefix( mapName )}/{path.Replace( ".vtf", ".png" )}{queryStringBuilder}");
        }
예제 #4
0
        private JObject GetJson(IResourceProvider provider, string filePath, string mapName = null)
        {
            ValveTextureFile vtf;

            using (var vtfStream = provider.OpenFile(filePath))
            {
                vtf = new ValveTextureFile(vtfStream, true);
            }

            var response = new JObject
            {
                { "width", vtf.Header.Width },
                { "height", vtf.Header.Height },
                { "version", vtf.Header.MajorVersion + vtf.Header.MinorVersion * 0.1f },
                { "flags", (long)vtf.Header.Flags },
                { "pngUrl", GetPngUrl(Request, filePath, vtf, mapName) },
                { "mipmaps", vtf.MipmapCount },
                { "frames", vtf.FrameCount },
                { "faces", vtf.FaceCount },
                { "depth", vtf.ZSliceCount }
            };

            return(response);
        }
예제 #5
0
        public static MagickImage DecodeImage(ValveTextureFile vtf, int mip, int frame, int face, int zslice)
        {
            var dataLength  = vtf.GetHiResPixelDataLength(mip);
            var totalLength = dataLength + 128;

            if (_sPixelBuffer == null || _sPixelBuffer.Length < totalLength)
            {
                var powerOf2 = 256;
                while (powerOf2 < totalLength)
                {
                    powerOf2 <<= 1;
                }

                _sPixelBuffer = new byte[powerOf2];
            }

            var offset = 0;
            var width  = Math.Max(1, vtf.Header.Width >> mip);
            var height = Math.Max(1, vtf.Header.Height >> mip);

            var readSettings = new MagickReadSettings
            {
                Width  = width,
                Height = height
            };

            switch (vtf.Header.HiResFormat)
            {
            case TextureFormat.DXT1:
            case TextureFormat.DXT3:
            case TextureFormat.DXT5:
                readSettings.Format = MagickFormat.Dds;
                offset = WriteDdsHeader(vtf, mip, _sPixelBuffer);
                break;

            case TextureFormat.BGR888:
                readSettings.PixelStorage = new PixelStorageSettings(StorageType.Char, "BGR");
                break;

            case TextureFormat.RGB888:
            case TextureFormat.RGB888_BLUESCREEN:
                readSettings.PixelStorage = new PixelStorageSettings(StorageType.Char, "RGB");
                break;

            case TextureFormat.ABGR8888:
                readSettings.PixelStorage = new PixelStorageSettings(StorageType.Char, "ABGR");
                break;

            case TextureFormat.BGRA8888:
                readSettings.PixelStorage = new PixelStorageSettings(StorageType.Char, "BGRA");
                break;

            case TextureFormat.RGBA8888:
                readSettings.PixelStorage = new PixelStorageSettings(StorageType.Char, "RGBA");
                break;

            default:
                throw new NotImplementedException();
            }

            vtf.GetHiResPixelData(mip, frame, face, zslice, _sPixelBuffer, offset);

            var img = new MagickImage(_sPixelBuffer, readSettings);

            if (img.Width != width || img.Height != height)
            {
                img.Resize(new MagickGeometry(width, height)
                {
                    IgnoreAspectRatio = true
                });
            }

            return(img);
        }
예제 #6
0
        public static unsafe void ConvertToDds(ValveTextureFile vtf, int mipMap, int frame, int face, int zslice, Stream outStream)
        {
            var oneMipMap = mipMap > -1;

            if (mipMap < 0)
            {
                mipMap = 0;
            }

            if (mipMap >= vtf.Header.MipMapCount)
            {
                ConvertToDds(vtf, vtf.Header.MipMapCount - 1, frame, face, zslice, outStream);
                return;
            }

            var header = new DdsHeader();

            int  blockSize;
            uint fourCC;

            switch (vtf.Header.HiResFormat)
            {
            case TextureFormat.DXT1:
                blockSize = 8;
                fourCC    = 0x31545844;
                break;

            case TextureFormat.DXT5:
                blockSize = 16;
                fourCC    = 0x35545844;
                break;

            default:
                throw new NotImplementedException();
            }

            GetMipMapSize(vtf.Header.Width, vtf.Header.Height, mipMap, out header.dwWidth, out header.dwHeight);

            header.dwSize  = (uint)Marshal.SizeOf(typeof(DdsHeader));
            header.dwFlags = DdsHeaderFlags.CAPS | DdsHeaderFlags.HEIGHT | DdsHeaderFlags.WIDTH
                             | DdsHeaderFlags.PIXELFORMAT | (oneMipMap ? 0 : DdsHeaderFlags.MIPMAPCOUNT);
            header.dwPitchOrLinearSize = (uint)(Math.Max(1, (vtf.Header.Width + 3) / 4) * blockSize);
            header.dwDepth             = 1;
            header.dwMipMapCount       = oneMipMap ? 1 : (uint)vtf.Header.MipMapCount;
            header.dwCaps         = DdsCaps.TEXTURE | (oneMipMap ? 0 : DdsCaps.MIPMAP);
            header.ddspf.dwSize   = (uint)Marshal.SizeOf(typeof(DdsPixelFormat));
            header.ddspf.dwFlags  = DdsPixelFormatFlags.FOURCC;
            header.ddspf.dwFourCC = fourCC;

            if (_sHeaderBuffer == null)
            {
                _sHeaderBuffer = new byte[header.dwSize];

                fixed(byte *bufferPtr = _sHeaderBuffer)
                {
                    var headerPtr = (DdsHeader *)bufferPtr;

                    *headerPtr = header;
                }

                using (var writer = new BinaryWriter(outStream, Encoding.ASCII, true))
                {
                    writer.Write((uint)0x20534444);
                    writer.Write(_sHeaderBuffer);

                    var endMipMap = oneMipMap ? mipMap + 1 : vtf.Header.MipMapCount;
                    for (var i = mipMap; i < endMipMap; ++i)
                    {
                        vtf.WriteHiResPixelData(i, frame, face, zslice, writer);
                    }
                }
        }
예제 #7
0
파일: VTF.cs 프로젝트: yarligayan/libTech
        public static Texture ToTexture(ValveTextureFile VTF, int Mip = 0, int Frame = 0, int Face = 0, int ZSlice = 0)
        {
            int DataLen  = VTF.GetHiResPixelDataLength(Mip);
            int TotalLen = DataLen + 128;

            byte[] PixelBuffer = null;

            if (PixelBuffer == null || PixelBuffer.Length < TotalLen)
            {
                int PowerOfTwo = 256;

                while (PowerOfTwo < TotalLen)
                {
                    PowerOfTwo <<= 1;
                }

                PixelBuffer = new byte[PowerOfTwo];
            }

            bool  RemoveAlpha = false;
            Image Img         = null;
            int   Offset      = 0;
            int   Width       = Math.Max(1, VTF.Header.Width >> Mip);
            int   Height      = Math.Max(1, VTF.Header.Height >> Mip);
            MagickReadSettings ReadSettings = new MagickReadSettings {
                Width = Width, Height = Height
            };

            switch (VTF.Header.HiResFormat)
            {
            case TextureFormat.DXT1:
            case TextureFormat.DXT3:
            case TextureFormat.DXT5: {
                if (VTF.Header.HiResFormat == TextureFormat.DXT1)
                {
                    RemoveAlpha = true;
                }

                ReadSettings.Format = MagickFormat.Dds;
                Offset = DDS.WriteDdsHeader(VTF, Mip, PixelBuffer);
                break;
            }

            case TextureFormat.I8:
                ReadSettings.Format = MagickFormat.Gray;
                RemoveAlpha         = true;
                break;

            case TextureFormat.IA88:
                ReadSettings.Format = MagickFormat.Graya;
                break;

            case TextureFormat.BGRA8888:
                ReadSettings.Format = MagickFormat.Bgra;
                break;

            case TextureFormat.BGR888:
                ReadSettings.Format = MagickFormat.Bgr;
                RemoveAlpha         = true;
                break;

            default:
                throw new NotImplementedException();
            }


            if (Img == null)
            {
                VTF.GetHiResPixelData(Mip, Frame, Face, ZSlice, PixelBuffer, Offset);
                MagickImage MImg = new MagickImage(PixelBuffer, ReadSettings);

                if (MImg.Width != Width || MImg.Height != Height)
                {
                    MImg.Resize(new MagickGeometry(Width, Height)
                    {
                        IgnoreAspectRatio = true
                    });
                }

                Bitmap Bmp = MImg.ToBitmap();

                if (RemoveAlpha)
                {
                    Bmp.RemoveAlpha();
                }

                Img = Bmp;
            }

            TextureWrap WrapU = TextureWrap.Repeat;
            TextureWrap WrapV = TextureWrap.Repeat;

            if ((VTF.Header.Flags & TextureFlags.CLAMPS) != 0)
            {
                WrapU = TextureWrap.ClampToEdge;
            }

            if ((VTF.Header.Flags & TextureFlags.CLAMPT) != 0)
            {
                WrapV = TextureWrap.ClampToEdge;
            }

            if ((VTF.Header.Flags & TextureFlags.CLAMPS) != 0)
            {
                WrapU = WrapV = TextureWrap.ClampToBorder;
            }

            TextureFilter MinFilter = TextureFilter.LinearMipmapLinear;

            if ((VTF.Header.Flags & TextureFlags.POINTSAMPLE) != 0)
            {
                MinFilter = TextureFilter.NearestMipmapNearest;
            }

            Texture T = Texture.FromImage(Img, MipmapLevels: 4);

            T.SetWrap(WrapU, WrapV);
            T.SetFilter(MinFilter, TextureFilter.Nearest);
            return(T);
        }
예제 #8
0
        public static MagickImage DecodeImage(ValveTextureFile vtf, int mip, int frame, int face, int zslice)
        {
            var dataLength = vtf.GetHiResPixelDataLength(mip);

            // Let's pretend 16bpp formats are really 24bpp
            switch (vtf.Header.HiResFormat)
            {
            case TextureFormat.RGB565:
            case TextureFormat.BGR565:
                dataLength = dataLength * 3 / 2;
                break;
            }

            var totalLength = dataLength + 128;

            if (_sPixelBuffer == null || _sPixelBuffer.Length < totalLength)
            {
                var powerOf2 = 256;
                while (powerOf2 < totalLength)
                {
                    powerOf2 <<= 1;
                }

                _sPixelBuffer = new byte[powerOf2];
            }

            var offset = 0;
            var width  = Math.Max(1, vtf.Header.Width >> mip);
            var height = Math.Max(1, vtf.Header.Height >> mip);

            var readSettings = new MagickReadSettings
            {
                Width  = width,
                Height = height
            };

            switch (vtf.Header.HiResFormat)
            {
            case TextureFormat.DXT1:
            case TextureFormat.DXT3:
            case TextureFormat.DXT5:
                readSettings.Format = MagickFormat.Dds;
                offset = WriteDdsHeader(vtf, mip, _sPixelBuffer);
                break;

            case TextureFormat.I8:
                readSettings.Format = MagickFormat.Gray;
                break;

            case TextureFormat.IA88:
                readSettings.Format       = MagickFormat.Gray;
                readSettings.PixelStorage = new PixelStorageSettings
                {
                    StorageType = StorageType.Char,
                    Mapping     = "PA"
                };
                break;

            case TextureFormat.BGR565:
            case TextureFormat.BGR888:
                readSettings.PixelStorage = new PixelStorageSettings(StorageType.Char, "BGR");
                break;

            case TextureFormat.RGB565:
            case TextureFormat.RGB888:
            case TextureFormat.RGB888_BLUESCREEN:
                readSettings.PixelStorage = new PixelStorageSettings(StorageType.Char, "RGB");
                break;

            case TextureFormat.ABGR8888:
                readSettings.PixelStorage = new PixelStorageSettings(StorageType.Char, "ABGR");
                break;

            case TextureFormat.BGRA8888:
                readSettings.PixelStorage = new PixelStorageSettings(StorageType.Char, "BGRA");
                break;

            case TextureFormat.RGBA8888:
                readSettings.PixelStorage = new PixelStorageSettings(StorageType.Char, "RGBA");
                break;

            default:
                throw new NotImplementedException();
            }

            vtf.GetHiResPixelData(mip, frame, face, zslice, _sPixelBuffer, offset);

            // Convert 16bpp to 24bpp
            switch (vtf.Header.HiResFormat)
            {
            case TextureFormat.RGB565:
            case TextureFormat.BGR565:
                for (var i = width * height - 1; i >= 0; --i)
                {
                    var pixel = (ushort)(_sPixelBuffer[i * 2] | (_sPixelBuffer[i * 2 + 1] << 8));

                    _sPixelBuffer[i * 3]     = (byte)((pixel & 31) / 31f * 255f);
                    _sPixelBuffer[i * 3 + 1] = (byte)(((pixel >> 5) & 63) / 63f * 255f);
                    _sPixelBuffer[i * 3 + 2] = (byte)(((pixel >> 11) & 31) / 31f * 255f);
                }
                break;
            }

            var img = new MagickImage(_sPixelBuffer, readSettings);

            if (img.Width != width || img.Height != height)
            {
                img.Resize(new MagickGeometry(width, height)
                {
                    IgnoreAspectRatio = true
                });
            }

            return(img);
        }
예제 #9
0
        public static Texture Get(ValveBspFile bsp, string path)
        {
            var inBsp = bsp != null && bsp.PakFile.ContainsFile(path);
            var res   = inBsp ? bsp.PakFile : Program.Resources;

            if (!res.ContainsFile(path))
            {
                return(null);
            }

            ValveTextureFile vtf;

            using (var stream = res.OpenFile(path))
            {
                vtf = new ValveTextureFile(stream);
            }

            var isCube     = vtf.FaceCount == 6;
            var untextured = Program.BaseOptions.Untextured && !path.StartsWith("materials/skybox/");

            var tex = new Texture
            {
                Path       = path.ToLower(),
                Target     = isCube ? TextureTarget.TextureCubeMap : TextureTarget.Texture2D,
                Width      = untextured ? 1 : vtf.Header.Width,
                Height     = untextured ? 1 : vtf.Header.Height,
                FrameCount = vtf.Header.Frames,
                Params     =
                {
                    Filter = untextured || (vtf.Header.Flags & TextureFlags.POINTSAMPLE) != 0
                        ? TextureMinFilter.Nearest
                        : TextureMinFilter.Linear,
                    MipMap = !untextured && (vtf.Header.Flags & TextureFlags.NOMIP) == 0,
                    WrapS  = (vtf.Header.Flags & TextureFlags.CLAMPS) != 0
                        ? TextureWrapMode.ClampToEdge
                        : TextureWrapMode.Repeat,
                    WrapT  = (vtf.Header.Flags & TextureFlags.CLAMPT) != 0
                        ? TextureWrapMode.ClampToEdge
                        : TextureWrapMode.Repeat
                }
            };

            byte[] pixelBuf = null;

            for (var mip = vtf.MipmapCount - 1; mip >= 0; --mip)
            {
                var isSinglePixel = Math.Max(tex.Width >> mip, 1) * Math.Max(tex.Height >> mip, 1) == 1;

                for (var frame = 0; frame < vtf.FrameCount; ++frame)
                {
                    for (var face = 0; face < vtf.FaceCount; ++face)
                    {
                        var elem = new TextureElement
                        {
                            Level = untextured ? 0 : mip,
                            Frame = vtf.FrameCount > 1 ? (int?)frame : null
                        };

                        if (isCube)
                        {
                            elem.Target = TextureTarget.TextureCubeMapPositiveX + face;
                        }
                        if (isSinglePixel)
                        {
                            if (pixelBuf == null)
                            {
                                pixelBuf = new byte[vtf.GetHiResPixelDataLength(mip)];
                            }

                            vtf.GetHiResPixelData(mip, frame, face, 0, pixelBuf);

                            using (var img = DecodeImage(vtf, mip, frame, face, 0))
                            {
                                var pixel = img.GetPixels()[0, 0];
                                switch (pixel.Channels)
                                {
                                case 3:
                                    elem.Color = new MaterialColor(pixel[0], pixel[1], pixel[2]);
                                    break;

                                case 4:
                                    elem.Color = new MaterialColor(pixel[0], pixel[1], pixel[2], pixel[3]);
                                    break;

                                default:
                                    throw new NotImplementedException();
                                }
                            }
                        }
                        else
                        {
                            var fileName = $"{path}/mip{mip}";

                            if (vtf.FrameCount > 1)
                            {
                                fileName = $"{fileName}.frame{frame}";
                            }

                            if (vtf.FaceCount > 1)
                            {
                                fileName = $"{fileName}.face{face}";
                            }

                            fileName = $"{fileName}.png";

                            elem.Url = inBsp ? $"/maps/{bsp.Name}/{fileName}" : $"/{fileName}";
                        }

                        tex.Elements.Add(elem);
                    }
                }

                if (untextured)
                {
                    break;
                }
            }

            return(tex);
        }
예제 #10
0
        public void GetImage([Url] string map)
        {
            if (Skip)
            {
                Response.OutputStream.Close();
                return;
            }

            var absolute  = Request.Url.AbsolutePath;
            var pathStart = absolute.IndexOf("/materials") + 1;
            var pathEnd   = absolute.IndexOf(".vtf", pathStart) + ".vtf".Length;
            var path      = HttpUtility.UrlDecode(absolute.Substring(pathStart, pathEnd - pathStart));

            var fileName = Path.GetFileName(absolute);
            var match    = _sFileNameRegex.Match(fileName);

            if (!match.Success)
            {
                throw NotFoundException();
            }

            var mip   = 0;
            var face  = 0;
            var frame = 0;

            var index = 0;

            foreach (Capture capture in match.Groups["param"].Captures)
            {
                var param = capture.Value.ToLower();
                var value = int.Parse(match.Groups["value"].Captures[index++].Value);

                switch (param)
                {
                case "mip":
                    mip = value;
                    break;

                case "face":
                    face = value;
                    break;

                case "frame":
                    frame = value;
                    break;
                }
            }

            var bsp = map == null ? null : Program.GetMap(map);
            var res = bsp == null ? Program.Resources : bsp.PakFile;

            ValveTextureFile vtf;

            using (var stream = res.OpenFile(path))
            {
                vtf = new ValveTextureFile(stream);
            }

            var buffer = new byte[vtf.GetHiResPixelDataLength(mip)];

            vtf.GetHiResPixelData(mip, frame, face, 0, buffer);

            using (var image = Texture.DecodeImage(vtf, mip, frame, face, 0))
            {
                image.Write(Response.OutputStream, MagickFormat.Png);
            }

            Response.OutputStream.Close();
        }