protected byte[] CreateDDSHeader(TgvFile file) { var hd = new DDS.DDS.Header { Size = 124, Flags = DDS.DDS.HeaderFlags.Texture, SurfaceFlags = DDS.DDS.SurfaceFlags.Texture, Width = file.ImageWidth, Height = file.ImageHeight, Depth = 0, MipMapCount = 1 }; DDS.DDS.PixelFormat ddpf = DDS.DDS.PixelFormatFromDXGIFormat(file.Format); int rowPitch, slicePitch; int widthCount, heightCount; DDS.DDS.ComputePitch(file.Format, (int)file.ImageWidth, (int)file.ImageHeight, out rowPitch, out slicePitch, out widthCount, out heightCount); if (DDS.DDS.IsCompressedFormat(file.Format)) { hd.Flags |= DDS.DDS.HeaderFlags.LinearSize; hd.PitchOrLinearSize = slicePitch; } else { hd.Flags |= DDS.DDS.HeaderFlags.Pitch; hd.PitchOrLinearSize = rowPitch; } hd.PixelFormat = ddpf; return Utils.StructToBytes(hd); }
public RawImage GetMip(TgvFile file, uint mip) { RawImage ret; uint width = file.ImageWidth; uint height = file.ImageHeight; // Compute width and height. for (uint m = 0; m < mip; m++) { width = Math.Max(1, width / 2); height = Math.Max(1, height / 2); } ret = new RawImage(width, height); using (var ms = new MemoryStream(file.MipMaps[(int)mip].Content)) { if (DDS.DDS.IsCompressedFormat(file.Format)) { ReadBlockFormat(ret, ms); } } return ret; }
public TgvFile ReadDDS(byte[] input) { int contentSize = input.Length - Marshal.SizeOf(typeof(DDS.DDS.Header)) - Marshal.SizeOf((typeof(uint))); var file = new TgvFile(); using (var ms = new MemoryStream(input)) { var buffer = new byte[4]; ms.Read(buffer, 0, buffer.Length); if (BitConverter.ToUInt32(buffer, 0) != DDS.DDS.MagicHeader) throw new ArgumentException("Wrong DDS magic"); buffer = new byte[Marshal.SizeOf(typeof(DDS.DDS.Header))]; ms.Read(buffer, 0, buffer.Length); var header = Utils.ByteArrayToStructure<DDS.DDS.Header>(buffer); int mipSize = contentSize; if (header.MipMapCount == 0) header.MipMapCount = 1; else mipSize -= contentSize / header.MipMapCount; for (ushort i = 0; i < header.MipMapCount; i++) { buffer = new byte[mipSize]; ms.Read(buffer, 0, buffer.Length); var mip = new TgvMipMap { Content = buffer }; file.MipMaps.Add(mip); mipSize /= 4; } file.Height = header.Height; file.ImageHeight = header.Height; file.Width = header.Width; file.ImageWidth = header.Width; file.MipMapCount = (ushort)header.MipMapCount; DDSHelper.ConversionFlags conversionFlags; file.Format = DDSHelper.GetDXGIFormat(ref header.PixelFormat, out conversionFlags); } return file; }
public byte[] CreateDDSFile(TgvFile file) { using (var ms = new MemoryStream()) { byte[] buffer = BitConverter.GetBytes(DDS.DDS.MagicHeader); ms.Write(buffer, 0, buffer.Length); buffer = CreateDDSHeader(file); ms.Write(buffer, 0, buffer.Length); buffer = file.MipMaps.OrderByDescending(x => x.MipWidth).First().Content; ms.Write(buffer, 0, buffer.Length); return ms.ToArray(); } }
public void Write(Stream destStream, TgvFile sourceFile, byte[] sourceChecksum, bool compress = true) { if (sourceChecksum.Length > 16) throw new ArgumentException("sourceChecksum"); sourceFile.PixelFormatStr = TranslatePixelFormatBack(sourceFile.Format); var zipoMagic = Encoding.ASCII.GetBytes("ZIPO"); var buffer = BitConverter.GetBytes(Version); destStream.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(compress ? 1 : 0); destStream.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(sourceFile.Width); destStream.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(sourceFile.Height); destStream.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(sourceFile.Width); destStream.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(sourceFile.Height); destStream.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes((short)sourceFile.MipMapCount); destStream.Write(buffer, 0, buffer.Length); var fmtLen = (short)sourceFile.PixelFormatStr.Length; buffer = BitConverter.GetBytes(fmtLen); destStream.Write(buffer, 0, buffer.Length); buffer = Encoding.ASCII.GetBytes(sourceFile.PixelFormatStr); destStream.Write(buffer, 0, buffer.Length); destStream.Seek(Utils.RoundToNextDivBy4(fmtLen) - fmtLen, SeekOrigin.Current); destStream.Write(sourceChecksum, 0, sourceChecksum.Length); var mipdefOffset = (destStream.Position); var mipImgsizes = new List<int>(); var tileSize = sourceFile.Width - sourceFile.Width / sourceFile.MipMapCount; for (int i = 0; i < sourceFile.MipMapCount; i++) { destStream.Seek(8, SeekOrigin.Current); mipImgsizes.Add((int)tileSize); tileSize /= 4; } var sortedMipMaps = sourceFile.MipMaps.OrderBy(x => x.Content.Length).ToList(); //mipImgsizes = mipImgsizes.OrderBy(x => x).ToList(); // Create the content and write all MipMaps, // since we compress on this part its the first part where we know the size of a MipMap foreach (var sortedMipMap in sortedMipMaps) { sortedMipMap.Offset = (uint)destStream.Position; if (compress) { destStream.Write(zipoMagic, 0, zipoMagic.Length); //buffer = BitConverter.GetBytes(mipImgsizes[sortedMipMaps.IndexOf(sortedMipMap)]); buffer = BitConverter.GetBytes((int)Math.Pow(4, sortedMipMaps.IndexOf(sortedMipMap))); destStream.Write(buffer, 0, buffer.Length); buffer = Compressor.Comp(sortedMipMap.Content); destStream.Write(buffer, 0, buffer.Length); sortedMipMap.Size = (uint)buffer.Length; } else { destStream.Write(sortedMipMap.Content, 0, sortedMipMap.Content.Length); sortedMipMap.Size = (uint)sortedMipMap.Content.Length; } } destStream.Seek(mipdefOffset, SeekOrigin.Begin); // Write the offset collection in the header. for (int i = 0; i < sourceFile.MipMapCount; i++) { buffer = BitConverter.GetBytes(sortedMipMaps[i].Offset); destStream.Write(buffer, 0, buffer.Length); } // Write the size collection into the header. for (int i = 0; i < sourceFile.MipMapCount; i++) { buffer = BitConverter.GetBytes(sortedMipMaps[i].Size + 8); destStream.Write(buffer, 0, buffer.Length); } }
/// <summary> /// This method is stream and order dependant, don't use outside. /// </summary> /// <param name="ms"></param> /// <param name="file"></param> /// <param name="id"></param> /// <returns></returns> private TgvMipMap ReadMip(Stream ms, TgvFile file, int id) { if (id > file.MipMapCount) throw new ArgumentException("id"); var zipo = new byte[] { 0x5A, 0x49, 0x50, 0x4F }; var mipMap = new TgvMipMap(file.Offsets[id], file.Sizes[id], 0); byte[] buffer; if (file.IsCompressed) { buffer = new byte[4]; ms.Read(buffer, 0, buffer.Length); if (!Utils.ByteArrayCompare(buffer, zipo)) throw new InvalidDataException("Mipmap has to start with \"ZIPO\"!"); ms.Read(buffer, 0, buffer.Length); mipMap.MipWidth = BitConverter.ToInt32(buffer, 0); buffer = new byte[mipMap.Size - 8]; } else buffer = new byte[mipMap.Size]; ms.Read(buffer, 0, buffer.Length); ms.Seek(Utils.RoundToNextDivBy4((int)mipMap.Size)-mipMap.Size, SeekOrigin.Current); if (file.IsCompressed) buffer = Compressor.Decomp(buffer); mipMap.Content = buffer; return mipMap; }
public TgvFile Read(Stream ms) { var file = new TgvFile(); var buffer = new byte[4]; ms.Read(buffer, 0, buffer.Length); file.Version = BitConverter.ToUInt32(buffer, 0); ms.Read(buffer, 0, buffer.Length); file.IsCompressed = BitConverter.ToInt32(buffer, 0) > 0; ms.Read(buffer, 0, buffer.Length); file.Width = BitConverter.ToUInt32(buffer, 0); ms.Read(buffer, 0, buffer.Length); file.Height = BitConverter.ToUInt32(buffer, 0); ms.Read(buffer, 0, buffer.Length); file.ImageWidth = BitConverter.ToUInt32(buffer, 0); ms.Read(buffer, 0, buffer.Length); file.ImageHeight = BitConverter.ToUInt32(buffer, 0); buffer = new byte[2]; ms.Read(buffer, 0, buffer.Length); file.MipMapCount = BitConverter.ToUInt16(buffer, 0); ms.Read(buffer, 0, buffer.Length); ushort pixelFormatLen = BitConverter.ToUInt16(buffer, 0); buffer = new byte[pixelFormatLen]; ms.Read(buffer, 0, buffer.Length); file.PixelFormatStr = Encoding.ASCII.GetString(buffer); ms.Seek(Utils.RoundToNextDivBy4(pixelFormatLen) - pixelFormatLen, SeekOrigin.Current); buffer = new byte[16]; ms.Read(buffer, 0, buffer.Length); file.SourceChecksum = (byte[])buffer.Clone(); buffer = new byte[4]; for (int i = 0; i < file.MipMapCount; i++) { ms.Read(buffer, 0, buffer.Length); uint offset = BitConverter.ToUInt32(buffer, 0); file.Offsets.Add(offset); } for (int i = 0; i < file.MipMapCount; i++) { ms.Read(buffer, 0, buffer.Length); uint offset = BitConverter.ToUInt32(buffer, 0); file.Sizes.Add(offset); } for (int i = 0; i < file.MipMapCount; i++) file.MipMaps.Add(ReadMip(ms, file, i)); file.Format = TranslatePixelFormat(file.PixelFormatStr); //if (file.Width != file.ImageWidth || file.Height != file.ImageHeight) //{ // throw new InvalidDataException("something interresting happened here"); //} return file; }