예제 #1
0
        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);
        }
예제 #2
0
        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;
        }
예제 #3
0
        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;
        }
예제 #4
0
        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();
            }
        }
예제 #5
0
        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);
            }
        }
예제 #6
0
        /// <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;
        }
예제 #7
0
        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;
        }