Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
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();
        }