/// <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; }