public DDSFile ReadDDSFile(BinaryReader binaryReader) { DDSFile ddsFile = new DDSFile(); var magicNumber = BitConverter.ToUInt32(binaryReader.ReadBytes(Marshal.SizeOf(Constants.DDSMagicNumber))); if (magicNumber != Constants.DDSMagicNumber) { throw new InvalidOperationException("Unrecognizable DDS file format."); } // read header info var headerData = binaryReader.ReadBytes(Marshal.SizeOf(typeof(DDSHeader))); // Read the header data directly into a DDS file header structure GCHandle handle = GCHandle.Alloc(headerData, GCHandleType.Pinned); ddsFile.DDSHeader = (DDSHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(DDSHeader)); handle.Free(); var mainImageSize = Math.Max(1, (ddsFile.DDSHeader.Width + 3) / 4) * Math.Max(1, (ddsFile.DDSHeader.Height + 3) / 4) * 8; if (mainImageSize != ddsFile.DDSHeader.PitchOrLinearSize && ddsFile.DDSHeader.PitchOrLinearSize != 0) { throw new InvalidOperationException("Parsing wrong, check DDS file."); } ddsFile.Data = binaryReader.ReadAllBytes(); return(ddsFile); }
public override object Preview() { var data = this.GetChildNode <TextureData>(); if (data == null) { return(null); } var memory = new MemoryStream(); memory.Write(data.Data, 0, data.Data.Length); memory.Seek(0, SeekOrigin.Begin); try { var dds = new DDSFile(); dds.Deserialize(memory); return(dds.Image()); } catch (FormatException) { return(null); } }
private void importImageAsTile8bitToolStripMenuItem_Click(object sender, EventArgs e) { using (OpenFileDialog dlg = new OpenFileDialog()) { dlg.Title = "Import Image As Tile"; dlg.DefaultExt = "dds"; dlg.Filter = "DDS Image Files (*.dds)|*.dds|All files (*.*)|*.*"; if (dlg.ShowDialog() == DialogResult.OK) { Cursor saveCursor = this.Cursor; this.Cursor = Cursors.WaitCursor; TileMaker tm = new TileMaker(dlg.FileName, 4); dds = new DDSFile32(tm.Width, tm.Height); tm.FillTile(dds); currentTileName = dlg.FileName; // grab colors from tilemaker for (int i = 0; i < 4; i++) { fileColors[i] = baseColors[i] = tm.Colors[i].HSVColor; } UpdateButtons(); ColorizeTile(); this.Cursor = saveCursor; } } }
static void Update(string fileName) { string dir = fileName.Substring(0, fileName.Length - 4); if (Directory.Exists(dir)) { VDriveMibFile outfile = new VDriveMibFile(fileName); foreach (var item in outfile.Entries) { if (item.isDDS) { DDSFile dds = new DDSFile(); if (dds.ReadData(string.Format("{0}/{1}.dds", dir, item.InternalID))) { item.UpdateFromDDS(dds); } } } outfile.UpdateOffsets(); outfile.WriteFile(fileName); } else { Console.WriteLine("Dump the file first"); } }
private bool repackFile(TPF.Texture tpfEntry, string name, string baseDir, string subDir) { string inputPath = baseDir + "\\" + subDir + "\\" + name + ".dds"; //DBGTEX_DETAIL crashes this, what in the heck if (inputPath != null && File.Exists(inputPath) && name != "DBGTEX_DETAIL") { byte[] inputBytes = File.ReadAllBytes(inputPath); DXGIFormat originalFormat = DDSFile.Read(new MemoryStream(tpfEntry.Bytes)).Format; DXGIFormat newFormat = DDSFile.Read(new MemoryStream(inputBytes)).Format; if (originalFormat != DXGIFormat.Unknown && newFormat != DXGIFormat.Unknown && originalFormat != newFormat) { byte[] newBytes = convertFile(inputPath, originalFormat); if (newBytes != null) { inputBytes = newBytes; } } tpfEntry.Bytes = inputBytes; return(true); } else { return(false); } }
private void UpdateButton_Click(object sender, EventArgs e) { var str = MIBFileNames[MIBFiles.SelectedIndex]; var dir = string.Format("{0}/{1}", textBox1.Text, str.Substring(0, str.Length - 4)); if (Directory.Exists(dir)) { if (currentMIB != null) { foreach (var item in currentMIB.Entries) { if (item.isDDS) { DDSFile dds = new DDSFile(); if (dds.ReadData(string.Format("{0}/{1}.dds", dir, item.InternalID))) { item.UpdateFromDDS(dds); } } } currentMIB.UpdateOffsets(); currentMIB.WriteFile(string.Format("{0}.mib", dir)); } } }
public UnpackReportFile(TPF.Texture tex) { using (var ms = new MemoryStream(tex.Bytes)) using (var dds = DDSFile.Read(ms)) { Name = tex.Name; Format = dds?.Format ?? DXGIFormat.Unknown; Width = dds?.MipChains[0][0].Width ?? -1; Height = dds?.MipChains[0][0].Height ?? -1; } }
public static int GetTpfFormatFromDdsBytes(FBX2FLVERImporter importer, string texName, byte[] ddsBytes) { using (var ddsStream = new MemoryStream(ddsBytes)) { DXGIFormat format = DDSFile.Read(ddsStream).Format; switch (format) { //DSR: case DXGIFormat.BC1_UNorm: case DXGIFormat.BC1_UNorm_SRGB: return(0); case DXGIFormat.BC2_UNorm: case DXGIFormat.BC2_UNorm_SRGB: return(3); case DXGIFormat.BC3_UNorm: case DXGIFormat.BC3_UNorm_SRGB: return(5); case DXGIFormat.R16G16_Float: return(35); case DXGIFormat.BC5_UNorm: return(36); case DXGIFormat.BC6H_UF16: return(37); case DXGIFormat.BC7_UNorm: case DXGIFormat.BC7_UNorm_SRGB: return(38); //DS3: //case DXGIFormat.B5G5R5A1_UNorm: // return 6; //case DXGIFormat.B8G8R8A8_UNorm: //case DXGIFormat.B8G8R8A8_UNorm_SRGB: // return 9; //case DXGIFormat.B8G8R8X8_UNorm: //case DXGIFormat.B8G8R8X8_UNorm_SRGB: // return 10; //case DXGIFormat.R16G16B16A16_Float: // return 22; default: importer.PrintWarning($"Texture \"{texName}\" has an unrecognized" + $" DDS format type ({format.ToString()}) and will likely appear garbled ingame. " + $"For greatest compatibility, use DXT1 (aka BC1_UNorm) or DXT5 (aka BC3_UNorm) " + $"for your textures."); return(0); } } }
private bool repackFile(TPF.Texture tpfEntry, string name, string baseDir, string subDir) { string inputPath = getSwappedPath(name, subDir, out bool dds); if (inputPath != null && File.Exists(inputPath)) { byte[] inputBytes = File.ReadAllBytes(inputPath); DXGIFormat originalFormat = DDSFile.Read(new MemoryStream(tpfEntry.Bytes)).Format; if (originalFormat == DXGIFormat.Unknown) { appendError("Error: {0}\r\n\u2514\u2500 Could not determine format of game file.", subDir + "\\" + name + ".dds"); } bool convert = !dds; if (dds) { DXGIFormat newFormat = DDSFile.Read(new MemoryStream(inputBytes)).Format; if (newFormat == DXGIFormat.Unknown) { appendError("Error: {0}\r\n\u2514\u2500 Could not determine format of override file.", inputPath); } if (originalFormat != DXGIFormat.Unknown && newFormat != DXGIFormat.Unknown && originalFormat != newFormat) { convert = true; } } if (convert) { byte[] newBytes = convertFile(inputPath, originalFormat); if (newBytes != null) { inputBytes = newBytes; } } tpfEntry.Bytes = inputBytes; lock (countLock) textureCount++; return(true); } else { return(false); } }
public static byte GetTpfFormatFromDdsBytes(byte[] ddsBytes) { using (var ddsStream = new MemoryStream(ddsBytes)) { DXGIFormat format = DDSFile.Read(ddsStream).Format; switch (format) { //DSR: case DXGIFormat.BC1_UNorm: case DXGIFormat.BC1_UNorm_SRGB: return(0); case DXGIFormat.BC2_UNorm: case DXGIFormat.BC2_UNorm_SRGB: return(3); case DXGIFormat.BC3_UNorm: case DXGIFormat.BC3_UNorm_SRGB: return(5); case DXGIFormat.R16G16_Float: return(35); case DXGIFormat.BC5_UNorm: return(36); case DXGIFormat.BC6H_UF16: return(37); case DXGIFormat.BC7_UNorm: case DXGIFormat.BC7_UNorm_SRGB: return(38); //DS3: //case DXGIFormat.B5G5R5A1_UNorm: // return 6; //case DXGIFormat.B8G8R8A8_UNorm: //case DXGIFormat.B8G8R8A8_UNorm_SRGB: // return 9; //case DXGIFormat.B8G8R8X8_UNorm: //case DXGIFormat.B8G8R8X8_UNorm_SRGB: // return 10; //case DXGIFormat.R16G16B16A16_Float: // return 22; default: return(0); } } }
private void loadTileToolStripMenuItem_Click(object sender, EventArgs e) { using (OpenFileDialog dlg = new OpenFileDialog()) { dlg.Title = "Load Tile"; dlg.DefaultExt = "dds"; dlg.Filter = "DDS Image Files (*.dds)|*.dds|All files (*.*)|*.*"; if (dlg.ShowDialog() == DialogResult.OK) { currentTileName = dlg.FileName; dds = DDSFile.LoadFile(dlg.FileName); ColorizeTile(); } } }
private void DdsToBitmap_Click(object sender, RoutedEventArgs e) { //check if it's actually a dds file bool isItADDSFile = DDSFile.IsDDSFile("damageIndicator.dds"); Bitmap bmp = null; //helpful links //https://docs.microsoft.com/en-us/windows/desktop/api/dxgiformat/ne-dxgiformat-dxgi_format#dxgi-format-bc3-unorm //https://docs.microsoft.com/en-us/windows/desktop/direct3d11/texture-block-compression-in-direct3d-11#bc1-bc2-and-b3-formats //best method found to use mode 1 and direct=true bool directBitmap = true; //TEXIMP DDSFILE //this is an Importer and says nothing about bitmap objects. i don't think it's designed to do this (load directly and make bitmap out of) //TEXIMP SURFACE //https://bitbucket.org/Starnick/teximpnet/src/acf2d0a8d7f6?at=master //format of image is Rgba32 using (Surface surface = Surface.LoadFromFile("damageIndicator.dds", ImageLoadFlags.Default)) { surface.FlipVertically(); if (directBitmap) { //https://stackoverflow.com/questions/16478449/convert-intptr-to-bitmapimage bmp = new Bitmap(surface.Width, surface.Height, surface.Pitch, System.Drawing.Imaging.PixelFormat.Format32bppArgb, surface.DataPtr); } else { //stride is rowpitch //length of array is height * stride/pitch int size = surface.Height * surface.Pitch; byte[] managedArrayy = new byte[size]; //https://stackoverflow.com/questions/5486938/c-sharp-how-to-get-byte-from-intptr //https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.copy?view=netframework-4.8#System_Runtime_InteropServices_Marshal_Copy_System_IntPtr_System_Byte___System_Int32_System_Int32_ Marshal.Copy(surface.DataPtr, managedArrayy, 0, size); BitmapSource source = BitmapSource.Create(surface.Width, surface.Height, 96.0, 96.0, PixelFormats.Bgra32, null, managedArrayy, surface.Pitch); bmp = BitmapFromSource(source); //TestImageDisplay.Source = source; } bmp.Save("damageIndicator.png", System.Drawing.Imaging.ImageFormat.Png); bmp.Dispose(); } }
public void WriteDDSFile(string fileName, BMPFile bmpFile, BC1CompressionFormat compressionFormat) { using (BinaryWriter writer = new BinaryWriter(File.Open(fileName, FileMode.Create))) { var ddsFile = new DDSFile(); writer.Write(Constants.DDSMagicNumber); //create default header ddsFile.DDSHeader = CreateHeader((int)bmpFile.BMPFileInfoHeader.Width, (int)bmpFile.BMPFileInfoHeader.Height, Helpers.BC1Unorm()); var headerSize = Marshal.SizeOf(typeof(DDSHeader)); var headerBuffer = new byte[headerSize]; // Populate header data directly from the bytebuffer GCHandle handle = GCHandle.Alloc(headerBuffer, GCHandleType.Pinned); Marshal.StructureToPtr(ddsFile.DDSHeader, handle.AddrOfPinnedObject(), true); handle.Free(); writer.Write(headerBuffer); ddsFile.Data = new byte[ddsFile.DDSHeader.PitchOrLinearSize]; int numberOfPixels = (int)ddsFile.DDSHeader.Width * (int)ddsFile.DDSHeader.Height; int numberOfRequiredBlocks = numberOfPixels / Constants.TexelCount; int bufferSize = numberOfRequiredBlocks * Constants.BC1ByteSize; ddsFile.Data = new byte[bufferSize]; int numberOfVerticalBlocks = (int)bmpFile.BMPFileInfoHeader.Height / Constants.BlockDimension; int numberOfHorizontalBlocks = (int)bmpFile.BMPFileInfoHeader.Width / Constants.BlockDimension; int numberOfBlocks = numberOfVerticalBlocks * numberOfHorizontalBlocks; for (int i = 0; i < numberOfBlocks; ++i) { var blockIndex = Helpers.ToColumnMajor(i, numberOfHorizontalBlocks); var blockColors = bmpFile.GetBlockColors(blockIndex); var blockData = compressionFormat.Compress(blockColors); ddsFile.SetBlockData(blockIndex, blockData); } writer.Write(ddsFile.Data); } }
public static BitmapTextureInteropResource CreateBitmapResourceFromDDS(GameCache cache, DDSFile file) { BitmapTextureInteropResource result = BitmapUtils.CreateEmptyBitmapTextureInteropResource(); if (cache is GameCacheHaloOnlineBase) { // TODO: for cubemaps, fix mipmap order to d3d9 expected order result.Texture.Definition.PrimaryResourceData = new TagData(file.BitmapData); result.Texture.Definition.Bitmap = BitmapUtils.CreateBitmapTextureInteropDefinition(file.Header); } else if (cache.GetType() == typeof(GameCacheGen3)) { // need to do some serious conversion, might be better to require an uncompressed input throw new NotImplementedException(); } return(result); }
public override bool Compile(GameAssetType gameAsset, Uri baseUri, BinaryAsset asset, XmlNode node, GameDefinition game, string trace, ref int position, out string ErrorDescription) { List <TerrainTextureTileRuntime> tiles = new List <TerrainTextureTileRuntime>(); int atlasSize = 2048; /*foreach (XmlAttribute attribute in node.Attributes) * { * switch (attribute.Name) * { * case "AtlasSize": * atlasSize = ushort.Parse(attribute.Value); * break; * } * }*/ List <XmlNode> nodes = new List <XmlNode>(); foreach (XmlNode childNode in node.ChildNodes) { if (childNode.Name == "Tile") { nodes.Add(childNode); } } FileHelper.SetInt(nodes.Count, 4, asset.Content); BinaryAsset tileList = new BinaryAsset(12 * nodes.Count); asset.SubAssets.Add(8, tileList); DDSFile[,] textureList = new DDSFile[nodes.Count, 2]; BinaryAsset baseAsset = new BinaryAsset(0); BinaryAsset normalAsset = new BinaryAsset(0); uint positionX = 16; uint positionY = 16; uint nextY = 0; for (int idx = 0; idx < nodes.Count; ++idx) { FileHelper.SetUInt(uint.Parse(nodes[idx].Attributes["TextureID"].Value), idx * 12, tileList.Content); string baseTexture = nodes[idx].Attributes["BaseTexture"].Value; baseTexture = baseTexture.Substring(baseTexture.LastIndexOf(Path.DirectorySeparatorChar) + 1); baseTexture = baseTexture.Substring(baseTexture.LastIndexOf('/') + 1); baseTexture = baseTexture.Substring(0, baseTexture.LastIndexOf('.')); string baseTexturePath = Macro.Terrain + baseTexture + ".dds"; if (!IOFile.Exists(baseTexturePath)) { ErrorDescription = string.Format("{0} doesn't exist.", baseTexturePath); return(false); } using (FileStream textureStream = new FileStream(baseTexturePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (BinaryReader textureReader = new BinaryReader(textureStream)) { textureList[idx, 0] = new DDSFile(textureReader.ReadBytes((int)(textureStream.Length))); } } string normalTexture = nodes[idx].Attributes["NormalTexture"].Value; normalTexture = normalTexture.Substring(normalTexture.LastIndexOf(Path.DirectorySeparatorChar) + 1); normalTexture = normalTexture.Substring(normalTexture.LastIndexOf('/') + 1); normalTexture = normalTexture.Substring(0, normalTexture.LastIndexOf('.')); string normalTexturePath = Macro.Terrain + normalTexture + ".dds"; if (!IOFile.Exists(normalTexturePath)) { ErrorDescription = string.Format("{0} doesn't exist.", normalTexturePath); return(false); } using (FileStream textureStream = new FileStream(normalTexturePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (BinaryReader textureReader = new BinaryReader(textureStream)) { textureList[idx, 1] = new DDSFile(textureReader.ReadBytes((int)(textureStream.Length))); } } } // For now assume each texture has the same size. atlasSize = (int)textureList[0, 0].Header.Width + 32; atlasSize *= atlasSize * (textureList.Length >> 1); atlasSize = (int)Math.Sqrt((double)atlasSize); --atlasSize; atlasSize |= atlasSize >> 1; atlasSize |= atlasSize >> 2; atlasSize |= atlasSize >> 4; atlasSize |= atlasSize >> 8; ++atlasSize; byte[] baseContent = new byte[atlasSize * atlasSize * 4]; byte[] normalContent = new byte[atlasSize * atlasSize * 4]; for (int tileIdx = 0; tileIdx < textureList.Length >> 1; ++tileIdx) { uint size = textureList[tileIdx, 0].Header.Width; if (positionX + size + 16 > atlasSize) { positionX = 16; positionY += nextY; } byte[] color = textureList[tileIdx, 0].Content.GetColor(size, size); byte[] normal = textureList[tileIdx, 1].Content.GetColor(size, size); for (int idy = -16; idy < size + 16; ++idy) { for (int idx = -16; idx < size + 16; ++idx) { int tileY = idy; if (tileY < 0) { tileY = (int)(size + tileY); } else if (tileY >= size) { tileY = (int)(tileY - size); } int tileX = idx; if (tileX < 0) { tileX = (int)(size + tileX); } else if (tileX >= size) { tileX = (int)(tileX - size); } baseContent[(positionY + idy) * atlasSize * 4 + (positionX + idx) * 4] = color[tileY * size * 4 + tileX * 4]; baseContent[(positionY + idy) * atlasSize * 4 + (positionX + idx) * 4 + 1] = color[tileY * size * 4 + tileX * 4 + 1]; baseContent[(positionY + idy) * atlasSize * 4 + (positionX + idx) * 4 + 2] = color[tileY * size * 4 + tileX * 4 + 2]; baseContent[(positionY + idy) * atlasSize * 4 + (positionX + idx) * 4 + 3] = color[tileY * size * 4 + tileX * 4 + 3]; normalContent[(positionY + idy) * atlasSize * 4 + (positionX + idx) * 4] = normal[tileY * size * 4 + tileX * 4]; normalContent[(positionY + idy) * atlasSize * 4 + (positionX + idx) * 4 + 1] = normal[tileY * size * 4 + tileX * 4 + 1]; normalContent[(positionY + idy) * atlasSize * 4 + (positionX + idx) * 4 + 2] = normal[tileY * size * 4 + tileX * 4 + 2]; normalContent[(positionY + idy) * atlasSize * 4 + (positionX + idx) * 4 + 3] = normal[tileY * size * 4 + tileX * 4 + 3]; } } FileHelper.SetUShort((ushort)positionX, 12 * tileIdx + 4, tileList.Content); FileHelper.SetUShort((ushort)positionY, 12 * tileIdx + 6, tileList.Content); FileHelper.SetUShort((ushort)(positionX + size), 12 * tileIdx + 8, tileList.Content); FileHelper.SetUShort((ushort)(positionY + size), 12 * tileIdx + 10, tileList.Content); positionX += size + 32; nextY = Math.Max(size + 32, nextY); } bool hasAlpha = false; for (int idx = 0; idx < nodes.Count; ++idx) { if (textureList[idx, 0].HasAlpha()) { hasAlpha = true; break; } } DDSFile baseAtlas = null; if (hasAlpha) { baseAtlas = new DDSFile((uint)atlasSize, (uint)atlasSize, 5, DDSType.DXT5, baseContent); } else { baseAtlas = new DDSFile((uint)atlasSize, (uint)atlasSize, 5, DDSType.DXT1, baseContent); } hasAlpha = false; for (int idx = 0; idx < nodes.Count; ++idx) { if (textureList[idx, 1].HasAlpha()) { hasAlpha = true; break; } } DDSFile normalAtlas = null; if (hasAlpha) { normalAtlas = new DDSFile((uint)atlasSize, (uint)atlasSize, 5, DDSType.A1R5G5B5, normalContent, true); } else { normalAtlas = new DDSFile((uint)atlasSize, (uint)atlasSize, 5, DDSType.R5G5B5, normalContent, true); } baseAsset.Content = baseAtlas.Binary; asset.SubAssets.Add(0x0C, baseAsset); FileHelper.SetInt(baseAsset.Content.Length, 0x10, asset.Content); normalAsset.Content = normalAtlas.Binary; asset.SubAssets.Add(0x14, normalAsset); FileHelper.SetInt(normalAsset.Content.Length, 0x18, asset.Content); ErrorDescription = string.Empty; return(true); }
private void WriteBMPFile(string fileName, DDSFile ddsFile, BC1CompressionFormat compressionFormat) { using (BinaryWriter writer = new BinaryWriter(File.Open(fileName, FileMode.Create))) { byte[] BMPMagicNumber = { 0x42, 0x4D }; int BMPFileHeaderSize = 14; int BMPFileInfoHeaderSize = 40; int imageRawSize = (int)ddsFile.DDSHeader.Width * (int)ddsFile.DDSHeader.Height * 3; int fileSize = imageRawSize + BMPFileHeaderSize + BMPFileInfoHeaderSize; var bmpFile = new BMPFile(); bmpFile.BMPFileHeader = new BMPFileHeader(); bmpFile.BMPFileHeader.MagicHeader = BMPMagicNumber; bmpFile.BMPFileHeader.Reserved1 = 0; bmpFile.BMPFileHeader.Reserved2 = 0; bmpFile.BMPFileHeader.FileSize = (uint)fileSize; bmpFile.BMPFileHeader.OffToPixelArray = (uint)BMPFileHeaderSize + (uint)BMPFileInfoHeaderSize; bmpFile.BMPFileInfoHeader = new BMPFileInfoHeader(); bmpFile.BMPFileInfoHeader.HeaderSize = (uint)BMPFileInfoHeaderSize; bmpFile.BMPFileInfoHeader.Width = ddsFile.DDSHeader.Width; bmpFile.BMPFileInfoHeader.Height = ddsFile.DDSHeader.Height; bmpFile.BMPFileInfoHeader.ColorPlanes = 1; bmpFile.BMPFileInfoHeader.BitCount = 24; bmpFile.BMPFileInfoHeader.CompressionType = 0; bmpFile.BMPFileInfoHeader.RawDataSize = (uint)imageRawSize; bmpFile.BMPFileInfoHeader.HorizontalPixelPerMeter = 2835; bmpFile.BMPFileInfoHeader.VerticalPixelPerMeter = 2835; bmpFile.BMPFileInfoHeader.ColorsUsed = 0; bmpFile.BMPFileInfoHeader.ImportantColors = 0; writer.Write(bmpFile.BMPFileHeader.MagicHeader); writer.Write(bmpFile.BMPFileHeader.FileSize); writer.Write(bmpFile.BMPFileHeader.Reserved1); writer.Write(bmpFile.BMPFileHeader.Reserved2); writer.Write(bmpFile.BMPFileHeader.OffToPixelArray); writer.Write(bmpFile.BMPFileInfoHeader.HeaderSize); writer.Write(bmpFile.BMPFileInfoHeader.Width); writer.Write(bmpFile.BMPFileInfoHeader.Height); writer.Write(bmpFile.BMPFileInfoHeader.ColorPlanes); writer.Write(bmpFile.BMPFileInfoHeader.BitCount); writer.Write(bmpFile.BMPFileInfoHeader.CompressionType); writer.Write(bmpFile.BMPFileInfoHeader.RawDataSize); writer.Write(bmpFile.BMPFileInfoHeader.HorizontalPixelPerMeter); writer.Write(bmpFile.BMPFileInfoHeader.VerticalPixelPerMeter); writer.Write(bmpFile.BMPFileInfoHeader.ColorsUsed); writer.Write(bmpFile.BMPFileInfoHeader.ImportantColors); bmpFile.PixelData = new byte[imageRawSize]; int numberOfVerticalBlocks = (int)ddsFile.DDSHeader.Height / Constants.BlockDimension; int numberOfHorizontalBlocks = (int)ddsFile.DDSHeader.Width / Constants.BlockDimension; int numberOfBlocks = numberOfVerticalBlocks * numberOfHorizontalBlocks; for (int i = 0; i < numberOfBlocks; ++i) { var blockIndex = Helpers.ToColumnMajor(i, numberOfHorizontalBlocks); var blockData = ddsFile.GetBlockData(blockIndex); var blockColors = compressionFormat.Decompress(blockData); bmpFile.SetBlockColors(blockIndex, blockColors); } writer.Write(bmpFile.PixelData.FlipArrayHorizontal((int)bmpFile.BMPFileInfoHeader.Height)); } }
private void ModdedTexOpen() { moddedTexPathBox.Text = moddedTexPath; moddedTexOpen = true; if (!isWebImage) { texturePreview2.Image = null; } moddedFormat = "None"; // Check if file is dds or png if (DDSFile.IsDDSFile(moddedTexPath) == true) { // Get dds data DDSContainer moddedTexture = DDSFile.Read(moddedTexPath); moddedFormat = moddedTexture.Format.ToString(); moddedDDS.MipMaps = moddedTexture.MipChains[0].Count; if (moddedFormat == "BC3_UNorm") { moddedFormat = "DXT5"; } else if (moddedFormat == "BC1_UNorm") { moddedFormat = "DXT1"; } moddedDDS.Format = moddedFormat; // Convert to png for preview DDSImage modDDS = new DDSImage(moddedTexPath); MemoryStream pngStream = new MemoryStream(); modDDS.SaveAsPng(pngStream); var newPNG = Image.FromStream(pngStream); // Change labels moddedTexCompression.Text = moddedDDS.Format; mipMapCountLabel2.Text = moddedDDS.MipMaps.ToString(); texturePreview2.Image = newPNG; previewLabel2.Text = "Preview:"; moddedDDS.ResX = texturePreview2.Image.Width; moddedDDS.ResY = texturePreview2.Image.Height; resolutionCheck2.Text = moddedDDS.ResX.ToString() + "x" + moddedDDS.ResY.ToString(); texturePreview2.SizeMode = PictureBoxSizeMode.Zoom; // Dispose pngStream.Dispose(); moddedTexture.Dispose(); } else { // Bitmap/Png format if (moddedTexPath.Contains(".bmp")) { moddedTexCompression.Text = "None (Bitmap)"; } else if (moddedTexPath.Contains(".png")) { moddedTexCompression.Text = "None (PNG)"; } else { moddedTexCompression.Text = "None"; } mipMapCountLabel2.Text = "None"; previewLabel2.Text = "Preview:"; if (!isWebImage) { texturePreview2.Image = new Bitmap(moddedTexPath); texturePreview2.SizeMode = PictureBoxSizeMode.Zoom; } resolutionCheck2.Text = texturePreview2.Image.Width.ToString() + "x" + texturePreview2.Image.Height.ToString(); } EnableButtons(); }
static void DumpPixel(DDSFile dds, int x, int y) { Console.WriteLine("Pixel({0}, {1}) : 0x{2:x})", x, y, dds.GetPixel(x, y)); }
public override object Execute(List <string> args) { if (args.Count != 2) { return(false); } if (!int.TryParse(args[0], NumberStyles.HexNumber, null, out int imageIndex)) { return(false); } if (Bitmap.Images.Count == 0) { Bitmap.Flags = BitmapRuntimeFlags.UsingTagInteropAndTagResource; Bitmap.Images.Add(new Bitmap.Image { Signature = new Tag("bitm") }); Bitmap.Resources.Add(new TagResourceReference()); } if (imageIndex < 0 || imageIndex >= Bitmap.Images.Count) { Console.Error.WriteLine("Invalid image index."); return(true); } var imagePath = args[1]; Console.WriteLine("Importing image data..."); #if !DEBUG try { #endif DDSFile file = new DDSFile(); using (var imageStream = File.OpenRead(imagePath)) using (var reader = new EndianReader(imageStream)) { file.Read(reader); } var bitmapTextureInteropDefinition = BitmapInjector.CreateBitmapResourceFromDDS(Cache, file); var reference = Cache.ResourceCache.CreateBitmapResource(bitmapTextureInteropDefinition); // set the tag data Bitmap.Resources[imageIndex] = reference; Bitmap.Images[imageIndex] = BitmapUtils.CreateBitmapImageFromResourceDefinition(bitmapTextureInteropDefinition.Texture.Definition.Bitmap); using (var tagsStream = Cache.OpenCacheReadWrite()) Cache.Serialize(tagsStream, Tag, Bitmap); #if !DEBUG } catch (Exception ex) { Console.WriteLine("Importing image data failed: " + ex.Message); return(true); } #endif Console.WriteLine("Done!"); return(true); }
public TileMaker(string filename, int numColors) { dds = DDSFile.LoadFile(filename); int numPixels = dds.Width * dds.Height; HSVColor[] pixels = new HSVColor[numPixels]; // create the array of colors in this image int offset = 0; for (int y = 0; y < dds.Height; y++) { for (int x = 0; x < dds.Width; x++) { pixels[offset] = HSVColor.FromRGB(dds.GetPixel(x, y)); offset++; } } // compute the clustering km = new Kmeans(pixels, numColors); float[] minv = new float[numColors]; float[] maxv = new float[numColors]; for (int i = 0; i < numColors; i++) { minv[i] = float.MaxValue; maxv[i] = float.MinValue; } // compute min and max v for each color cluster for (int y = 0; y < dds.Height; y++) { for (int x = 0; x < dds.Width; x++) { HSVColor hsv = HSVColor.FromRGB(dds.GetPixel(x, y)); int index = km.ClosestIndex(hsv); // record min and max v for each channel float v = hsv.V; if (v < minv[index]) { minv[index] = v; } if (v > maxv[index]) { maxv[index] = v; } } } for (int i = 0; i < numColors; i++) { if (minv[i] == float.MaxValue) { minv[i] = 0.0f; } if (maxv[i] == float.MinValue) { maxv[i] = 0.0f; } ColorInfo ci = new ColorInfo(i, minv[i], maxv[i], km.CenterColors[i]); colors.Add(ci); } colors.Sort(); // create the mapping from the kmeans returned colors to the sorted colors kmColorMap = new int[numColors]; for (int i = 0; i < numColors; i++) { kmColorMap[colors[i].KMIndex] = i; } }
private void importImageAsTileToolStripMenuItem_Click(object sender, EventArgs e) { using (OpenFileDialog dlg = new OpenFileDialog()) { dlg.Title = "Import Image As Tile"; dlg.DefaultExt = "dds"; dlg.Filter = "DDS Image Files (*.dds)|*.dds|All files (*.*)|*.*"; if (dlg.ShowDialog() == DialogResult.OK) { Cursor saveCursor = this.Cursor; this.Cursor = Cursors.WaitCursor; TileMaker tm = new TileMaker(dlg.FileName, 4); dds = new DDSFile16(tm.Width, tm.Height); tm.FillTile(dds); currentTileName = dlg.FileName; // grab colors from tilemaker ResetAdjust(); for (int i = 0; i < 4; i++) { fileColors[i] = baseColors[i] = tm.Colors[i].HSVColor; } UpdateButtons(); ColorizeTile(); this.Cursor = saveCursor; } } }
static void Main(string[] args) { DDSFile dds = DDSFile.LoadFile(args[0]); int w = dds.Width; int h = dds.Height; int halfW = w / 2; int halfH = h / 2; if (dds.BitsPerPixel != 32) { Console.WriteLine("Error: input file must be 32-bits per pixel"); } DDSFile destDDS = new DDSFile32(w * 2, h * 2); // copy the various parts of the source to pad all edges destDDS.Copy(dds, halfW, halfH, halfW, halfH, 0, 0); destDDS.Copy(dds, 0, halfH, w, halfH, halfW, 0); destDDS.Copy(dds, 0, halfH, halfW, halfH, w + halfW, 0); destDDS.Copy(dds, halfW, 0, halfW, h, 0, halfH); destDDS.Copy(dds, 0, 0, w, h, halfW, halfH); destDDS.Copy(dds, 0, 0, halfW, h, w + halfW, halfH); destDDS.Copy(dds, halfW, 0, halfW, halfH, 0, h + halfH); destDDS.Copy(dds, 0, 0, w, halfH, halfW, h + halfH); destDDS.Copy(dds, 0, 0, halfW, halfH, w + halfW, h + halfH); // save the padded tile destDDS.Save(args[1]); DDSFile preview = new DDSFile32(halfW, halfH); for (int y = 0; y < halfH; y++) { for (int x = 0; x < halfW; x++) { uint p0 = dds.GetPixel(x * 2, y * 2); uint p1 = dds.GetPixel(x * 2 + 1, y * 2); uint p2 = dds.GetPixel(x * 2, y * 2 + 1); uint p3 = dds.GetPixel(x * 2 + 1, y * 2 + 1); uint r = ((p0 >> 16) & 0xff) + ((p1 >> 16) & 0xff) + ((p2 >> 16) & 0xff) + ((p3 >> 16) & 0xff); uint g = ((p0 >> 8) & 0xff) + ((p1 >> 8) & 0xff) + ((p2 >> 8) & 0xff) + ((p3 >> 8) & 0xff); uint b = ((p0 >> 0) & 0xff) + ((p1 >> 0) & 0xff) + ((p2 >> 0) & 0xff) + ((p3 >> 0) & 0xff); uint a = ((p0 >> 24) & 0xff) + ((p1 >> 24) & 0xff) + ((p2 >> 24) & 0xff) + ((p3 >> 24) & 0xff); uint high = r; uint highCol = 0xffffffff; if (g > high) { high = g; highCol = 0xff000000; } if (b > high) { high = b; highCol = 0xffaaaaaa; } if (a > high) { high = g; highCol = 0xff555555; } preview.SetPixel(x, y, highCol); } } preview.Save(args[2]); }
public void FillTile(DDSFile ddsDest) { for (int y = 0; y < dds.Height; y++) { for (int x = 0; x < dds.Width; x++) { HSVColor hsv = HSVColor.FromRGB(dds.GetPixel(x, y)); float[] distances = km.DistanceToCenters(hsv); int nearest, second; float nearestWeight; if (distances[0] < distances[1]) { nearest = 0; second = 1; } else { nearest = 1; second = 0; } if (distances[2] < distances[nearest]) { second = nearest; nearest = 2; } else if (distances[2] < distances[second]) { second = 2; } if (distances[3] < distances[nearest]) { second = nearest; nearest = 3; } else if (distances[3] < distances[second]) { second = 3; } // only weight between the two colors if the current point is nearer to each of them // than they are to each other. otherwise just weight to neartest. if (km.CenterDistances[nearest, second] < distances[second]) { nearestWeight = 1.0f; } else { nearestWeight = distances[second] / (distances[nearest] + distances[second]); } // init color components int[] components = new int[4]; components[0] = 0; components[1] = 0; components[2] = 0; components[3] = 0; nearest = kmColorMap[nearest]; second = kmColorMap[second]; components[nearest] = (int)(hsv.V * colors[nearest].VMult * 255 * nearestWeight); components[second] = (int)(hsv.V * colors[second].VMult * 255 * (1.0f - nearestWeight)); Color c = Color.FromArgb(components[3], components[0], components[1], components[2]); int index = kmColorMap[km.ClosestIndex(hsv)]; ddsDest.SetColor(x, y, c); } } }
public override bool Compile(GameAssetType gameAsset, Uri baseUri, BinaryAsset asset, XmlNode node, GameDefinition game, string trace, ref int position, out string ErrorDescription) { List <TerrainTextureTileRuntime> tiles = new List <TerrainTextureTileRuntime>(); List <XmlNode> nodes = new List <XmlNode>(); foreach (XmlNode childNode in node.ChildNodes) { if (childNode.Name == "Tile") { nodes.Add(childNode); } } FileHelper.SetInt(nodes.Count, 4, asset.Content); BinaryAsset tileList = new BinaryAsset(12 * nodes.Count); asset.SubAssets.Add(8, tileList); DDSFile[,] textureList = new DDSFile[nodes.Count, 2]; BinaryAsset baseAsset = new BinaryAsset(0); BinaryAsset normalAsset = new BinaryAsset(0); uint positionX = 16; uint positionY = 16; uint nextX = 0; for (int idx = 0; idx < nodes.Count; ++idx) { FileHelper.SetUInt(uint.Parse(nodes[idx].Attributes["TextureID"].Value), idx * 12, tileList.Content); string baseTexture = nodes[idx].Attributes["BaseTexture"].Value; baseTexture = baseTexture.Substring(baseTexture.LastIndexOf(Path.DirectorySeparatorChar) + 1); baseTexture = baseTexture.Substring(baseTexture.LastIndexOf('/') + 1); baseTexture = baseTexture.Substring(0, baseTexture.LastIndexOf('.')); string baseTexturePath = Macro.Terrain + baseTexture + ".dds"; if (!IOFile.Exists(baseTexturePath)) { ErrorDescription = string.Format("{0} doesn't exist.", baseTexturePath); return(false); } using (FileStream textureStream = new FileStream(baseTexturePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (BinaryReader textureReader = new BinaryReader(textureStream)) { textureList[idx, 0] = new DDSFile(textureReader.ReadBytes((int)(textureStream.Length))); } } string normalTexture = nodes[idx].Attributes["NormalTexture"].Value; normalTexture = normalTexture.Substring(normalTexture.LastIndexOf(Path.DirectorySeparatorChar) + 1); normalTexture = normalTexture.Substring(normalTexture.LastIndexOf('/') + 1); normalTexture = normalTexture.Substring(0, normalTexture.LastIndexOf('.')); string normalTexturePath = Macro.Terrain + normalTexture + ".dds"; if (!IOFile.Exists(normalTexturePath)) { ErrorDescription = string.Format("{0} doesn't exist.", normalTexturePath); return(false); } using (FileStream textureStream = new FileStream(normalTexturePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (BinaryReader textureReader = new BinaryReader(textureStream)) { textureList[idx, 1] = new DDSFile(textureReader.ReadBytes((int)(textureStream.Length))); } } } // fixed height, automatically calculated width ushort atlasWidth = 0; ushort atlasHeight = 1152; /* * foreach (XmlAttribute attribute in node.Attributes) * { * switch (attribute.Name) * { * case "AtlasSize": * atlasSize = ushort.Parse(attribute.Value); * break; * } * } */ byte[,,] baseContent = new byte[0, atlasHeight, 4]; byte[,,] normalContent = new byte[0, atlasHeight, 4]; uint colWidth = 0; for (int tileIdx = 0; tileIdx < textureList.Length >> 1; ++tileIdx) { uint size = textureList[tileIdx, 0].Header.Height; colWidth = Math.Max(size + 32, colWidth); if (positionY + size + 16 > atlasHeight) { positionY = 16; positionX += nextX; colWidth = size + 32; } atlasWidth = (ushort)(positionX + colWidth - 16); baseContent = ResizeArray <byte>(baseContent, atlasWidth, atlasHeight, 4); normalContent = ResizeArray <byte>(normalContent, atlasWidth, atlasHeight, 4); byte[] color = textureList[tileIdx, 0].Content.GetColor(size, size); byte[] normal = textureList[tileIdx, 1].Content.GetColor(size, size); for (int idy = -16; idy < size + 16; ++idy) { for (int idx = -16; idx < size + 16; ++idx) { int tileY = idy; if (tileY < 0) { tileY = (int)(size + tileY); } else if (tileY >= size) { tileY = (int)(tileY - size); } int tileX = idx; if (tileX < 0) { tileX = (int)(size + tileX); } else if (tileX >= size) { tileX = (int)(tileX - size); } baseContent[(positionX + idx), (positionY + idy), 0] = color[tileY * size * 4 + tileX * 4]; baseContent[(positionX + idx), (positionY + idy), 1] = color[tileY * size * 4 + tileX * 4 + 1]; baseContent[(positionX + idx), (positionY + idy), 2] = color[tileY * size * 4 + tileX * 4 + 2]; baseContent[(positionX + idx), (positionY + idy), 3] = color[tileY * size * 4 + tileX * 4 + 3]; normalContent[(positionX + idx), (positionY + idy), 0] = normal[tileY * size * 4 + tileX * 4]; normalContent[(positionX + idx), (positionY + idy), 1] = normal[tileY * size * 4 + tileX * 4 + 1]; normalContent[(positionX + idx), (positionY + idy), 2] = normal[tileY * size * 4 + tileX * 4 + 2]; normalContent[(positionX + idx), (positionY + idy), 3] = normal[tileY * size * 4 + tileX * 4 + 3]; } } FileHelper.SetUShort((ushort)positionX, 12 * tileIdx + 4, tileList.Content); FileHelper.SetUShort((ushort)positionY, 12 * tileIdx + 6, tileList.Content); FileHelper.SetUShort((ushort)(positionX + size), 12 * tileIdx + 8, tileList.Content); FileHelper.SetUShort((ushort)(positionY + size), 12 * tileIdx + 10, tileList.Content); positionY += size + 32; nextX = Math.Max(size + 32, nextX); } byte[] baseContentArray = new byte[atlasWidth * atlasHeight * 4]; byte[] normalContentArray = new byte[atlasWidth * atlasHeight * 4]; for (int h = 0; h < atlasHeight; ++h) { for (int w = 0; w < atlasWidth; ++w) { for (int c = 0; c < 4; ++c) { baseContentArray[(h * atlasWidth * 4) + (w * 4) + c] = baseContent[w, h, c]; normalContentArray[(h * atlasWidth * 4) + (w * 4) + c] = normalContent[w, h, c]; } } } bool hasAlpha = false; for (int idx = 0; idx < nodes.Count; ++idx) { if (textureList[idx, 0].HasAlpha()) { hasAlpha = true; break; } } DDSFile baseAtlas = null; if (hasAlpha) { baseAtlas = new DDSFile(atlasWidth, atlasHeight, 5, DDSType.DXT5, baseContentArray); } else { baseAtlas = new DDSFile(atlasWidth, atlasHeight, 5, DDSType.DXT1, baseContentArray); } hasAlpha = false; for (int idx = 0; idx < nodes.Count; ++idx) { if (textureList[idx, 1].HasAlpha()) { hasAlpha = true; break; } } DDSFile normalAtlas = null; if (hasAlpha) { normalAtlas = new DDSFile(atlasWidth, atlasHeight, 5, DDSType.A1R5G5B5, normalContentArray); } else { normalAtlas = new DDSFile(atlasWidth, atlasHeight, 5, DDSType.R5G6B5, normalContentArray); } baseAsset.Content = baseAtlas.Binary; asset.SubAssets.Add(0x0C, baseAsset); FileHelper.SetInt(baseAsset.Content.Length, 0x10, asset.Content); normalAsset.Content = normalAtlas.Binary; asset.SubAssets.Add(0x14, normalAsset); FileHelper.SetInt(normalAsset.Content.Length, 0x18, asset.Content); ErrorDescription = string.Empty; return(true); }