/// <summary> /// Initializes a new <see cref="HaloBitmap"/> instance using the supplied object index entry. /// </summary> /// <param name="entry">The object index entry that contains the bitmap tag group data.</param> /// <exception cref="ArgumentNullException"><paramref name="entry"/> is null.</exception> /// <exception cref="ArgumentException"><paramref name="entry"/> is not a bitmap.</exception> public HaloBitmap(IndexEntry entry) { //Check if (entry == null) { throw new ArgumentNullException(nameof(entry)); } else if (entry.Root != HaloTags.bitm) { throw new ArgumentException("Index entry is not bitmap.", nameof(entry)); } //Setup this.entry = entry; tag = new BitmapTag(entry); maps = new Bitmap[tag.Bitmaps.Length][][]; //Setup Property Accessors bitmaps = new BitmapProperties[tag.Bitmaps.Length]; for (int i = 0; i < tag.Bitmaps.Length; i++) { bitmaps[i] = new BitmapProperties(this, i); } sequences = new SequenceProperties[tag.Sequences.Length]; for (int i = 0; i < tag.Sequences.Length; i++) { sequences[i] = new SequenceProperties(this, i); } //Check if (tag == null) { return; } else if (tag.Bitmaps.Length == 0) { return; } //Loop through bitmaps for (int k = 0; k < tag.Bitmaps.Length; k++) { //Setup BitmapTagGroup.Bitmap bitmap = tag.Bitmaps[k]; maps[k] = new Bitmap[6][]; //Loop through LODs byte[] sourceData = null; for (int l = 0; l < 6; l++) { //Get source data if (bitmap.rawOffsets[l] != uint.MaxValue) { RawLocation rawLocation = (RawLocation)(bitmap.rawOffsets[l] & 0xC0000000); if (rawLocation == RawLocation.Local) { sourceData = entry.Raws[RawSection.Bitmap][(int)bitmap.rawOffsets[l]].GetBuffer(); } else { string filelocation = string.Empty; int rawOffset = (int)(bitmap.rawOffsets[l] & (uint)RawLocation.LocalMask); switch (rawLocation) { case RawLocation.Mainmenu: filelocation = HaloSettings.MainmenuPath; break; case RawLocation.Shared: filelocation = HaloSettings.SharedPath; break; case RawLocation.SinglePlayerShared: filelocation = HaloSettings.SingleplayerSharedPath; break; } //Check if (File.Exists(filelocation)) { using (FileStream fs = new FileStream(filelocation, FileMode.Open)) using (BinaryReader mapReader = new BinaryReader(fs)) { fs.Seek(rawOffset, SeekOrigin.Begin); sourceData = mapReader.ReadBytes(bitmap.rawLengths[l]); } } } } //Set if (sourceData.Length == 0) { continue; } //Prepare BitmapFlags flags = (BitmapFlags)bitmap.flags; BitmapFormat format = (BitmapFormat)bitmap.format; PixelFormat bitmapFormat = PixelFormat.Format32bppArgb; int sourceBits = 32; switch (format) { case BitmapFormat.A8: case BitmapFormat.Y8: case BitmapFormat.P8Bump: case BitmapFormat.P8: case BitmapFormat.Ay8: sourceBits = 8; break; case BitmapFormat.A8y8: case BitmapFormat.A1r5g5b5: case BitmapFormat.A4r4g4b4: case BitmapFormat.V8u8: case BitmapFormat.G8b8: case BitmapFormat.R5g6b5: sourceBits = 16; break; case BitmapFormat.Dxt1: sourceBits = 4; break; case BitmapFormat.Dxt5: case BitmapFormat.Dxt3: sourceBits = 8; break; case BitmapFormat.Argbfp32: sourceBits = 128; break; } //Handle switch (format) { case BitmapFormat.R5g6b5: bitmapFormat = PixelFormat.Format16bppRgb565; break; case BitmapFormat.A1r5g5b5: bitmapFormat = PixelFormat.Format16bppArgb1555; break; case BitmapFormat.X8r8g8b8: bitmapFormat = PixelFormat.Format32bppRgb; break; case BitmapFormat.P8Bump: bitmapFormat = PixelFormat.Format8bppIndexed; break; case BitmapFormat.P8: bitmapFormat = PixelFormat.Format8bppIndexed; break; } //Prepare int width = bitmap.width, height = bitmap.height; if (flags.HasFlag(BitmapFlags.Linear)) { width = (int)Math.Ceiling(width / 16f) * 16; } //Loop LOD for (int i = 0; i < l; i++) { width /= 2; height /= 2; } //Prepare int mapWidth = width, mapHeight = height, location = 0; int mipmapCount = bitmap.mipmapCount; maps[k][l] = new Bitmap[mipmapCount + 1]; Size bitmapSize = Size.Empty; byte[] mapData = null; //Loop for (int i = 1; i <= mipmapCount + 1; i++) { //Prepare int mapIndex = i - 1; mapWidth = width; mapHeight = height; for (int j = 1; j < i; j++) { mapWidth /= 2; mapHeight /= 2; } //Get Size bitmapSize = new Size(mapWidth, mapHeight); //Check if (bitmapSize.Width == 0 || bitmapSize.Height == 0) { continue; } //Create Map int mapStride = mapWidth * sourceBits / 8; int mapSize = mapStride * mapHeight; //Ehh? switch (format) { case BitmapFormat.Dxt1: mapSize = Math.Max(mapSize, 8); break; case BitmapFormat.Dxt3: case BitmapFormat.Dxt5: mapSize = Math.Max(mapSize, 16); break; case BitmapFormat.P8: case BitmapFormat.P8Bump: mapSize = Math.Max(mapSize, 16); break; default: mapSize = Math.Max(mapSize, 1); break; } mapData = new byte[mapSize]; if (location + mapSize > sourceData.Length) { continue; } Array.Copy(sourceData, location, mapData, 0, mapSize); //Deswizzle? if ((flags & BitmapFlags.Swizzled) == BitmapFlags.Swizzled) { mapData = Swizzler.Swizzle(mapData, mapWidth, mapHeight, bitmap.depth, sourceBits, true); } if (mapData == null) { mapData = new byte[mapSize]; } using (Bitmap map = new Bitmap(mapWidth, mapHeight, bitmapFormat)) { unsafe { //Lock Bits BitmapData data = map.LockBits(new Rectangle(0, 0, mapWidth, mapHeight), ImageLockMode.ReadWrite, bitmapFormat); //Prepare Buffer byte[] bitmapData = new byte[data.Stride * data.Height]; int dataLength = Math.Min(bitmapData.Length, mapSize); //Handle Format... switch (format) { case BitmapFormat.A8: for (int x = 0; x < mapWidth * mapHeight; x++) { bitmapData[x * 4 + 0] = 255; bitmapData[x * 4 + 1] = 255; bitmapData[x * 4 + 2] = 255; bitmapData[x * 4 + 3] = mapData[x]; } break; case BitmapFormat.Y8: for (int x = 0; x < mapWidth * mapHeight; x++) { bitmapData[x * 4 + 0] = mapData[x]; bitmapData[x * 4 + 1] = mapData[x]; bitmapData[x * 4 + 2] = mapData[x]; bitmapData[x * 4 + 3] = 255; } break; case BitmapFormat.Ay8: for (int x = 0; x < mapWidth * mapHeight; x++) { bitmapData[x * 4 + 0] = mapData[x]; bitmapData[x * 4 + 1] = mapData[x]; bitmapData[x * 4 + 2] = mapData[x]; bitmapData[x * 4 + 3] = mapData[x]; } break; case BitmapFormat.A8y8: for (int x = 0; x < mapWidth * mapHeight; x++) { bitmapData[x * 4 + 0] = mapData[x * 2]; bitmapData[x * 4 + 1] = mapData[x * 2]; bitmapData[x * 4 + 2] = mapData[x * 2]; bitmapData[x * 4 + 3] = mapData[x * 2 + 1]; } break; case BitmapFormat.A4r4g4b4: for (int x = 0; x < mapWidth * mapHeight; x++) { bitmapData[x * 4 + 0] = (byte)(mapData[x * 2 + 0] & 0xF0); bitmapData[x * 4 + 1] = (byte)(mapData[x * 2 + 0] & 0x0F); bitmapData[x * 4 + 2] = (byte)(mapData[x * 2 + 1] & 0xF0); bitmapData[x * 4 + 3] = (byte)(mapData[x * 2 + 1] & 0x0F); } break; case BitmapFormat.P8Bump: case BitmapFormat.P8: Array.Copy(mapData, 0, bitmapData, 0, dataLength); break; case BitmapFormat.R5g6b5: Array.Copy(mapData, 0, bitmapData, 0, dataLength); break; case BitmapFormat.A1r5g5b5: Array.Copy(mapData, 0, bitmapData, 0, dataLength); break; case BitmapFormat.X8r8g8b8: Array.Copy(mapData, 0, bitmapData, 0, dataLength); break; case BitmapFormat.A8r8g8b8: Array.Copy(mapData, 0, bitmapData, 0, dataLength); break; case BitmapFormat.Dxt1: if (mapWidth >= 4 && mapHeight >= 4) { S3TC.DecompressDxt1(ref bitmapData, mapData, bitmapSize); } break; case BitmapFormat.Dxt3: if (mapWidth >= 4 && mapHeight >= 4) { S3TC.DecompressDxt3(ref bitmapData, mapData, bitmapSize); } break; case BitmapFormat.Dxt5: if (mapWidth >= 4 && mapHeight >= 4) { S3TC.DecompressDxt5(ref bitmapData, mapData, bitmapSize); } break; case BitmapFormat.Argbfp32: for (int x = 0; x < mapWidth * mapHeight; x++) { bitmapData[x * 4 + 0] = (byte)Math.Min((BitConverter.ToSingle(mapData, x * 16 + 8) * 255f), 255f); bitmapData[x * 4 + 1] = (byte)Math.Min((BitConverter.ToSingle(mapData, x * 16 + 4) * 255f), 255f); bitmapData[x * 4 + 2] = (byte)Math.Min((BitConverter.ToSingle(mapData, x * 16) * 255f), 255f); bitmapData[x * 4 + 3] = (byte)Math.Min((BitConverter.ToSingle(mapData, x * 16 + 12) * 255f), 255f); } break; case BitmapFormat.Rgbfp32: break; case BitmapFormat.Rgbfp16: break; case BitmapFormat.V8u8: for (int x = 0; x < mapWidth * mapHeight; x++) { bitmapData[x * 4 + 0] = 255; bitmapData[x * 4 + 1] = (byte)(127 + (sbyte)mapData[x * 2 + 1]); bitmapData[x * 4 + 2] = (byte)(127 + (sbyte)mapData[x * 2]); bitmapData[x * 4 + 3] = 255; } break; case BitmapFormat.G8b8: break; } //Copy Marshal.Copy(bitmapData, 0, data.Scan0, bitmapData.Length); map.UnlockBits(data); //Setup Palettes if (format == BitmapFormat.P8Bump) { map.SetNormalMapPalette(); } else if (format == BitmapFormat.P8) { map.SetGrayscalePalette(); } //Set location += mapSize; } //Draw into cropped image maps[k][l][mapIndex] = new Bitmap(bitmap.width, bitmap.height, bitmapFormat); using (Graphics g = Graphics.FromImage(maps[k][l][mapIndex])) g.DrawImage(map, Point.Empty); } } } } }
private byte[][] ddsFile_CreateBuffer(DdsFile ddsFile, out HaloBitmap.BitmapFormat format, ref int lodLevels, out bool linear, out bool swizzle, out bool deleteLods) { //Prepare format = HaloBitmap.BitmapFormat.Null; deleteLods = true; swizzle = false; linear = false; //Get Format if (ddsFile.PixelFormatFlags.HasFlag(DirectDrawPixelFormatFlags.FourCC)) //Check for FourCC flag... { switch (ddsFile.FourCC) //Check FourCC string { case "DXT1": format = HaloBitmap.BitmapFormat.Dxt1; break; case "DXT2": case "DXT3": format = HaloBitmap.BitmapFormat.Dxt3; break; case "DXT4": case "DXT5": format = HaloBitmap.BitmapFormat.Dxt5; break; case "ATI2": format = HaloBitmap.BitmapFormat.P8Bump; break; } switch (ddsFile.DwordFourCC) //Check FourCC int { case 116: format = HaloBitmap.BitmapFormat.Argbfp32; break; } } else { if (ddsFile.PixelFormatFlags.HasFlag(DirectDrawPixelFormatFlags.Argb)) //ARGB { switch (ddsFile.RgbBitCount) { case 16: //16bpp if (ddsFile.AlphaBitmask == 0x8000) { format = HaloBitmap.BitmapFormat.A1r5g5b5; //A1R5G5B5 } else { format = HaloBitmap.BitmapFormat.A4r4g4b4; //A4R4G4B4 } break; case 32: format = HaloBitmap.BitmapFormat.A8r8g8b8; break; //A8R8G8B8 } } else if (ddsFile.PixelFormatFlags.HasFlag(DirectDrawPixelFormatFlags.Rgb)) //RGB { switch (ddsFile.RgbBitCount) { case 16: format = HaloBitmap.BitmapFormat.R5g6b5; break; //R5G6B5 case 32: format = HaloBitmap.BitmapFormat.X8r8g8b8; break; //X8R8G8B8 } } else if (ddsFile.PixelFormatFlags.HasFlag(DirectDrawPixelFormatFlags.AlphaLuminance)) //AL { switch (ddsFile.RgbBitCount) { case 16: format = HaloBitmap.BitmapFormat.A8y8; break; //A8L8 } } else if (ddsFile.PixelFormatFlags.HasFlag(DirectDrawPixelFormatFlags.Luminance)) //L { switch (ddsFile.RgbBitCount) { case 8: format = HaloBitmap.BitmapFormat.Y8; break; //L8 } } else if (ddsFile.PixelFormatFlags.HasFlag(DirectDrawPixelFormatFlags.Argb)) //A { switch (ddsFile.RgbBitCount) { case 8: format = HaloBitmap.BitmapFormat.A8; break; //A8 } } else if (ddsFile.PixelFormatFlags.HasFlag(DirectDrawPixelFormatFlags.VU)) //VU { switch (ddsFile.RgbBitCount) { case 16: format = HaloBitmap.BitmapFormat.V8u8; break; //V8U8 } } } //Check if (format == HaloBitmap.BitmapFormat.Null) { switch (ddsFile.RgbBitCount) { case 8: format = HaloBitmap.BitmapFormat.Y8; break; case 16: format = HaloBitmap.BitmapFormat.A8y8; break; case 32: format = HaloBitmap.BitmapFormat.A8r8g8b8; break; default: throw new FormatException("DirectDraw Surface texture format is not supported."); } } //Confirm using (TextureImportOptionsDialog texDlg = new TextureImportOptionsDialog()) { //Setup int mapCount = 1 + (int)ddsFile.MipmapCount; texDlg.OriginalHeight = (int)ddsFile.Height; texDlg.OriginalWidth = (int)ddsFile.Width; texDlg.MaxLodLevels = mapCount; texDlg.LodLevels = lodLevels; texDlg.Format = format; //Show if (texDlg.ShowDialog(this) == DialogResult.OK) { lodLevels = texDlg.LodLevels; format = texDlg.Format; deleteLods = texDlg.DeleteLods; swizzle = texDlg.Swizzle; } else { return(null); } } //Prepare buffers byte[][] buffers = new byte[lodLevels][]; //Get BPP uint bitsPerPixel = 0; if (ddsFile.DefinitionFlags.HasFlag(DirectDrawSurfaceDefinitionFlags.LinearSize)) { bitsPerPixel = ddsFile.PitchOrLinearSize * 8u / ddsFile.Width / ddsFile.Height; } else { bitsPerPixel = ddsFile.RgbBitCount; } //Get Data Length long length = 0; uint mipWidth = ddsFile.Width, mipHeight = ddsFile.Height; for (int j = 0; j <= ddsFile.MipmapCount; j++) { length += mipWidth * mipHeight * bitsPerPixel / 8; mipWidth /= 2; mipHeight /= 2; } //Get Linear? if (ddsFile.RgbBitCount > 0) { linear = !swizzle; } //Get Data Lengths uint width = ddsFile.Width, height = ddsFile.Height; int position = 0; for (int i = 0; i < lodLevels; i++) { //Prepare int lodLength = 0; mipWidth = width; mipHeight = height; //Loop for (int j = i; j <= ddsFile.MipmapCount; j++) { lodLength += (int)(mipWidth * mipHeight * bitsPerPixel / 8); mipWidth /= 2; mipHeight /= 2; } //Prepare int mipPosition = 0; buffers[i] = new byte[lodLength]; mipWidth = width; mipHeight = height; for (int j = i; j <= ddsFile.MipmapCount; j++) { //Get Mip Data byte[] data = new byte[mipWidth * mipHeight * bitsPerPixel / 8]; Array.Copy(ddsFile.Data, mipPosition + position, data, 0, data.Length); //Swizzle? if (swizzle) { data = Swizzler.Swizzle(data, (int)mipWidth, (int)mipHeight, 1, (int)bitsPerPixel, !swizzle); } //Copy Array.Copy(data, 0, buffers[i], mipPosition, data.Length); //Increment mipPosition += (int)(mipWidth * mipHeight * bitsPerPixel / 8); mipWidth /= 2; mipHeight /= 2; } //Increment position += (int)(width * height * bitsPerPixel / 8); //Get next LOD width /= 2; height /= 2; } //Return return(buffers); }
public LandTextureMap(short[,] textureIndexMapping, bool swizzled) { this.textureIndexMapping = Validation.ValidateSquare(textureIndexMapping, TEXTURE_MAPPING_SIDE_LENGTH, "textureIndexMapping", "Texture Index Mapping"); Swizzled = swizzled; swizzler = new Swizzler(textureIndexMapping); }
private byte[] image_CreateBuffer(Image image, out bool linear, out bool swizzle, out bool deleteLods) { //Prepare linear = false; swizzle = false; deleteLods = true; byte[] buffer = new byte[image.Width * image.Height * 4]; //Get Color Data Color pixel = Color.Black; using (Bitmap bitmap = new Bitmap(image)) for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { //Get Pixel pixel = bitmap.GetPixel(x, y); int a = y * bitmap.Width + x; //Copy into buffer buffer[a * 4] = pixel.B; buffer[a * 4 + 1] = pixel.G; buffer[a * 4 + 2] = pixel.R; buffer[a * 4 + 3] = pixel.A; } } //Confirm using (TextureImportOptionsDialog texDlg = new TextureImportOptionsDialog()) { //Setup texDlg.OriginalHeight = image.Height; texDlg.OriginalWidth = image.Width; texDlg.MaxLodLevels = 1; texDlg.LodLevels = 1; texDlg.Format = HaloBitmap.BitmapFormat.A8r8g8b8; //Show if (texDlg.ShowDialog(this) == DialogResult.OK) { deleteLods = texDlg.DeleteLods; swizzle = texDlg.Swizzle; } else { return(null); } } //Get Linear linear = !swizzle; //Check if (swizzle) { buffer = Swizzler.Swizzle(buffer, image.Width, image.Height, 1, 32, false); } //Return return(buffer); }
private void exportToolStripButton_Click(object sender, EventArgs e) { //Prepare string filename = string.Empty; bool save = false; //Get Filename string[] parts = this.bitmap.Entry.Filename.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length > 0) { filename = parts[parts.Length - 1]; } //Initialize using (SaveFileDialog saveDlg = new SaveFileDialog()) { //Setup saveDlg.Filter = "DirectDraw Surface Files (*.dds)|*.dds"; saveDlg.Title = "Save texture as..."; saveDlg.FileName = filename; if (saveDlg.ShowDialog() == DialogResult.OK) { filename = saveDlg.FileName; save = true; } } //Prepare HaloBitmap.BitmapProperties bitmap = null; int bitmapIndex = (int)bitmapUpDown.Value; //Check if (save) { //Get Bitmap bitmap = this.bitmap.Bitmaps[bitmapIndex]; uint width = bitmap.Width, height = bitmap.Height, depth = bitmap.Depth; bool swizzled = (bitmap.Flags & HaloBitmap.BitmapFlags.Swizzled) == HaloBitmap.BitmapFlags.Swizzled; if ((bitmap.Flags & HaloBitmap.BitmapFlags.PowTwoDimensions) == 0 && bitmap.MipmapCount == 0) { width = width + (16 - (width % 16) == 16 ? 0 : 16 - (width % 16)); //Pad width to 16 for some ungodly reason } //Setup DDS file DdsFile file = new DdsFile(); file.Width = width; file.Height = height; file.MipmapCount = bitmap.MipmapCount; file.DefinitionFlags |= DirectDrawSurfaceDefinitionFlags.PixelFormat | DirectDrawSurfaceDefinitionFlags.Width | DirectDrawSurfaceDefinitionFlags.Height | DirectDrawSurfaceDefinitionFlags.Caps; file.Caps |= DirectDrawCaps.Texture; file.PitchOrLinearSize = (uint)bitmap_GetLength(bitmap.Format, bitmap.Width, bitmap.Height); file.DefinitionFlags |= DirectDrawSurfaceDefinitionFlags.LinearSize; if (file.MipmapCount > 0) { file.Caps |= DirectDrawCaps.Mipmap | DirectDrawCaps.Complex; file.DefinitionFlags |= DirectDrawSurfaceDefinitionFlags.MipmapCount; } //Setup Pixel Format switch (bitmap.Format) { case HaloBitmap.BitmapFormat.Dxt1: file.RgbBitCount = 0; file.FourCC = "DXT1"; file.PixelFormatFlags |= DirectDrawPixelFormatFlags.FourCC; break; case HaloBitmap.BitmapFormat.Dxt3: file.RgbBitCount = 0; file.FourCC = "DXT3"; file.PixelFormatFlags |= DirectDrawPixelFormatFlags.FourCC; break; case HaloBitmap.BitmapFormat.Dxt5: file.RgbBitCount = 0; file.FourCC = "DXT5"; file.PixelFormatFlags |= DirectDrawPixelFormatFlags.FourCC; break; case HaloBitmap.BitmapFormat.V8u8: file.RgbBitCount = 16; file.PixelFormatFlags = DirectDrawPixelFormatFlags.VU; break; default: file.RgbBitCount = (uint)bitmapFormat_GetBitCount(bitmap.Format); break; } uint aMask = 0, rMask = 0, gMask = 0, bMask = 0; bitmapFormat_GetBitMask(bitmap.Format, out aMask, out rMask, out bMask, out gMask); file.AlphaBitmask = aMask; file.RedBitmask = rMask; file.GreenBitmask = gMask; file.BlueBitmask = bMask; //Setup Bits switch (bitmap.Format) { case HaloBitmap.BitmapFormat.A8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.AlphaPixels; break; case HaloBitmap.BitmapFormat.Y8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.Luminance; break; case HaloBitmap.BitmapFormat.Ay8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.AlphaPixels; break; case HaloBitmap.BitmapFormat.G8b8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.AlphaLuminance; break; case HaloBitmap.BitmapFormat.A8y8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.AlphaLuminance; break; case HaloBitmap.BitmapFormat.R5g6b5: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.Rgb; break; case HaloBitmap.BitmapFormat.A4r4g4b4: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.Argb; break; case HaloBitmap.BitmapFormat.X8r8g8b8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.Rgb; break; case HaloBitmap.BitmapFormat.A8r8g8b8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.Argb; break; } //Prepare File Data int mapWidth = (int)width, mapHeight = (int)height; file.Data = new byte[bitmap.RawLengths[0]]; using (MemoryStream ds = new MemoryStream(file.Data)) using (MemoryStream ms = new MemoryStream(bitmap_LoadData(bitmapIndex, 0))) using (BinaryWriter writer = new BinaryWriter(ds)) using (BinaryReader reader = new BinaryReader(ms)) for (int i = 0; i <= bitmap.MipmapCount; i++) { byte[] data = reader.ReadBytes(bitmap_GetLength(bitmap.Format, mapWidth, mapHeight)); if (data.Length > 0) { writer.Write(swizzled ? Swizzler.Swizzle(data, mapWidth, mapHeight, (int)depth, (int)file.RgbBitCount, swizzled) : data); } mapWidth /= 2; mapHeight /= 2; } //Save file.Save(filename); } }
private void dumpTexturesToolStripButton_Click(object sender, EventArgs e) { //Check if (bitmap == null) { return; } //Prepare string directory = string.Empty; bool ok = false; //Initialize using (FolderBrowserDialog folderDlg = new FolderBrowserDialog()) { //Setup folderDlg.Description = "Select directory to dump textures."; //Show if (folderDlg.ShowDialog() == DialogResult.OK) { directory = folderDlg.SelectedPath; ok = true; } } //Check if (ok) { //Prepare HaloBitmap.BitmapProperties bitmap = null; string[] parts = this.bitmap.Entry.Filename.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); string filename = Path.Combine(directory, $"{parts[parts.Length - 1]}_{{0}}.dds"); //Loop for (int b = 0; b < this.bitmap.BitmapCount; b++) { //Get Bitmap bitmap = this.bitmap.Bitmaps[b]; uint width = bitmap.Width, height = bitmap.Height, depth = bitmap.Depth; bool swizzled = (bitmap.Flags & HaloBitmap.BitmapFlags.Swizzled) == HaloBitmap.BitmapFlags.Swizzled; if ((bitmap.Flags & HaloBitmap.BitmapFlags.PowTwoDimensions) == 0 && bitmap.MipmapCount == 0) { width = (uint)Math.Ceiling(width / 16f) * 16; //Pad width to 16 for some ungodly reason } //Setup DDS file DdsFile file = new DdsFile(); file.Width = width; file.Height = height; file.MipmapCount = bitmap.MipmapCount; file.DefinitionFlags |= DirectDrawSurfaceDefinitionFlags.PixelFormat | DirectDrawSurfaceDefinitionFlags.Width | DirectDrawSurfaceDefinitionFlags.Height | DirectDrawSurfaceDefinitionFlags.Caps; file.Caps |= DirectDrawCaps.Texture; file.PitchOrLinearSize = (uint)bitmap_GetLength(bitmap.Format, bitmap.Width, bitmap.Height); file.DefinitionFlags |= DirectDrawSurfaceDefinitionFlags.LinearSize; if (file.MipmapCount > 0) { file.Caps |= DirectDrawCaps.Mipmap | DirectDrawCaps.Complex; file.DefinitionFlags |= DirectDrawSurfaceDefinitionFlags.MipmapCount; } //Setup Pixel Format switch (bitmap.Format) { case HaloBitmap.BitmapFormat.Dxt1: file.RgbBitCount = 0; file.FourCC = "DXT1"; file.PixelFormatFlags |= DirectDrawPixelFormatFlags.FourCC; break; case HaloBitmap.BitmapFormat.Dxt3: file.RgbBitCount = 0; file.FourCC = "DXT3"; file.PixelFormatFlags |= DirectDrawPixelFormatFlags.FourCC; break; case HaloBitmap.BitmapFormat.Dxt5: file.RgbBitCount = 0; file.FourCC = "DXT5"; file.PixelFormatFlags |= DirectDrawPixelFormatFlags.FourCC; break; case HaloBitmap.BitmapFormat.V8u8: file.RgbBitCount = 16; file.PixelFormatFlags = DirectDrawPixelFormatFlags.VU; break; default: file.RgbBitCount = (uint)bitmapFormat_GetBitCount(bitmap.Format); break; } uint aMask = 0, rMask = 0, gMask = 0, bMask = 0; bitmapFormat_GetBitMask(bitmap.Format, out aMask, out rMask, out bMask, out gMask); file.AlphaBitmask = aMask; file.RedBitmask = rMask; file.GreenBitmask = gMask; file.BlueBitmask = bMask; //Setup Bits switch (bitmap.Format) { case HaloBitmap.BitmapFormat.A8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.AlphaPixels; break; case HaloBitmap.BitmapFormat.Y8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.Luminance; break; case HaloBitmap.BitmapFormat.Ay8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.AlphaPixels; break; case HaloBitmap.BitmapFormat.G8b8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.AlphaLuminance; break; case HaloBitmap.BitmapFormat.A8y8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.AlphaLuminance; break; case HaloBitmap.BitmapFormat.R5g6b5: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.Rgb; break; case HaloBitmap.BitmapFormat.A4r4g4b4: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.Argb; break; case HaloBitmap.BitmapFormat.X8r8g8b8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.Rgb; break; case HaloBitmap.BitmapFormat.A8r8g8b8: file.PixelFormatFlags |= DirectDrawPixelFormatFlags.Argb; break; } //Prepare File Data int mapWidth = (int)width, mapHeight = (int)height; file.Data = new byte[bitmap.RawLengths[0]]; using (MemoryStream ds = new MemoryStream(file.Data)) using (MemoryStream ms = new MemoryStream(bitmap_LoadData(b, 0))) using (BinaryWriter writer = new BinaryWriter(ds)) using (BinaryReader reader = new BinaryReader(ms)) for (int i = 0; i <= bitmap.MipmapCount; i++) { byte[] data = reader.ReadBytes(bitmap_GetLength(bitmap.Format, mapWidth, mapHeight)); if (data.Length > 0) { writer.Write(swizzled ? Swizzler.Swizzle(data, mapWidth, mapHeight, (int)depth, (int)file.RgbBitCount, swizzled) : data); } mapWidth /= 2; mapHeight /= 2; } //Save file.Save(string.Format(filename, b)); } } }
/// <summary> /// This post process creates DirectX texture objects. /// </summary> public override void DoPostProcess() { // do the base post processing base.DoPostProcess(); // init variables int count = bitmapValues.Bitmaps.Count; textures = new BaseTexture[count]; ResourceType type = ParseType(bitmapValues.Type.Value); DirectDrawSurfaceHeader ddsHeader = new DirectDrawSurfaceHeader(); // create size array int position = 0; int[] sizes = new int[count]; for (int i = 0; i < count - 1; i++) { sizes[i] = bitmapValues.Bitmaps[i + 1].PixelsOffset.Value - position; position += sizes[i]; } sizes[count - 1] = bitmapValues.ProcessedPixelData.Binary.Length - position; // create textures for (int i = 0; i < count; i++) { short displayMipCount = bitmapValues.Bitmaps[i].MipmapCount.Value; if (type == ResourceType.Textures) { displayMipCount = (short)Math.Max(1, displayMipCount - 2); // HACK: this prevents blackness taking over when we retreat from textures } Format format = ParseFormat(bitmapValues.Bitmaps[i].Format.Value); BinaryWriter memWriter = ddsHeader.CreateMemoryStream(format == Format.P8 ? Format.A8R8G8B8 : format, bitmapValues.Bitmaps[i].Width.Value, bitmapValues.Bitmaps[i].Height.Value, bitmapValues.Bitmaps[i].Depth.Value, displayMipCount, type == ResourceType.CubeTexture); int bitsPerPixel = format == Format.P8 ? 8 : ddsHeader.BitCount; byte[] raw = new byte[sizes[i]]; Array.Copy(bitmapValues.ProcessedPixelData.Binary, bitmapValues.Bitmaps[i].PixelsOffset.Value, raw, 0, sizes[i]); if (type == ResourceType.CubeTexture) { raw = ReorderCubeTexture(raw, bitmapValues.Bitmaps[i].Width.Value, bitmapValues.Bitmaps[i].Height.Value, bitmapValues.Bitmaps[i].MipmapCount.Value, bitsPerPixel); } if ((bitmapValues.Bitmaps[i].Flags.Value & SwizzledBit) != 0) { raw = Swizzler.Swizzle(raw, bitmapValues.Bitmaps[i].Width.Value, bitmapValues.Bitmaps[i].Height.Value, bitmapValues.Bitmaps[i].Depth.Value, bitsPerPixel, /* i seem to remember this being right */ (bitmapValues.Bitmaps[i].Flags.Value & PalettizedBit) != 0); } if ((bitmapValues.Bitmaps[i].Flags.Value & PalettizedBit) != 0) { raw = DePalettize(raw, ref bitsPerPixel); } memWriter.Write(raw); memWriter.Write(new byte[Compression.Pad(sizes[i], 0x80)]); memWriter.BaseStream.Position = 0; if (type == ResourceType.Textures) { textures[i] = TextureLoader.FromStream(MdxRender.Device, memWriter.BaseStream); } else if (type == ResourceType.CubeTexture) { textures[i] = TextureLoader.FromCubeStream(MdxRender.Device, memWriter.BaseStream); } else if (type == ResourceType.VolumeTexture) { textures[i] = TextureLoader.FromVolumeStream(MdxRender.Device, memWriter.BaseStream); } else { throw new HaloException("Unsupported texture type: {0}.", type); } // DEBUG: //TextureLoader.Save(System.Windows.Forms.Application.StartupPath + "\\texture dump\\" + Path.GetFileNameWithoutExtension(Name) + '[' + i.ToString() + "].dds", ImageFileFormat.Dds, textures[i]); } }
public static byte[] DecodeToDDS(GNFTexture texture) { var imageFormat = ImageEngineFormat.DDS_DXT5; var dx10ImageFormat = DDS_Header.DXGI_FORMAT.DXGI_FORMAT_UNKNOWN; switch (texture.SurfaceFormat) { case GNF.SurfaceFormat.BC1: imageFormat = ImageEngineFormat.DDS_DXT1; break; case GNF.SurfaceFormat.BC2: imageFormat = ImageEngineFormat.DDS_DXT2; break; case GNF.SurfaceFormat.BC3: imageFormat = ImageEngineFormat.DDS_DXT5; break; case GNF.SurfaceFormat.BC4: imageFormat = ImageEngineFormat.DDS_ATI1; break; case GNF.SurfaceFormat.BC5: imageFormat = ImageEngineFormat.DDS_ATI2_3Dc; break; case GNF.SurfaceFormat.BC6: imageFormat = ImageEngineFormat.DDS_DX10; dx10ImageFormat = DDS_Header.DXGI_FORMAT.DXGI_FORMAT_BC6H_UF16; break; case GNF.SurfaceFormat.BC7: imageFormat = ImageEngineFormat.DDS_DX10; switch (texture.ChannelType) { case ChannelType.Srgb: dx10ImageFormat = DDS_Header.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB; break; default: dx10ImageFormat = DDS_Header.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM; break; } break; } var ddsHeaderSize = 0x80; if (dx10ImageFormat != DDS_Header.DXGI_FORMAT.DXGI_FORMAT_UNKNOWN) { ddsHeaderSize += 20; } var ddsBytes = new byte[ddsHeaderSize + texture.Data.Length]; // create & write header var ddsHeader = new DDS_Header(1, texture.Height, texture.Width, imageFormat, dx10ImageFormat); ddsHeader.WriteToArray(ddsBytes, 0); // unswizzle var data = Swizzler.UnSwizzle(texture.Data, texture.Width, texture.Height, imageFormat == ImageEngineFormat.DDS_DXT1 ? 8 : 16, SwizzleType.PS4); // write pixel data Array.Copy(data, 0, ddsBytes, ddsHeaderSize, texture.Data.Length); return(ddsBytes); }