示例#1
0
        private ushort getNTP3CompressionType(DDSFileInfo DDSFileList, NTP3FileInfo NTP3FileInfo)
        {
            string compressionType = DDSFileList.CompressionType;

            if (compressionType == "No Compression")
            {
                if (Enum.TryParse(NTP3FileInfo.pixelFormat, out PixelFormat pixelFormat))
                {
                    switch (pixelFormat)
                    {
                    case PixelFormat.AbgrExt:
                        return(14);

                    case PixelFormat.R5G6B5IccSgix:
                    default:
                        return(7);
                    }
                }
                else
                {
                    throw new Exception("Cannot parse pixelFormat!");
                }
            }
            else
            {
                return(NTP3CompressedTypes[compressionType]);
            }
        }
示例#2
0
        private List <uint> calculateMipmapsSize(DDSFileInfo DDSFile)
        {
            List <uint> mipmapsSizeList  = new List <uint>();
            int         numberofMipmaps  = DDSFile.numberofMipmaps;
            int         widthResolution  = DDSFile.widthReso;
            int         heightResolution = DDSFile.heightReso;

            for (int i = 0; i < numberofMipmaps; i++)
            {
                uint mipmapSize = 0;
                if (DDSFile.CompressionType == "No Compression")
                {
                    mipmapSize = (uint)(widthResolution * heightResolution * DDSFile.pixelFormatRGBAByteSize);
                    Math.Max(1, Math.Truncate((decimal)(widthResolution /= 2)));
                    Math.Max(1, Math.Truncate((decimal)(heightResolution /= 2)));
                    mipmapsSizeList.Add(mipmapSize);
                }
                else
                {
                    int blockSize;
                    switch (DDSFile.CompressionType)
                    {
                    case "DXT1":
                        blockSize = 8;
                        break;

                    case "DXT2":
                    case "DXT3":
                    case "DXT5":
                        blockSize = 16;
                        break;

                    default:
                        throw new Exception("DDS Compression type not supported!");
                    }
                    // should I add a check on min size?
                    mipmapSize = (uint)(Math.Max(1, Math.Truncate((decimal)((widthResolution + 3) / 4))) * Math.Max(1, Math.Truncate((decimal)((heightResolution + 3) / 4))) * blockSize);
                    Math.Max(1, Math.Truncate((decimal)(widthResolution /= 2)));
                    Math.Max(1, Math.Truncate((decimal)(heightResolution /= 2)));
                    mipmapsSizeList.Add(mipmapSize);
                }
            }
            return(mipmapsSizeList);
        }
示例#3
0
        private void repackNTP3(List <NTP3FileInfo> NTP3FileInfoList, List <DDSFileInfo> DDSFileList, MemoryStream NTP3Stream)
        {
            for (int fileNo = 0; fileNo < DDSFileList.Count; fileNo++)
            {
                NTP3FileInfo NTP3Info = NTP3FileInfoList[fileNo];
                DDSFileInfo  DDSFile  = DDSFileList[fileNo];

                // We try to follow the compressionType

                bool writeWithNTP3Header = fileNo == 0 ? true : false;
                writeNTP3Header(writeWithNTP3Header, NTP3Info, DDSFileList, fileNo, NTP3Stream);

                // byteReverse?
                byte[] DDSDataChunkBuffer = addPaddingArrayBuffer(DDSFile.DDSByteStream.ToArray());
                NTP3Stream.Write(DDSDataChunkBuffer, 0, DDSDataChunkBuffer.Length);

                FileStream fileStream = File.Create(Directory.GetCurrentDirectory() + (@"\temp\NTP3-" + fileNumber.ToString()));
                fileStream.Write(DDSDataChunkBuffer, 0, DDSDataChunkBuffer.Length);

                fileStream.Close();
            }
        }
