public void Parse(Stream s) { if (s == null) { return; } BinaryReader r = new BinaryReader(s); info = new RLEInfo(s); this.MipHeaders = new MipHeader[this.info.mipCount + 1]; for (int i = 0; i < this.info.mipCount; i++) { MipHeaders[i] = new MipHeader { CommandOffset = r.ReadInt32(), Offset2 = r.ReadInt32(), Offset3 = r.ReadInt32(), Offset0 = r.ReadInt32(), Offset1 = r.ReadInt32(), }; } this.MipHeaders[this.info.mipCount] = new MipHeader { CommandOffset = MipHeaders[0].Offset2, Offset2 = MipHeaders[0].Offset3, Offset3 = MipHeaders[0].Offset0, Offset0 = MipHeaders[0].Offset1, Offset1 = (int)s.Length, }; s.Position = 0; this.data = r.ReadBytes((int)s.Length); }
public void Parse(Stream s) { if (s == null || s.Length == 0) { this.data = new byte[0]; return; } BinaryReader r = new BinaryReader(s); info = new RLEInfo(s); this.MipHeaders = new MipHeader[this.info.mipCount + 1]; for (int i = 0; i < this.info.mipCount; i++) { var header = new MipHeader { CommandOffset = r.ReadInt32(), Offset2 = r.ReadInt32(), Offset3 = r.ReadInt32(), Offset0 = r.ReadInt32(), Offset1 = r.ReadInt32(), }; if (this.info.Version == RLEVersion.RLES) { header.Offset4 = r.ReadInt32(); } MipHeaders[i] = header; } this.MipHeaders[this.info.mipCount] = new MipHeader { CommandOffset = MipHeaders[0].Offset2, Offset2 = MipHeaders[0].Offset3, Offset3 = MipHeaders[0].Offset0, Offset0 = MipHeaders[0].Offset1, }; if (this.info.Version == RLEVersion.RLES) { this.MipHeaders[this.info.mipCount].Offset1 = this.MipHeaders[0].Offset4; this.MipHeaders[this.info.mipCount].Offset4 = (int)s.Length; } else { this.MipHeaders[this.info.mipCount].Offset1 = (int)s.Length; } s.Position = 0; this.data = r.ReadBytes((int)s.Length); }
public void ImportToRLE(Stream input, RLEVersion rleVersion = RLEVersion.RLE2) { var fullOpaqueAlpha = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; MemoryStream output = new MemoryStream(); BinaryReader r = new BinaryReader(input); BinaryWriter w = new BinaryWriter(output); this.info = new RLEInfo(); this.info.Parse(input); if (this.info.pixelFormat.Fourcc != FourCC.DXT5) { throw new InvalidDataException(string.Format("Not a DXT5 format DDS, read {0}", this.info.pixelFormat.Fourcc)); } if (this.info.Depth == 0) { this.info.Depth = 1; } w.Write((uint)FourCC.DXT5); if (rleVersion == RLEVersion.RLE2) { w.Write((uint)0x32454C52); } else { w.Write((uint)0x53454C52); } w.Write((ushort)this.info.Width); w.Write((ushort)this.info.Height); w.Write((ushort)this.info.mipCount); w.Write((ushort)0); if (rleVersion == RLEVersion.RLE2) { var headerOffset = 16; var dataOffset = 16 + (20 * this.info.mipCount); this.MipHeaders = new MipHeader[this.info.mipCount]; using (var commandData = new MemoryStream()) using (var block2Data = new MemoryStream()) using (var block3Data = new MemoryStream()) using (var block0Data = new MemoryStream()) using (var block1Data = new MemoryStream()) { BinaryWriter commonDataWriter = new BinaryWriter(commandData); for (int mipIndex = 0; mipIndex < this.info.mipCount; mipIndex++) { this.MipHeaders[mipIndex] = new MipHeader() { CommandOffset = (int)commandData.Length, Offset2 = (int)block2Data.Length, Offset3 = (int)block3Data.Length, Offset0 = (int)block0Data.Length, Offset1 = (int)block1Data.Length, }; var mipWidth = Math.Max(4, this.info.Width >> mipIndex); var mipHeight = Math.Max(4, this.info.Height >> mipIndex); var mipDepth = Math.Max(1, this.info.Depth >> mipIndex); var mipSize = Math.Max(1, (mipWidth + 3) / 4) * Math.Max(1, (mipHeight + 3) / 4) * 16; var mipData = r.ReadBytes(mipSize); for (int offset = 0; offset < mipSize;) { ushort transparentCount = 0; while (transparentCount < 0x3FFF && offset < mipSize && TestAlphaAny(mipData, offset, a => a != 0) == false) { transparentCount++; offset += 16; } if (transparentCount > 0) { transparentCount <<= 2; transparentCount |= 0; commonDataWriter.Write(transparentCount); continue; } var opaqueOffset = offset; ushort opaqueCount = 0; while (opaqueCount < 0x3FFF && offset < mipSize && TestAlphaAll(mipData, offset, a => a == 0xFF) == true) { opaqueCount++; offset += 16; } if (opaqueCount > 0) { for (int i = 0; i < opaqueCount; i++, opaqueOffset += 16) { block2Data.Write(mipData, opaqueOffset + 8, 4); block3Data.Write(mipData, opaqueOffset + 12, 4); } opaqueCount <<= 2; opaqueCount |= 2; commonDataWriter.Write(opaqueCount); continue; } var translucentOffset = offset; ushort translucentCount = 0; while (translucentCount < 0x3FFF && offset < mipSize && TestAlphaAny(mipData, offset, a => a != 0) == true && TestAlphaAll(mipData, offset, a => a == 0xFF) == false) { translucentCount++; offset += 16; } if (translucentCount > 0) { for (int i = 0; i < translucentCount; i++, translucentOffset += 16) { block0Data.Write(mipData, translucentOffset + 0, 2); block1Data.Write(mipData, translucentOffset + 2, 6); block2Data.Write(mipData, translucentOffset + 8, 4); block3Data.Write(mipData, translucentOffset + 12, 4); } translucentCount <<= 2; translucentCount |= 1; commonDataWriter.Write(translucentCount); continue; } throw new NotImplementedException(); } } output.Position = dataOffset; commandData.Position = 0; var commandOffset = (int)output.Position; output.Write(commandData.ToArray(), 0, (int)commandData.Length); block2Data.Position = 0; var block2Offset = (int)output.Position; output.Write(block2Data.ToArray(), 0, (int)block2Data.Length); block3Data.Position = 0; var block3Offset = (int)output.Position; output.Write(block3Data.ToArray(), 0, (int)block3Data.Length); block0Data.Position = 0; var block0Offset = (int)output.Position; output.Write(block0Data.ToArray(), 0, (int)block0Data.Length); block1Data.Position = 0; var block1Offset = (int)output.Position; output.Write(block1Data.ToArray(), 0, (int)block1Data.Length); output.Position = headerOffset; for (int i = 0; i < this.info.mipCount; i++) { var mipHeader = this.MipHeaders[i]; w.Write(mipHeader.CommandOffset + commandOffset); w.Write(mipHeader.Offset2 + block2Offset); w.Write(mipHeader.Offset3 + block3Offset); w.Write(mipHeader.Offset0 + block0Offset); w.Write(mipHeader.Offset1 + block1Offset); } this.data = output.ToArray(); } } else { var headerOffset = 16; var dataOffset = 16 + (24 * this.info.mipCount); this.MipHeaders = new MipHeader[this.info.mipCount]; using (var commandData = new MemoryStream()) using (var block2Data = new MemoryStream()) using (var block3Data = new MemoryStream()) using (var block0Data = new MemoryStream()) using (var block1Data = new MemoryStream()) using (var block4Data = new MemoryStream()) { BinaryWriter commonDataWriter = new BinaryWriter(commandData); for (int mipIndex = 0; mipIndex < this.info.mipCount; mipIndex++) { this.MipHeaders[mipIndex] = new MipHeader() { CommandOffset = (int)commandData.Length, Offset2 = (int)block2Data.Length, Offset3 = (int)block3Data.Length, Offset0 = (int)block0Data.Length, Offset1 = (int)block1Data.Length, Offset4 = (int)block4Data.Length }; var mipWidth = Math.Max(4, this.info.Width >> mipIndex); var mipHeight = Math.Max(4, this.info.Height >> mipIndex); var mipDepth = Math.Max(1, this.info.Depth >> mipIndex); var mipSize = Math.Max(1, (mipWidth + 3) / 4) * Math.Max(1, (mipHeight + 3) / 4) * 16; var mipData = r.ReadBytes(mipSize); for (int offset = 0; offset < mipSize;) { ushort transparentCount = 0; while (transparentCount < 0x3FFF && offset < mipSize && TestAlphaAny(mipData, offset, a => a != 0) == false) { transparentCount++; offset += 16; } if (transparentCount > 0) { transparentCount <<= 2; transparentCount |= 0; commonDataWriter.Write(transparentCount); continue; } var opaqueOffset = offset; ushort opaqueCount = 0; while (opaqueCount < 0x3FFF && offset < mipSize && TestAlphaAll(mipData, offset, a => a == 0xFF) == true) { opaqueCount++; offset += 16; } if (opaqueCount > 0) { for (int i = 0; i < opaqueCount; i++, opaqueOffset += 16) { block0Data.Write(mipData, opaqueOffset + 0, 2); block1Data.Write(mipData, opaqueOffset + 2, 6); block2Data.Write(mipData, opaqueOffset + 8, 4); block3Data.Write(mipData, opaqueOffset + 12, 4); // block4Data.Write(fullOpaqueAlpha, 0, 8); } opaqueCount <<= 2; opaqueCount |= 2; commonDataWriter.Write(opaqueCount); continue; } var translucentOffset = offset; ushort translucentCount = 0; while (translucentCount < 0x3FFF && offset < mipSize && TestAlphaAny(mipData, offset, a => a != 0) == true && TestAlphaAll(mipData, offset, a => a == 0xFF) == false) { translucentCount++; offset += 16; } if (translucentCount > 0) { for (int i = 0; i < translucentCount; i++, translucentOffset += 16) { block0Data.Write(mipData, translucentOffset + 0, 2); block1Data.Write(mipData, translucentOffset + 2, 6); block2Data.Write(mipData, translucentOffset + 8, 4); block3Data.Write(mipData, translucentOffset + 12, 4); block4Data.Write(fullOpaqueAlpha, 0, 8); block4Data.Write(fullOpaqueAlpha, 0, 8); } translucentCount <<= 2; translucentCount |= 1; commonDataWriter.Write(translucentCount); continue; } throw new NotImplementedException(); } } output.Position = dataOffset; commandData.Position = 0; var commandOffset = (int)output.Position; output.Write(commandData.ToArray(), 0, (int)commandData.Length); block2Data.Position = 0; var block2Offset = (int)output.Position; output.Write(block2Data.ToArray(), 0, (int)block2Data.Length); block3Data.Position = 0; var block3Offset = (int)output.Position; output.Write(block3Data.ToArray(), 0, (int)block3Data.Length); block0Data.Position = 0; var block0Offset = (int)output.Position; output.Write(block0Data.ToArray(), 0, (int)block0Data.Length); block1Data.Position = 0; var block1Offset = (int)output.Position; output.Write(block1Data.ToArray(), 0, (int)block1Data.Length); block4Data.Position = 0; var block4Offset = (int)output.Position; output.Write(block4Data.ToArray(), 0, (int)block4Data.Length); output.Position = headerOffset; for (int i = 0; i < this.info.mipCount; i++) { var mipHeader = this.MipHeaders[i]; w.Write(mipHeader.CommandOffset + commandOffset); w.Write(mipHeader.Offset2 + block2Offset); w.Write(mipHeader.Offset3 + block3Offset); w.Write(mipHeader.Offset0 + block0Offset); w.Write(mipHeader.Offset1 + block1Offset); w.Write(mipHeader.Offset4 + block4Offset); } this.data = output.ToArray(); } } }