Example #1
0
        /// <summary>
        /// Extract Bitmap from WAD.
        /// </summary>
        /// <param name="index">Lump index.</param>
        /// <param name="transparent">Replace blue color with alpha 0.</param>
        /// <returns>Returns Texture. Contains image and Mipmaps.</returns>
        /// <exception cref="TextureDimensionException"></exception>
        public Texture GetLumpImage(int index, bool transparent = false)
        {
            Texture retVal;

            if (index > -1 && index < LumpsInfo.Count)
            {
                byte type = LumpsInfo[index].Type;

                //0x40 - tempdecal.wad
                //0x42 - cached.wad
                //0x43 - normald wads
                //0x46 - fonts
                if (type == 0x40 || type == 0x42 || type == 0x43 || type == 0x46) //Supported types
                {
                    //Go to lump
                    binReader.BaseStream.Seek(LumpsInfo[index].Offset, SeekOrigin.Begin);

                    if (type == 0x40 || type == 0x43)
                    {
                        //Skip lump name
                        binReader.BaseStream.Seek(MaxNameLength, SeekOrigin.Current);
                    }

                    //Read texture size
                    uint width  = binReader.ReadUInt32();
                    uint height = binReader.ReadUInt32();

                    if (width > MaxTextureWidth || height > MaxTextureHeight)
                    {
                        throw new TextureDimensionException("Texture width or height exceeds maximum size!");
                    }

                    if (width == 0 || height == 0)
                    {
                        throw new TextureDimensionException("Texture width and height must be larger than 0!");
                    }

                    //If QFont
                    if (type == 0x46)
                    {
                        //width = width * QCharWidth;
                        width = 256;
                        uint       RowCount  = binReader.ReadUInt32();
                        uint       RowHeight = binReader.ReadUInt32();
                        CharInfo[] FontInfo  = new CharInfo[QNumbOfGlyphs];
                        for (int i = 0; i < QNumbOfGlyphs; i++)
                        {
                            FontInfo[i].StartOffset = binReader.ReadUInt16();
                            FontInfo[i].CharWidth   = binReader.ReadUInt16();
                        }
                    }

                    //Initialize bitmap
                    Bitmap bmp = new Bitmap((int)width, (int)height, PixelFormat.Format8bppIndexed);

                    //Read pixel offset, skip MIPMAPS offsets
                    if (type == 0x40 || type == 0x43)
                    {
                        //Not used, but needed
                        uint pixelOffset = binReader.ReadUInt32();

                        //Skip MIPMAPS offsets, not needed
                        binReader.BaseStream.Seek(12, SeekOrigin.Current);
                    }

                    //Read RAW pixels
                    uint pixelSize = width * height;
                    pixelsBlockPos = binReader.BaseStream.Position;
                    lastImageSize  = pixelSize;
                    lastImageWidth = width;
                    byte[] pixels = pixels = binReader.ReadBytes((int)pixelSize);

                    //Read MIPMAPS
                    Texture.TextureMipmaps mipmaps = null;
                    if (type == 0x40 || type == 0x43)
                    {
                        mipmaps = new Texture.TextureMipmaps
                        {
                            Mipmap1 = binReader.ReadBytes((int)((width / 2) * (height / 2))),
                            Mipmap2 = binReader.ReadBytes((int)((width / 4) * (height / 4))),
                            Mipmap3 = binReader.ReadBytes((int)((width / 8) * (height / 8)))
                        };
                    }

                    //Padding 2-bytes
                    binReader.BaseStream.Seek(2, SeekOrigin.Current);

                    //Prepare new palette for bitmap
                    ColorPalette pal = bmp.Palette;
                    palleteBlockPos = binReader.BaseStream.Position;

                    //Read palette bytes from file into array
                    byte[] palBytes = binReader.ReadBytes(MaxPaletteColors * 3);
                    for (int i = 0, j = 0; i < MaxPaletteColors; i++)
                    {
                        if (type == 0x40) //e.g.: tempdecal.wad
                        {
                            pal.Entries[i] = Color.FromArgb(i, i, i);
                        }
                        else
                        {
                            //Read palette entry RGB
                            pal.Entries[i] = Color.FromArgb(palBytes[j], palBytes[j + 1], palBytes[j + 2]);
                        }

                        //Check for transparent (blue) color
                        if (transparent && i == (MaxPaletteColors - 1) && LumpsInfo[index].Name.StartsWith("{"))
                        {
                            pal.Entries[i] = Color.FromArgb(0, pal.Entries[i]);
                        }
                        j += 3;
                    }
                    bmp.Palette = pal;

                    //Lock bitmap for pixel manipulation
                    BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, (int)width, (int)height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
                    System.Runtime.InteropServices.Marshal.Copy(pixels, 0, bmd.Scan0, pixels.Length);
                    bmp.UnlockBits(bmd);

                    retVal = new Texture
                    {
                        Image   = bmp,
                        Mipmaps = mipmaps
                    };
                }
                else
                {
                    throw new HLToolsUnsupportedFile("Unsupported type (0x" + LumpsInfo[index].Type.ToString("X") + ") of lump (texture) in WAD!");
                }
            }
            else
            {
                throw new ArgumentOutOfRangeException();
            }

            return(retVal);
        }
        /// <summary>
        /// Extract Bitmap from WAD.
        /// </summary>
        /// <param name="index">Lump index.</param>
        /// <param name="transparent">Replace blue color with alpha 0.</param>
        /// <returns>Returns Texture. Contains image and Mipmaps.</returns>
        /// <exception cref="TextureDimensionException"></exception>
        public Texture GetLumpImage(int index, bool transparent = false)
        {
            Texture retVal = null;

            if (index > -1 && index < LumpsInfo.Count)
            {
                byte type = LumpsInfo[index].Type;

                //0x40 - tempdecal.wad
                //0x42 - cached.wad
                //0x43 - normald wads
                //0x46 - fonts
                if (type == 0x40 || type == 0x42 || type == 0x43 || type == 0x46) //Supported types
                {
                    //Go to lump
                    binReader.BaseStream.Seek(LumpsInfo[index].Offset, SeekOrigin.Begin);

                    if (type == 0x40 || type == 0x43)
                    {
                        //Skip lump name
                        binReader.BaseStream.Seek(MaxNameLength, SeekOrigin.Current);
                    }

                    //Read texture size
                    uint width = binReader.ReadUInt32();
                    uint height = binReader.ReadUInt32();

                    if (width > MaxTextureWidth || height > MaxTextureHeight)
                        throw new TextureDimensionException("Texture width or height exceeds maximum size!");

                    if (width == 0 || height == 0)
                        throw new TextureDimensionException("Texture width and height must be larger than 0!");

                    //If QFont
                    if (type == 0x46)
                    {
                        //width = width * QCharWidth;
                        width = 256;
                        uint RowCount = binReader.ReadUInt32();
                        uint RowHeight = binReader.ReadUInt32();
                        CharInfo[] FontInfo = new CharInfo[QNumbOfGlyphs];
                        for (int i = 0; i < QNumbOfGlyphs; i++)
                        {
                            FontInfo[i].StartOffset = binReader.ReadUInt16();
                            FontInfo[i].CharWidth = binReader.ReadUInt16();
                        }

                    }

                    //Initialize bitmap
                    Bitmap bmp = new Bitmap((int)width, (int)height, PixelFormat.Format8bppIndexed);

                    //Read pixel offset, skip MIPMAPS offsets
                    if (type == 0x40 || type == 0x43)
                    {
                        //Not used, but needed
                        uint pixelOffset = binReader.ReadUInt32();

                        //Skip MIPMAPS offsets, not needed
                        binReader.BaseStream.Seek(12, SeekOrigin.Current);
                    }

                    //Read RAW pixels
                    uint pixelSize = width * height;
                    pixelsBlockPos = binReader.BaseStream.Position;
                    lastImageSize = pixelSize;
                    lastImageWidth = width;
                    byte[] pixels = pixels = binReader.ReadBytes((int)pixelSize);

                    //Read MIPMAPS
                    Texture.TextureMipmaps mipmaps = null;
                    if (type == 0x40 || type == 0x43)
                    {
                        mipmaps = new Texture.TextureMipmaps();
                        mipmaps.Mipmap1 = binReader.ReadBytes((int)((width / 2) * (height / 2)));
                        mipmaps.Mipmap2 = binReader.ReadBytes((int)((width / 4) * (height / 4)));
                        mipmaps.Mipmap3 = binReader.ReadBytes((int)((width / 8) * (height / 8)));
                    }

                    //Padding 2-bytes
                    binReader.BaseStream.Seek(2, SeekOrigin.Current);

                    //Prepare new palette for bitmap
                    ColorPalette pal = bmp.Palette;
                    palleteBlockPos = binReader.BaseStream.Position;

                    //Read palette bytes from file into array
                    byte[] palBytes = binReader.ReadBytes(MaxPaletteColors * 3);
                    for (int i = 0, j = 0; i < MaxPaletteColors; i++)
                    {
                        if (type == 0x40) //e.g.: tempdecal.wad
                        {
                            pal.Entries[i] = Color.FromArgb(i, i, i);
                        }
                        else
                        {
                            //Read palette entry RGB
                            pal.Entries[i] = Color.FromArgb(palBytes[j], palBytes[j + 1], palBytes[j + 2]);
                        }

                        //Check for transparent (blue) color
                        if (transparent && i == (MaxPaletteColors - 1) && LumpsInfo[index].Name.StartsWith("{"))
                        {
                            pal.Entries[i] = Color.FromArgb(0, pal.Entries[i]);
                        }
                        j += 3;
                    }
                    bmp.Palette = pal;

                    //Lock bitmap for pixel manipulation
                    BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, (int)width, (int)height), System.Drawing.Imaging.ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
                    System.Runtime.InteropServices.Marshal.Copy(pixels, 0, bmd.Scan0, pixels.Length);
                    bmp.UnlockBits(bmd);

                    retVal = new Texture();
                    retVal.Image = bmp;
                    retVal.Mipmaps = mipmaps;
                }
                else
                {
                    throw new HLToolsUnsupportedFile("Unsupported type (0x" + LumpsInfo[index].Type.ToString("X") + ") of lump (texture) in WAD!");
                }
            }
            else
            {
                throw new ArgumentOutOfRangeException();
            }

            return retVal;
        }