示例#4
0
        private void writeNTP3Header(bool withHeader, NTP3FileInfo NTP3FileInfo, List <DDSFileInfo> DDSFileList, int fileNo, MemoryStream NTP3Stream)
        {
            DDSFileInfo DDSFile = DDSFileList[fileNo];

            int DDSDataChunkSize = DDSFile.DDSFileChunkSize;

            byte[] NTP3Header   = new byte[0];
            byte[] NTP3Metadata = new byte[0];
            if (withHeader)
            {
                NTP3Header = appendUIntArrayBuffer(NTP3Header, 0x4E545033, true);
                NTP3Header = appendShortArrayBuffer(NTP3Header, 0x0001, false); // Version 1
                NTP3Header = appendShortArrayBuffer(NTP3Header, (ushort)DDSFileList.Count, true);
                NTP3Header = appendZeroArrayBuffer(NTP3Header, 0x08);
            }

            int combinedSizeOffset = NTP3Metadata.Length;

            NTP3Metadata = appendUIntArrayBuffer(NTP3Metadata, 0, true); // Placeholder, will be written once the header part is all done.
            NTP3Metadata = appendZeroArrayBuffer(NTP3Metadata, 0x04);
            NTP3Metadata = appendUIntArrayBuffer(NTP3Metadata, (uint)DDSDataChunkSize, true);
            int NTP3HeaderChunkSizeOffset = NTP3Metadata.Length;

            NTP3Metadata = appendShortArrayBuffer(NTP3Metadata, 0, true); // Placeholder, will be written once the header part is all done.
            NTP3Metadata = appendZeroArrayBuffer(NTP3Metadata, 0x02);

            NTP3Metadata = appendShortArrayBuffer(NTP3Metadata, (ushort)DDSFile.numberofMipmaps, true);

            ushort NTP3compresionType = getNTP3CompressionType(DDSFile, NTP3FileInfo);

            NTP3Metadata = appendShortArrayBuffer(NTP3Metadata, NTP3compresionType, true);
            NTP3Metadata = appendShortArrayBuffer(NTP3Metadata, (ushort)DDSFile.widthReso, true);
            NTP3Metadata = appendShortArrayBuffer(NTP3Metadata, (ushort)DDSFile.heightReso, true);

            // TODO: cube maps
            NTP3Metadata = appendZeroArrayBuffer(NTP3Metadata, 0x18);

            // Manually calculate mipmapsSize, not trusting Info file's.
            List <uint> mipmapsSizeList = calculateMipmapsSize(DDSFile);

            if (mipmapsSizeList.Count > 1)
            {
                // Only write the offsets if there are more than 1 mipmaps. (1 is the original)
                for (int i = 0; i < mipmapsSizeList.Count; i++)
                {
                    NTP3Metadata = appendUIntArrayBuffer(NTP3Metadata, mipmapsSizeList[i], true);
                }
            }


            NTP3Metadata = addPaddingArrayBuffer(NTP3Metadata);

            byte[] eXtChunkBuffer  = NTP3FileInfo.eXtChunk;
            byte[] GIDXChunkBuffer = NTP3FileInfo.GIDXChunk; // TODO: write hash seperately.

            byte[] hexName = NTP3FileInfo.hexName;
            int    a       = 0x8;

            foreach (var name in hexName)
            {
                GIDXChunkBuffer[a] = name;
                a++;
            }

            byte[] NTP3MetadataBuffer = NTP3Metadata.Concat(eXtChunkBuffer).Concat(GIDXChunkBuffer).ToArray();

            // I don't like this implementation, for changing size when everything is written.
            ushort NTP3HeaderChunkSize = (ushort)NTP3MetadataBuffer.Length;
            uint   combinedSize        = (uint)(NTP3HeaderChunkSize + DDSDataChunkSize);

            byte[] NTP3HeaderChunkSizeBuffer = BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(NTP3HeaderChunkSize));
            byte[] combinedSizeBuffer        = BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(combinedSize));

            for (int i = 0; i < NTP3HeaderChunkSizeBuffer.Length; i++)
            {
                NTP3MetadataBuffer[NTP3HeaderChunkSizeOffset + i] = NTP3HeaderChunkSizeBuffer[i];
            }

            for (int i = 0; i < combinedSizeBuffer.Length; i++)
            {
                NTP3MetadataBuffer[combinedSizeOffset + i] = combinedSizeBuffer[i];
            }

            byte[] NTP3HeaderBuffer = NTP3Header.Concat(NTP3MetadataBuffer).ToArray();

            NTP3Stream.Write(NTP3HeaderBuffer, 0, NTP3HeaderBuffer.Length);
        }
示例#5
0
        private List <DDSFileInfo> parseDDS(List <NTP3FileInfo> NTP3FileInfoList, List <FileInfo> allDDSFiles)
        {
            List <DDSFileInfo> realNTP3FileList = new List <DDSFileInfo>();
            int numberofDDS = allDDSFiles.Count;

            for (int fileNo = 0; fileNo < numberofDDS; fileNo++)
            {
                // https://docs.microsoft.com/en-us/windows/win32/direct3ddds/dds-header
                FileStream   DDSStream    = File.OpenRead(allDDSFiles[fileNo].FullName);
                NTP3FileInfo NTP3FileInfo = NTP3FileInfoList[fileNo];
                changeStreamFile(DDSStream);

                if (readIntBigEndian(DDSStream.Position) != 0x44445320)
                {
                    throw new Exception("DDS header not found!");
                }

                // 7C byte
                DDSStream.Seek(0x04, SeekOrigin.Current);

                // DDSFlags
                dwDDSFlags ddsFlags         = (dwDDSFlags)readIntSmallEndian(DDSStream.Position);
                dwDDSFlags requiredDDSFlags = dwDDSFlags.DDSD_CAPS | dwDDSFlags.DDSD_HEIGHT | dwDDSFlags.DDSD_WIDTH | dwDDSFlags.DDSD_PIXELFORMAT;

                if (!ddsFlags.HasFlag(requiredDDSFlags))
                {
                    throw new Exception("DDS Flags error!");
                }

                // Resolutions
                int heightReso = readIntSmallEndian(DDSStream.Position);
                int widthReso  = readIntSmallEndian(DDSStream.Position);

                if (widthReso != NTP3FileInfo.widthReso || heightReso != NTP3FileInfo.heightReso)
                {
                    throw new Exception("Image resolution mismatch between DDS file and NTP3FileInfo!" + Environment.NewLine + "DDS File: " + allDDSFiles[fileNo].FullName);
                }

                // pitchorLinearSize
                int pitchorLinearSize = readIntSmallEndian(DDSStream.Position); // Not used as per Microsoft's Guideline.

                // depth, skipped.
                DDSStream.Seek(0x04, SeekOrigin.Current);

                // Mipmaps
                int numberofMipmaps = readIntSmallEndian(DDSStream.Position);

                // Reserved 11*4 byte + 4 byte dwSizeforPixelFormat.
                DDSStream.Seek(0x30, SeekOrigin.Current);

                // Pixel Formats.
                dwPixelFormatFlags pixelFlags = (dwPixelFormatFlags)readIntSmallEndian(DDSStream.Position);
                string             compressionType = null;
                uint dwRGBBitCount = 0, dwRBitMask = 0, dwGBitMask = 0, dwBBitMask = 0, dwABitMask = 0, dwCaps = 0, dwCaps2 = 0, dwCaps3 = 0, dwCaps4 = 0;

                DDSFileInfo newFileInfo      = new DDSFileInfo();
                int         DDSFileChunkSize = addPaddingSizeCalculation((int)DDSStream.Length) - 0x80;

                if (pixelFlags.HasFlag(dwPixelFormatFlags.DDPF_FOURCC))
                {
                    // Compressed.
                    compressionType = identifyCompressionType(readIntBigEndian(DDSStream.Position));
                    DDSStream.Seek(0x80, SeekOrigin.Begin);
                    DDSStream.CopyTo(newFileInfo.DDSByteStream); // If not compressed, directly copy the RGBA values.
                }
                else
                {
                    DDSStream.Seek(0x04, SeekOrigin.Current);
                    compressionType = "No Compression";

                    dwRGBBitCount = readUIntSmallEndian(DDSStream.Position);
                    dwRBitMask    = readUIntSmallEndian(DDSStream.Position);
                    dwGBitMask    = readUIntSmallEndian(DDSStream.Position);
                    dwBBitMask    = readUIntSmallEndian(DDSStream.Position);
                    dwABitMask    = readUIntSmallEndian(DDSStream.Position);
                    dwCaps        = readUIntSmallEndian(DDSStream.Position); // Caps are not used to determine stuff although we set them.
                    dwCaps2       = readUIntSmallEndian(DDSStream.Position); // TODO: caps 2 stores cubemap infos.
                    dwCaps3       = readUIntSmallEndian(DDSStream.Position);
                    dwCaps4       = readUIntSmallEndian(DDSStream.Position);

                    DDSStream.Seek(0x04, SeekOrigin.Current); // Reserved 1*4 bytes.

                    bool isAlpha = pixelFlags.HasFlag(dwPixelFormatFlags.DDPF_ALPHAPIXELS);

                    if (dwRGBBitCount % 8 != 0)
                    {
                        throw new Exception("dwRGBitCount not a multiple of 4!");
                    }

                    int           RGBAByteCount = (int)(dwRGBBitCount / 8);
                    byte[]        RGBAChunk     = extractChunk(0x80, DDSFileChunkSize);
                    List <byte[]> RGBA          = parseMaskedRGBA(isAlpha, RGBAChunk, RGBAByteCount, dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask);

                    newFileInfo.pixelFormatRGBAByteSize = RGBAByteCount;

                    // We try to convert based on the pixelFormat in info file, else we use the default of Abgr.
                    byte[] maskedRGBA;
                    if (Enum.TryParse(NTP3FileInfo.pixelFormat, out PixelFormat pixelFormat))
                    {
                        maskedRGBA = writeMaskedRGBA(pixelFormat, RGBA);
                    }
                    else
                    {
                        maskedRGBA = writeMaskedRGBA(PixelFormat.AbgrExt, RGBA);
                    }

                    newFileInfo.DDSByteStream.Write(maskedRGBA, 0, maskedRGBA.Length);
                }

                if (compressionType != NTP3FileInfo.CompressionType)
                {
                    throw new Exception("Compression Type mismatch between DDS file and NTP3FileInfo!" + Environment.NewLine + "DDS File: " + allDDSFiles[fileNo].FullName);
                }

                newFileInfo.fileNo           = fileNo + 1;
                newFileInfo.DDSFileChunkSize = DDSFileChunkSize;
                newFileInfo.widthReso        = widthReso;
                newFileInfo.heightReso       = heightReso;
                newFileInfo.CompressionType  = compressionType;
                newFileInfo.hexName          = convertInt32toByteArray(getDDSFileName(DDSStream.Name), true);
                newFileInfo.numberofMipmaps  = numberofMipmaps;

                realNTP3FileList.Add(newFileInfo);
                DDSStream.Close();
            }

            return(realNTP3FileList);
        }