Beispiel #1
0
        public static Bitmap toBitmap(byte[] d, int width, int height, DDSFormat format)
        {
            byte[] pixels = new byte[width * height * 4];

            if (format == DDSFormat.DXT1)
            {
                decodeDXT1(pixels, d, width, height);
            }
            if (format == DDSFormat.DXT5)
            {
                decodeDXT5(pixels, d, width, height);
            }

            Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            BitmapData bmpData = bmp.LockBits(
                new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.WriteOnly, bmp.PixelFormat);

            Marshal.Copy(pixels, 0, bmpData.Scan0, pixels.Length);


            bmp.UnlockBits(bmpData);
            return(bmp);
        }
        /// <summary>
        /// Creates a DDS header from a set of information.
        /// </summary>
        /// <param name="Mips">Number of mipmaps.</param>
        /// <param name="Height">Height of top mipmap.</param>
        /// <param name="Width">Width of top mipmap.</param>
        /// <param name="surfaceformat">Format header represents.</param>
        public DDS_Header(int Mips, int Height, int Width, DDSFormat surfaceformat, DXGI_FORMAT dx10Format = DXGI_FORMAT.DXGI_FORMAT_UNKNOWN)
        {
            dwSize        = 124;
            dwFlags       = DDSdwFlags.DDSD_CAPS | DDSdwFlags.DDSD_HEIGHT | DDSdwFlags.DDSD_WIDTH | DDSdwFlags.DDSD_PIXELFORMAT | (Mips != 1 ? DDSdwFlags.DDSD_MIPMAPCOUNT : 0);
            this.Width    = Width;
            this.Height   = Height;
            dwCaps        = DDSdwCaps.DDSCAPS_TEXTURE | (Mips == 1 ? 0 : DDSdwCaps.DDSCAPS_COMPLEX | DDSdwCaps.DDSCAPS_MIPMAP);
            dwMipMapCount = Mips == 1 ? 1 : Mips;
            ddspf         = new DDS_PIXELFORMAT(surfaceformat);

            if (surfaceformat == DDSFormat.DDS_DX10 || surfaceformat == DDSFormat.DDS_ARGB_32F)
            {
                if (surfaceformat == DDSFormat.DDS_ARGB_32F)
                {
                    dx10Format = DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT;
                }

                DX10_DXGI_AdditionalHeader = new DDS_DXGI_DX10_Additional
                {
                    dxgiFormat        = dx10Format,
                    resourceDimension = D3D10_RESOURCE_DIMENSION.DDS_DIMENSION_TEXTURE2D,
                    miscFlag          = DDS_DXGI_DX10_Additional.D3D10_RESOURCE_MISC_FLAGS.D3D10_RESOURCE_MISC_GENERATE_MIPS,
                    miscFlags2        = DXGI_MiscFlags.DDS_ALPHA_MODE_UNKNOWN,
                    arraySize         = 1
                };
            }
        }
Beispiel #3
0
        public void extractTextureToDDS(string outputFile, string packagePath, int exportID)
        {
            Package package = new Package(packagePath);
            Texture texture = new Texture(package, exportID, package.getExportData(exportID));

            while (texture.mipMapsList.Exists(s => s.storageType == Texture.StorageTypes.empty))
            {
                texture.mipMapsList.Remove(texture.mipMapsList.First(s => s.storageType == Texture.StorageTypes.empty));
            }
            List <DDSImage.MipMap> mipmaps = new List <DDSImage.MipMap>();
            DDSFormat format = DDSImage.convertFormat(texture.properties.getProperty("Format").valueName);

            for (int i = 0; i < texture.mipMapsList.Count; i++)
            {
                byte[] data = texture.getMipMapDataByIndex(i);
                if (data == null)
                {
                    MessageBox.Show("Failed to extract to DDS file. Broken game files!");
                    return;
                }
                mipmaps.Add(new DDSImage.MipMap(data, format, texture.mipMapsList[i].width, texture.mipMapsList[i].height));
            }
            DDSImage dds = new DDSImage(mipmaps);

            if (File.Exists(outputFile))
            {
                File.Delete(outputFile);
            }
            using (FileStream fs = new FileStream(outputFile, FileMode.CreateNew, FileAccess.Write))
            {
                dds.SaveDDSImage(fs);
            }
        }
        /// <summary>
        /// Gets maximum number of channels a format can contain.
        /// NOTE: This likely isn't actually the max number. i.e. None exceed four, but some are only one or two channels.
        /// </summary>
        /// <param name="format">Format to channel count.</param>
        /// <returns>Max number of channels supported.</returns>
        static int MaxNumberOfChannels(DDSFormat format)
        {
            int numChannels = 4;

            switch (format)
            {
            case DDSFormat.DDS_A8:
            case DDSFormat.DDS_ATI1:
            case DDSFormat.DDS_G8_L8:
                numChannels = 1;
                break;

            case DDSFormat.DDS_A8L8:
            case DDSFormat.DDS_ATI2_3Dc:
            case DDSFormat.DDS_G16_R16:
            case DDSFormat.DDS_V8U8:
                numChannels = 2;
                break;

            case DDSFormat.DDS_R5G6B5:
            case DDSFormat.DDS_RGB_8:
                numChannels = 3;
                break;
            }

            return(numChannels);
        }
        /// <summary>
        /// Searches for a format within a string. Good for automatic file naming.
        /// </summary>
        /// <param name="stringWithFormatInIt">String containing format somewhere in it.</param>
        /// <returns>Format in string, or UNKNOWN otherwise.</returns>
        public static DDSFormat FindFormatInString(string stringWithFormatInIt)
        {
            DDSFormat detectedFormat = DDSFormat.Unknown;

            foreach (var formatName in Enum.GetNames(typeof(DDSFormat)))
            {
                string actualFormat = formatName.Replace("DDS_", "");
                bool   check        = stringWithFormatInIt.Contains(actualFormat, StringComparison.OrdinalIgnoreCase);

                if (actualFormat.Contains("3Dc"))
                {
                    check = stringWithFormatInIt.Contains("3dc", StringComparison.OrdinalIgnoreCase) || stringWithFormatInIt.Contains("ati2", StringComparison.OrdinalIgnoreCase);
                }
                else if (actualFormat == "A8L8")
                {
                    check = stringWithFormatInIt.Contains("L8", StringComparison.OrdinalIgnoreCase) && !stringWithFormatInIt.Contains("G", StringComparison.OrdinalIgnoreCase);
                }
                else if (actualFormat == "G8_L8")
                {
                    check = !stringWithFormatInIt.Contains("A", StringComparison.OrdinalIgnoreCase) && stringWithFormatInIt.Contains("G8", StringComparison.OrdinalIgnoreCase);
                }
                else if (actualFormat.Contains("ARGB"))
                {
                    check = stringWithFormatInIt.Contains("A8R8G8B8", StringComparison.OrdinalIgnoreCase) || stringWithFormatInIt.Contains("ARGB", StringComparison.OrdinalIgnoreCase);
                }

                if (check)
                {
                    detectedFormat = (DDSFormat)Enum.Parse(typeof(DDSFormat), formatName);
                    break;
                }
            }

            return(detectedFormat);
        }
Beispiel #6
0
        public DDSPreview(byte[] data)
        {
            if (BitConverter.ToUInt32(data, 0) != DDSMagic)
            {
                throw new FormatException("Invalid DDS Magic Number");
            }
            if (BitConverter.ToUInt32(data, 4) != 0x7C)
            {
                throw new FormatException("Invalid header size");
            }
            DDSFlags = BitConverter.ToUInt32(data, 8);
            if ((DDSFlags & 0x1) != 0x1 || (DDSFlags & 0x2) != 0x2 || (DDSFlags & 0x4) != 0x4 || (DDSFlags & 0x1000) != 0x1000)
            {
                throw new FormatException("Invalid DDS Flags");
            }
            mips   = (DDSFlags & 0x20000) == 0x20000;
            Height = BitConverter.ToUInt32(data, 12);
            Width  = BitConverter.ToUInt32(data, 16);
            // Skip pitch and depth, unimportant
            NumMips = BitConverter.ToUInt32(data, 28);
            uint pxformat = BitConverter.ToUInt32(data, 84);

            Format  = GetDDSFormat(pxformat);
            imgData = new byte[data.Length - 0x80];
            Array.Copy(data, 0x80, imgData, 0, imgData.Length);

            pfFlags     = BitConverter.ToUInt32(data, 0x50);
            fourCC      = BitConverter.ToUInt32(data, 0x54);
            rgbBitCount = BitConverter.ToUInt32(data, 0x58);
            rBitMask    = BitConverter.ToUInt32(data, 0x5C);
            gBitMask    = BitConverter.ToUInt32(data, 0x60);
            bBitMask    = BitConverter.ToUInt32(data, 0x64);
            aBitMask    = BitConverter.ToUInt32(data, 0x68);

            FormatString = GetFormat();

            switch (FormatString)
            {
            case "DXT1": BPP = 0.5F; stdDDS = true; compressed = true; break;

            case "DXT5": BPP = 1F; stdDDS = true; compressed = true; break;

            case "V8U8": BPP = 2F; stdDDS = true; compressed = false; break;

            case "ATI2": BPP = 1F; stdDDS = true; compressed = true; break;

            case "A8B8G8R8":
            case "A8R8G8B8": BPP = 4F; stdDDS = false; compressed = false; break;

            case "B8G8R8":
            case "R8G8B8": BPP = 3F; stdDDS = false; compressed = false; break;

            default: BPP = 1; stdDDS = false; compressed = false; break;
            }
        }
        /// <summary>
        /// Gets file extension of supported surface formats.
        /// Doesn't include preceding dot.
        /// </summary>
        /// <param name="format">Format to get file extension for.</param>
        /// <returns>File extension without dot.</returns>
        static string GetExtensionOfFormat(DDSFormat format)
        {
            string formatString = format.ToString().ToLowerInvariant();

            if (formatString.Contains('_'))
            {
                formatString = "dds";
            }

            return(formatString);
        }
 static FourCC ParseFormatToFourCC(DDSFormat format)
 {
     if (Enum.IsDefined(typeof(FourCC), (int)format))
     {
         return((FourCC)format);
     }
     else
     {
         return(FourCC.Unknown);
     }
 }
Beispiel #9
0
        public static double getBytesPerPixel(DDSFormat ddsFormat)
        {
            switch (ddsFormat)
            {
            case DDSFormat.DXT1: return(0.5);

            case DDSFormat.DXT5:
            case DDSFormat.ATI2: return(1);

            case DDSFormat.V8U8: return(2);
            }
            throw new Exception("invalid texture format");
        }
        private void Write_DDS_PIXELFORMAT(DDSFormat p, Stream s)
        {
            DDS_PIXELFORMAT fmt = getDDSPixelFormat(p);

            s.WriteInt32(DDS_PIXELFORMAT_size);
            s.WriteUInt32(fmt.dwFlags);
            s.WriteUInt32(fmt.dwFourCC);
            s.WriteUInt32(fmt.dwRGBBitCount);
            s.WriteUInt32(fmt.dwRBitMask);
            s.WriteUInt32(fmt.dwGBitMask);
            s.WriteUInt32(fmt.dwBBitMask);
            s.WriteUInt32(fmt.dwABitMask);
        }
Beispiel #11
0
            public MipMap(byte[] data, DDSFormat format, int w, int h)
            {
                long requiredSize = (long)(w * h * getBytesPerPixel(format));

                if (data.Length != requiredSize)
                {
                    throw new InvalidDataException("Data size is not valid for selected format.\nActual: " + data.Length + " bytes\nRequired: " + requiredSize + " bytes");
                }

                this.data = data;
                ddsFormat = format;
                width     = w;
                height    = h;
            }
Beispiel #12
0
        public DDSImage(string ddsFileName)
        {
            using (FileStream ddsStream = File.OpenRead(ddsFileName))
            {
                using (BinaryReader r = new BinaryReader(ddsStream))
                {
                    dwMagic = r.ReadInt32();
                    if (dwMagic != 0x20534444)
                    {
                        throw new Exception("This is not a DDS!");
                    }

                    Read_DDS_HEADER(header, r);

                    if (((header.ddspf.dwFlags & DDPF_FOURCC) != 0) && (header.ddspf.dwFourCC == FOURCC_DX10 /*DX10*/))
                    {
                        throw new Exception("DX10 not supported yet!");
                    }

                    int mipMapCount = 1;
                    if ((header.dwFlags & DDSD_MIPMAPCOUNT) != 0)
                    {
                        mipMapCount = header.dwMipMapCount;
                    }

                    mipMaps = new MipMap[mipMapCount];

                    ddsFormat = getFormat();

                    double bytePerPixel = getBytesPerPixel(ddsFormat);

                    for (int i = 0; i < mipMapCount; i++)
                    {
                        int w = (int)(header.dwWidth / Math.Pow(2, i));
                        int h = (int)(header.dwHeight / Math.Pow(2, i));

                        if (ddsFormat == DDSFormat.DXT1 || ddsFormat == DDSFormat.DXT5)
                        {
                            w = (w < 4) ? 4 : w;
                            h = (h < 4) ? 4 : h;
                        }

                        int mipMapBytes = (int)(w * h * bytePerPixel);
                        mipMaps[i] = new MipMap(r.ReadBytes(mipMapBytes), ddsFormat, w, h);
                    }
                }
            }
        }
Beispiel #13
0
        private Bitmap readBlockImage(byte[] imgData, int w, int h)
        {
            switch (header.ddspf.dwFourCC)
            {
            case FOURCC_DXT1:
                ddsFormat = DDSFormat.DXT1;
                return(UncompressDXT1(imgData, w, h));

            case FOURCC_DXT5:
                ddsFormat = DDSFormat.DXT5;
                return(UncompressDXT5(imgData, w, h));

            default: break;
            }
            throw new Exception("invalid texture format");
        }
        /// <summary>
        /// Gets block size of DDS format.
        /// Number of channels if not compressed.
        /// 1 if not a DDS format.
        /// </summary>
        /// <param name="format">DDS format to test.</param>
        /// <param name="componentSize">Size of channel components in bytes. e.g. 16bit = 2.</param>
        /// <returns>Number of blocks/channels in format.</returns>
        static int GetBlockSize(DDSFormat format, int componentSize = 1)
        {
            int blocksize = 1;

            switch (format)
            {
            case DDSFormat.DDS_ATI1:
            case DDSFormat.DDS_DXT1:
                blocksize = 8;
                break;

            case DDSFormat.DDS_DXT2:
            case DDSFormat.DDS_DXT3:
            case DDSFormat.DDS_DXT4:
            case DDSFormat.DDS_DXT5:
            case DDSFormat.DDS_ATI2_3Dc:
            case DDSFormat.DDS_DX10:
                blocksize = 16;
                break;

            case DDSFormat.DDS_V8U8:
            case DDSFormat.DDS_A8L8:
            case DDSFormat.DDS_ARGB_4:
                blocksize = 2;
                break;

            case DDSFormat.DDS_ARGB_8:
            case DDSFormat.DDS_ABGR_8:
            case DDSFormat.DDS_G16_R16:
                blocksize = 4;
                break;

            case DDSFormat.DDS_RGB_8:
                blocksize = 3;
                break;

            case DDSFormat.DDS_ARGB_32F:
                blocksize = 16;
                break;

            case DDSFormat.DDS_CUSTOM:
                blocksize = 4 * componentSize;
                break;
            }
            return(blocksize);
        }
        public static byte[] CreateDDS(string input, DDSFormat format, MipmapMethod mipm, bool slow, bool flip)
        {
            LoadLibraries();
            using (var stream = new MemoryStream())
            {
                using (var compress = new Compressor())
                {
                    compress.Input.GenerateMipmaps = false;
                    List <TeximpNet.Surface> toDispose = null;
                    if (mipm == MipmapMethod.None)
                    {
                        using (var surface = TeximpNet.Surface.LoadFromFile(input))
                        {
                            if (flip)
                            {
                                surface.FlipVertically();
                            }
                            compress.Input.SetData(surface);
                        }
                    }
                    else
                    {
                        var mips = GenerateMipmapsRGBA(input, mipm, flip);
                        compress.Input.SetTextureLayout(TextureType.Texture2D, mips[0].Width, mips[0].Height);

                        for (int i = 0; i < mips.Count; i++)
                        {
                            compress.Input.SetMipmapData(mips[i], i);
                        }
                        toDispose = mips;
                    }
                    compress.Compression.Format  = (CompressionFormat)format;
                    compress.Compression.Quality = slow ? CompressionQuality.Production : CompressionQuality.Normal;
                    compress.Compression.SetBGRAPixelFormat();
                    compress.Process(stream);
                    if (toDispose != null)
                    {
                        foreach (var sfc in toDispose)
                        {
                            sfc.Dispose();
                        }
                    }
                }
                return(stream.ToArray());
            }
        }
Beispiel #16
0
        public static Bitmap ToBitmap(byte[] imgData, DDSFormat ddsFormat, int w, int h)
        {
            switch (ddsFormat)
            {
            case DDSFormat.DXT1: return(UncompressDXT1(imgData, w, h));

            case DDSFormat.DXT5: return(UncompressDXT5(imgData, w, h));

            case DDSFormat.V8U8: return(UncompressV8U8(imgData, w, h));

            case DDSFormat.ATI2: return(UncompressATI2(imgData, w, h));

            case DDSFormat.G8: return(ViewG8(imgData, w, h));

            case DDSFormat.ARGB: return(View32Bit(imgData, w, h));
            }
            throw new Exception("invalid texture format " + ddsFormat);
        }
        /// <summary>
        /// Determines if format is a block compressed format.
        /// </summary>
        /// <param name="format">DDS Surface Format.</param>
        /// <returns>True if block compressed.</returns>
        static bool IsBlockCompressed(DDSFormat format)
        {
            switch (format)
            {
            case DDSFormat.DDS_ATI1:
            case DDSFormat.DDS_DXT1:
            case DDSFormat.DDS_DXT2:
            case DDSFormat.DDS_DXT3:
            case DDSFormat.DDS_DXT4:
            case DDSFormat.DDS_DXT5:
            case DDSFormat.DDS_ATI2_3Dc:
            case DDSFormat.DDS_DX10:
                return(true);

            default:
                return(false);
            }
        }
Beispiel #18
0
        public DDSPreview(byte[] data)
        {
            if (BitConverter.ToUInt32(data, 0) != DDSMagic)
                throw new FormatException("Invalid DDS Magic Number");
            if (BitConverter.ToUInt32(data, 4) != 0x7C)
                throw new FormatException("Invalid header size");
            DDSFlags = BitConverter.ToUInt32(data, 8);
            if ((DDSFlags & 0x1) != 0x1 || (DDSFlags & 0x2) != 0x2 || (DDSFlags & 0x4) != 0x4 || (DDSFlags & 0x1000) != 0x1000)
                throw new FormatException("Invalid DDS Flags");
            mips = (DDSFlags & 0x20000) == 0x20000;
            Height = BitConverter.ToUInt32(data, 12);
            Width = BitConverter.ToUInt32(data, 16);
            // Skip pitch and depth, unimportant
            NumMips = BitConverter.ToUInt32(data, 28);
            uint pxformat = BitConverter.ToUInt32(data, 84);
            Format = GetDDSFormat(pxformat);
            imgData = new byte[data.Length - 0x80];
            Array.Copy(data, 0x80, imgData, 0, imgData.Length);

            pfFlags = BitConverter.ToUInt32(data, 0x50);
            fourCC = BitConverter.ToUInt32(data, 0x54);
            rgbBitCount = BitConverter.ToUInt32(data, 0x58);
            rBitMask = BitConverter.ToUInt32(data, 0x5C);
            gBitMask = BitConverter.ToUInt32(data, 0x60);
            bBitMask = BitConverter.ToUInt32(data, 0x64);
            aBitMask = BitConverter.ToUInt32(data, 0x68);

            FormatString = GetFormat();

            switch (FormatString)
            {
                case "DXT1": BPP = 0.5F; stdDDS = true; compressed = true; break;
                case "DXT5": BPP = 1F; stdDDS = true; compressed = true; break;
                case "V8U8": BPP = 2F; stdDDS = true; compressed = false; break;
                case "ATI2": BPP = 1F; stdDDS = true; compressed = true; break;
                case "A8B8G8R8":
                case "A8R8G8B8": BPP = 4F; stdDDS = false; compressed = false; break;
                case "B8G8R8":
                case "R8G8B8": BPP = 3F; stdDDS = false; compressed = false; break;
                default: BPP = 1; stdDDS = false; compressed = false; break;
            }
        }
        public static double getBytesPerPixel(DDSFormat ddsFormat)
        {
            switch (ddsFormat)
            {
            case DDSFormat.DXT1: return(0.5);

            case DDSFormat.DXT3:
            case DDSFormat.DXT5:
            case DDSFormat.ATI2:
            case DDSFormat.G8: return(1);

            case DDSFormat.V8U8: return(2);

            case DDSFormat.ARGB: return(4);

            case DDSFormat.RGB: return(3);

            default:
                throw new Exception("invalid texture format " + ddsFormat);
            }
        }
        public static PngBitmapEncoder ToPng(byte[] imgData, DDSFormat ddsFormat, int w, int h)
        {
            switch (ddsFormat)
            {
            case DDSFormat.DXT1: return(DXT1ToPng(imgData, w, h));

            case DDSFormat.DXT5: return(DXT5ToPng(imgData, w, h));

            case DDSFormat.ATI2: return(ATI2ToPng(imgData, w, h));

            case DDSFormat.V8U8: return(V8U8ToPng(imgData, w, h));

            case DDSFormat.G8: return(G8ToPng(imgData, w, h));

            case DDSFormat.ARGB: return(RGBAToPng(imgData, w, h));

            case DDSFormat.RGB: return(RGBToPng(imgData, w, h));

            default:
                throw new Exception("invalid texture format " + ddsFormat);
            }
        }
        public static Bitmap ToBitmap(byte[] imgData, DDSFormat ddsFormat, int w, int h)
        {
            switch (ddsFormat)
            {
            case DDSFormat.DXT1: return(DXT1ToBitmap(imgData, w, h));

            case DDSFormat.DXT5: return(DXT5ToBitmap(imgData, w, h));

            case DDSFormat.ATI2: return(ATI2ToBitmap(imgData, w, h));

            case DDSFormat.V8U8: return(V8U8ToBitmap(imgData, w, h));

            case DDSFormat.G8: return(ViewG8(imgData, w, h));

            case DDSFormat.ARGB: return(View32Bit(imgData, w, h));

            case DDSFormat.RGB: return(View24Bit(imgData, w, h));

            default:
                throw new Exception("invalid texture format " + ddsFormat);
            }
        }
Beispiel #22
0
        public void extractTextureToPng(string outputFile, string packagePath, int exportID)
        {
            Package   package = new Package(packagePath);
            Texture   texture = new Texture(package, exportID, package.getExportData(exportID));
            DDSFormat format  = DDSImage.convertFormat(texture.properties.getProperty("Format").valueName);

            Texture.MipMap mipmap = texture.getTopMipmap();
            byte[]         data   = texture.getTopImageData();
            if (data == null)
            {
                MessageBox.Show("Failed to extract to PNG file. Broken game files!");
                return;
            }
            PngBitmapEncoder image = DDSImage.ToPng(data, format, mipmap.width, mipmap.height);

            if (File.Exists(outputFile))
            {
                File.Delete(outputFile);
            }
            using (FileStream fs = new FileStream(outputFile, FileMode.CreateNew, FileAccess.Write))
            {
                image.Save(fs);
            }
        }
        internal static List <MipMap> LoadDDS(MemoryStream compressed, DDS_Header header, int desiredMaxDimension, DDSFormatDetails formatDetails)
        {
            MipMap[] MipMaps = null;

            int       mipWidth  = header.Width;
            int       mipHeight = header.Height;
            DDSFormat format    = header.Format;

            int estimatedMips  = header.dwMipMapCount;
            int mipOffset      = formatDetails.HeaderSize;
            int originalOffset = mipOffset;

            if (!EnsureMipInImage(compressed.Length, mipWidth, mipHeight, 4, formatDetails, out mipOffset))  // Update number of mips too
            {
                estimatedMips = 1;
            }

            if (estimatedMips == 0)
            {
                estimatedMips = EstimateNumMipMaps(mipWidth, mipHeight);
            }

            mipOffset = originalOffset;  // Needs resetting after checking there's mips in this image.

            // Ensure there's at least 1 mipmap
            if (estimatedMips == 0)
            {
                estimatedMips = 1;
            }

            int orig_estimatedMips = estimatedMips; // Store original count for later (uncompressed only I think)

            // KFreon: Decide which mip to start loading at - going to just load a few mipmaps if asked instead of loading all, then choosing later. That's slow.
            if (desiredMaxDimension != 0 && estimatedMips > 1)
            {
                if (!EnsureMipInImage(compressed.Length, mipWidth, mipHeight, desiredMaxDimension, formatDetails, out mipOffset))  // Update number of mips too
                {
                    throw new InvalidDataException($"Requested mipmap does not exist in this image. Top Image Size: {mipWidth}x{mipHeight}, requested mip max dimension: {desiredMaxDimension}.");
                }

                // Not the first mipmap.
                if (mipOffset > formatDetails.HeaderSize)
                {
                    double divisor = mipHeight > mipWidth ? mipHeight / desiredMaxDimension : mipWidth / desiredMaxDimension;
                    mipHeight = (int)(mipHeight / divisor);
                    mipWidth  = (int)(mipWidth / divisor);

                    if (mipWidth == 0 || mipHeight == 0)  // Reset as a dimension is too small to resize
                    {
                        mipHeight = header.Height;
                        mipWidth  = header.Width;
                        mipOffset = formatDetails.HeaderSize;
                    }
                    else
                    {
                        // Update estimated mips due to changing dimensions.
                        estimatedMips = EstimateNumMipMaps(mipWidth, mipHeight);
                    }
                }
                else  // The first mipmap
                {
                    mipOffset = formatDetails.HeaderSize;
                }
            }

            // Move to requested mipmap
            compressed.Position = mipOffset;

            // Block Compressed texture chooser.
            Action <byte[], int, byte[], int, int, bool> DecompressBCBlock = formatDetails.BlockDecoder;

            MipMaps = new MipMap[estimatedMips];
            int blockSize = formatDetails.BlockSize;

            // KFreon: Read mipmaps
            if (formatDetails.IsBlockCompressed)    // Threading done in the decompression, not here.
            {
                for (int m = 0; m < estimatedMips; m++)
                {
                    // KFreon: If mip is too small, skip out. This happens most often with non-square textures. I think it's because the last mipmap is square instead of the same aspect.
                    // Don't do the mip size check here (<4) since we still need to have a MipMap object for those lower than this for an accurate count.
                    if (mipWidth <= 0 || mipHeight <= 0)  // Needed cos it doesn't throw when reading past the end for some reason.
                    {
                        break;
                    }

                    MipMap mipmap = ReadCompressedMipMap(compressed, mipWidth, mipHeight, mipOffset, formatDetails, DecompressBCBlock);
                    MipMaps[m] = mipmap;
                    mipOffset += (int)(mipWidth * mipHeight * (blockSize / 16d)); // Also put the division in brackets cos if the mip dimensions are high enough, the multiplications can exceed int.MaxValue)
                    mipWidth  /= 2;
                    mipHeight /= 2;
                }
            }
            else
            {
                int startMip = orig_estimatedMips - estimatedMips;

                // UNCOMPRESSED - Can't really do threading in "decompression" so do it for the mipmaps.
                var action = new Action <int>(mipIndex =>
                {
                    // Calculate mipOffset and dimensions
                    int offset, width, height;
                    offset = GetMipOffset(mipIndex, formatDetails, header.Width, header.Height);

                    double divisor = mipIndex == 0 ? 1d : 2 << (mipIndex - 1);   // Divisor represents 2^mipIndex - Math.Pow seems very slow.
                    width          = (int)(header.Width / divisor);
                    height         = (int)(header.Height / divisor);

                    MipMap mipmap = null;
                    try
                    {
                        mipmap = ReadUncompressedMipMap(compressed, offset, width, height, header.ddspf, formatDetails);
                    }
                    catch (Exception e)
                    {
                        Debug.WriteLine(e.ToString());
                    }

                    MipMaps[mipIndex] = mipmap;
                });

                if (EnableThreading)
                {
                    Parallel.For(startMip, orig_estimatedMips, new ParallelOptions {
                        MaxDegreeOfParallelism = ThreadCount
                    }, (mip, loopState) =>
                    {
                        action(mip);
                    });
                }
                else
                {
                    for (int i = startMip; i < orig_estimatedMips; i++)
                    {
                        action(i);
                    }
                }
            }

            List <MipMap> mips = new List <MipMap>(MipMaps.Where(t => t != null));

            if (mips.Count == 0)
            {
                throw new InvalidOperationException($"No mipmaps loaded. Estimated mips: {estimatedMips}, mip dimensions: {mipWidth}x{mipHeight}");
            }
            return(mips);
        }
            /// <summary>
            /// Details the given format.
            /// </summary>
            /// <param name="dxgiFormat">Optional DX10 format. Default = Unknown.</param>
            /// <param name="inFormat">Image Format.</param>
            public DDSFormatDetails(DDSFormat inFormat, DDS_Header.DXGI_FORMAT dxgiFormat = new DDS_Header.DXGI_FORMAT())
            {
                Format = inFormat;

                DX10Format = dxgiFormat;

                BitCount = 8;
                {
                    switch (inFormat)
                    {
                    case DDSFormat.DDS_G8_L8:
                    case DDSFormat.DDS_A8:
                    case DDSFormat.DDS_ATI1:
                        BitCount = 8;
                        break;

                    case DDSFormat.DDS_A8L8:
                    case DDSFormat.DDS_V8U8:
                    case DDSFormat.DDS_ATI2_3Dc:
                        BitCount = 16;
                        break;

                    case DDSFormat.DDS_ABGR_8:
                    case DDSFormat.DDS_ARGB_8:
                    case DDSFormat.DDS_DXT1:
                    case DDSFormat.DDS_DXT2:
                    case DDSFormat.DDS_DXT3:
                    case DDSFormat.DDS_DXT4:
                    case DDSFormat.DDS_DXT5:
                    case DDSFormat.DDS_G16_R16:
                        BitCount = 32;
                        break;

                    case DDSFormat.DDS_RGB_8:
                        BitCount = 24;
                        break;

                    case DDSFormat.DDS_ARGB_32F:
                        DX10Format = DDS_Header.DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT;
                        BitCount   = 128;
                        break;

                    case DDSFormat.DDS_R5G6B5:
                        BitCount = 16;
                        break;

                    case DDSFormat.DDS_ARGB_4:
                    case DDSFormat.DDS_CUSTOM:
                    case DDSFormat.DDS_DX10:
                        BitCount = GetDX10BitCount(DX10Format);
                        break;
                    }
                }

                // Functions
                ReadByte          = ReadByteFromByte;
                ReadUShort        = ReadUShortFromByte;
                ReadFloat         = ReadFloatFromByte;
                SetMaxValue       = WriteByteMax;
                WriteColor        = WriteByte;
                ReadUShortAsArray = ReadUShortFromByteAsArray;
                ReadFloatAsArray  = ReadFloatFromByteOrUShortAsArray;

                if (ComponentSize == 2)
                {
                    ReadByte          = ReadByteFromUShort;
                    ReadUShort        = ReadUShortFromUShort;
                    ReadFloat         = ReadFloatFromUShort;
                    SetMaxValue       = WriteUShortMax;
                    WriteColor        = WriteUShort;
                    ReadUShortAsArray = ReadUShortFromUShortAsArray;
                    // Don't need ReadFloatAsArray set here, as it's shared between byte and ushort reading.
                }
                else if (ComponentSize == 4)
                {
                    ReadByte          = ReadByteFromFloat;
                    ReadUShort        = ReadUShortFromFloat;
                    ReadFloat         = ReadFloatFromFloat;
                    SetMaxValue       = WriteFloatMax;
                    WriteColor        = WriteFloat;
                    ReadUShortAsArray = ReadUShortFromFloatAsArray;
                    ReadFloatAsArray  = ReadFloatFromFloatAsArray;
                }


                switch (inFormat)
                {
                case DDSFormat.DDS_ATI1:
                    BlockEncoder = DDS_Encoders.CompressBC4Block;
                    break;

                case DDSFormat.DDS_ATI2_3Dc:
                    BlockEncoder = DDS_Encoders.CompressBC5Block;
                    break;

                case DDSFormat.DDS_DX10:
                    if (DX10Format.ToString().Contains("BC7"))
                    {
                        BlockEncoder = DDS_Encoders.CompressBC7Block;
                    }
                    else
                    {
                        BlockEncoder = DDS_Encoders.CompressBC6Block;
                    }
                    break;

                case DDSFormat.DDS_DXT1:
                    BlockEncoder = DDS_Encoders.CompressBC1Block;
                    break;

                case DDSFormat.DDS_DXT2:
                case DDSFormat.DDS_DXT3:
                    BlockEncoder = DDS_Encoders.CompressBC2Block;
                    break;

                case DDSFormat.DDS_DXT4:
                case DDSFormat.DDS_DXT5:
                    BlockEncoder = DDS_Encoders.CompressBC3Block;
                    break;
                }

                switch (inFormat)
                {
                case DDSFormat.DDS_DXT1:
                    BlockDecoder = DDS_Decoders.DecompressBC1Block;
                    break;

                case DDSFormat.DDS_DXT2:
                case DDSFormat.DDS_DXT3:
                    BlockDecoder = DDS_Decoders.DecompressBC2Block;
                    break;

                case DDSFormat.DDS_DXT4:
                case DDSFormat.DDS_DXT5:
                    BlockDecoder = DDS_Decoders.DecompressBC3Block;
                    break;

                case DDSFormat.DDS_ATI1:
                    BlockDecoder = DDS_Decoders.DecompressATI1Block;
                    break;

                case DDSFormat.DDS_ATI2_3Dc:
                    BlockDecoder = DDS_Decoders.DecompressATI2Block;
                    break;

                case DDSFormat.DDS_DX10:
                    if (DX10Format.ToString().Contains("BC7"))
                    {
                        BlockDecoder = DDS_Decoders.DecompressBC7Block;
                    }
                    else
                    {
                        BlockDecoder = DDS_Decoders.DecompressBC6Block;
                    }
                    break;
                }
            }
        private DDS_PIXELFORMAT getDDSPixelFormat(DDSFormat format)
        {
            DDS_PIXELFORMAT pixelFormat = new DDS_PIXELFORMAT();

            switch (format)
            {
            case DDSFormat.DXT1:
                pixelFormat.dwFlags  = DDPF_FOURCC;
                pixelFormat.dwFourCC = FOURCC_DXT1;
                break;

            case DDSFormat.DXT3:
                pixelFormat.dwFlags  = DDPF_FOURCC;
                pixelFormat.dwFourCC = FOURCC_DXT3;
                break;

            case DDSFormat.DXT5:
                pixelFormat.dwFlags  = DDPF_FOURCC;
                pixelFormat.dwFourCC = FOURCC_DXT5;
                break;

            case DDSFormat.ATI2:
                pixelFormat.dwFlags  = DDPF_FOURCC;
                pixelFormat.dwFourCC = FOURCC_ATI2;
                break;

            case DDSFormat.V8U8:
                pixelFormat.dwFlags       = 0x80000;
                pixelFormat.dwRGBBitCount = 0x10;
                pixelFormat.dwRBitMask    = 0xFF;
                pixelFormat.dwGBitMask    = 0xFF00;
                pixelFormat.dwBBitMask    = 0x00;
                pixelFormat.dwABitMask    = 0x00;
                break;

            case DDSFormat.G8:
                pixelFormat.dwFlags       = DDPF_LUMINANCE;
                pixelFormat.dwRGBBitCount = 0x08;
                pixelFormat.dwRBitMask    = 0xFF;
                pixelFormat.dwGBitMask    = 0x00;
                pixelFormat.dwBBitMask    = 0x00;
                pixelFormat.dwABitMask    = 0x00;
                break;

            case DDSFormat.ARGB:
                pixelFormat.dwFlags       = DDPF_ALPHAPIXELS | DDPF_RGB;
                pixelFormat.dwRGBBitCount = 0x20;
                pixelFormat.dwRBitMask    = 0xFF0000;
                pixelFormat.dwGBitMask    = 0xFF00;
                pixelFormat.dwBBitMask    = 0xFF;
                pixelFormat.dwABitMask    = 0xFF000000;
                break;

            case DDSFormat.RGB:
                pixelFormat.dwFlags       = DDPF_RGB;
                pixelFormat.dwRGBBitCount = 0x18;
                pixelFormat.dwRBitMask    = 0xFF0000;
                pixelFormat.dwGBitMask    = 0xFF00;
                pixelFormat.dwBBitMask    = 0xFF;
                pixelFormat.dwABitMask    = 0x00;
                break;

            default:
                throw new Exception("invalid texture format " + ddsFormat);
            }
            return(pixelFormat);
        }
        public static byte[] CreateDDS(string input, DDSFormat format, MipmapMethod mipm, bool slow, bool flip)
        {
            var raw = ReadFile(input, flip);

            return(Crunch.CompressDDS(raw.Data, raw.Width, raw.Height, (CrnglueFormat)format, (CrnglueMipmaps)mipm, slow));
        }
Beispiel #27
0
            public MipMap(byte[] data, DDSFormat format, int w, int h)
            {
                long requiredSize = (long)(w * h * getBytesPerPixel(format));
                if (data.Length != requiredSize)
                    throw new InvalidDataException("Data size is not valid for selected format.\nActual: " + data.Length + " bytes\nRequired: " + requiredSize + " bytes");

                this.data = data;
                ddsFormat = format;
                width = w;
                height = h;
            }
Beispiel #28
0
 public static Bitmap ToBitmap(byte[] imgData, DDSFormat ddsFormat, int w, int h)
 {
     switch (ddsFormat)
     {
         case DDSFormat.DXT1: return UncompressDXT1(imgData, w, h);
         case DDSFormat.DXT5: return UncompressDXT5(imgData, w, h);
         case DDSFormat.V8U8: return UncompressV8U8(imgData, w, h);
         case DDSFormat.ATI2: return UncompressATI2(imgData, w, h);
         case DDSFormat.G8: return ViewG8(imgData, w, h);
         case DDSFormat.ARGB: return View32Bit(imgData, w, h);
     }
     throw new Exception("invalid texture format " + ddsFormat);
 }
Beispiel #29
0
 private Bitmap readBlockImage(byte[] imgData, int w, int h)
 {
     switch (header.ddspf.dwFourCC)
     {
         case FOURCC_DXT1:
             ddsFormat = DDSFormat.DXT1;
             return UncompressDXT1(imgData, w, h);
         case FOURCC_DXT5:
             ddsFormat = DDSFormat.DXT5;
             return UncompressDXT5(imgData, w, h);
         default: break;
     }
     throw new Exception("invalid texture format");
 }
Beispiel #30
0
 public static double getBytesPerPixel(DDSFormat ddsFormat)
 {
     switch (ddsFormat)
     {
         case DDSFormat.DXT1: return 0.5;
         case DDSFormat.DXT5:
         case DDSFormat.ATI2: return 1;
         case DDSFormat.V8U8: return 2;
     }
     throw new Exception("invalid texture format");
 }
Beispiel #31
0
        public string createTextureMod(string inDir, string outFile, List <FoundTexture> textures, MainWindow mainWindow, ref string log)
        {
            string errors = "";
            int    count  = 0;

            List <string> files = Directory.GetFiles(inDir, "*.dds").Where(item => item.EndsWith(".dds", StringComparison.OrdinalIgnoreCase)).ToList();

            files.Sort();
            List <FileMod> modFiles = new List <FileMod>();

            using (FileStream outFs = new FileStream(outFile, FileMode.Create, FileAccess.Write))
            {
                outFs.WriteUInt32(TexExplorer.TextureModTag);
                outFs.WriteUInt32(TexExplorer.TextureModVersion);
                outFs.WriteInt64(0); // files info offset - filled later

                for (int n = 0; n < files.Count(); n++)
                {
                    string file = files[n];
                    if (mainWindow != null)
                    {
                        mainWindow.updateStatusLabel("Creating MOD: " + Path.GetFileName(outFile));
                        mainWindow.updateStatusLabel2("Texture " + (n + 1) + " of " + files.Count() + ", File: " + Path.GetFileName(file));
                    }
                    string filename = Path.GetFileNameWithoutExtension(file).ToLowerInvariant();
                    if (!filename.Contains("0x"))
                    {
                        errors += "Texture filename not valid: " + Path.GetFileName(file) + " Texture filename must include texture CRC (0xhhhhhhhh). Skipping texture..." + Environment.NewLine;
                        log    += "Texture filename not valid: " + Path.GetFileName(file) + " Texture filename must include texture CRC (0xhhhhhhhh). Skipping texture..." + Environment.NewLine;
                        continue;
                    }
                    int idx = filename.IndexOf("0x");
                    if (filename.Length - idx < 10)
                    {
                        errors += "Texture filename not valid: " + Path.GetFileName(file) + " Texture filename must include texture CRC (0xhhhhhhhh). Skipping texture..." + Environment.NewLine;
                        log    += "Texture filename not valid: " + Path.GetFileName(file) + " Texture filename must include texture CRC (0xhhhhhhhh). Skipping texture..." + Environment.NewLine;
                        continue;
                    }
                    uint   crc;
                    string crcStr = filename.Substring(idx + 2, 8);
                    try
                    {
                        crc = uint.Parse(crcStr, System.Globalization.NumberStyles.HexNumber);
                    }
                    catch
                    {
                        errors += "Texture filename not valid: " + Path.GetFileName(file) + " Texture filename must include texture CRC (_0xhhhhhhhh). Skipping texture..." + Environment.NewLine;
                        log    += "Texture filename not valid: " + Path.GetFileName(file) + " Texture filename must include texture CRC (_0xhhhhhhhh). Skipping texture..." + Environment.NewLine;
                        continue;
                    }

                    List <FoundTexture> foundCrcList = textures.FindAll(s => s.crc == crc);
                    if (foundCrcList.Count == 0)
                    {
                        errors += "Texture skipped. Texture " + Path.GetFileName(file) + " is not present in your game setup." + Environment.NewLine;
                        log    += "Texture skipped. Texture " + Path.GetFileName(file) + " is not present in your game setup." + Environment.NewLine;
                        continue;
                    }

                    int savedCount = count;
                    using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
                    {
                        byte[]   src   = fs.ReadToBuffer((int)fs.Length);
                        DDSImage image = new DDSImage(new MemoryStream(src));
                        if (!image.checkExistAllMipmaps())
                        {
                            errors += "Error in texture: " + Path.GetFileName(file) + " This texture has not all the required mipmaps, skipping texture..." + Environment.NewLine;
                            log    += "Error in texture: " + Path.GetFileName(file) + " This texture has not all the required mipmaps, skipping texture..." + Environment.NewLine;
                            continue;
                        }

                        Package pkg     = new Package(GameData.GamePath + foundCrcList[0].list[0].path);
                        Texture texture = new Texture(pkg, foundCrcList[0].list[0].exportID, pkg.getExportData(foundCrcList[0].list[0].exportID));

                        if (texture.mipMapsList.Count > 1 && image.mipMaps.Count() <= 1)
                        {
                            errors += "Error in texture: " + Path.GetFileName(file) + " This texture must have mipmaps, skipping texture..." + Environment.NewLine;
                            log    += "Error in texture: " + Path.GetFileName(file) + " This texture must have mipmaps, skipping texture..." + Environment.NewLine;
                            continue;
                        }

                        string    fmt       = texture.properties.getProperty("Format").valueName;
                        DDSFormat ddsFormat = DDSImage.convertFormat(fmt);
                        if (image.ddsFormat != ddsFormat)
                        {
                            errors += "Error in texture: " + Path.GetFileName(file) + " This texture has wrong texture format, should be: " + ddsFormat + ", skipping texture..." + Environment.NewLine;
                            log    += "Error in texture: " + Path.GetFileName(file) + " This texture has wrong texture format, should be: " + ddsFormat + ", skipping texture..." + Environment.NewLine;
                            continue;
                        }

                        if (image.mipMaps[0].origWidth / image.mipMaps[0].origHeight !=
                            texture.mipMapsList[0].width / texture.mipMapsList[0].height)
                        {
                            errors += "Error in texture: " + Path.GetFileName(file) + " This texture has wrong aspect ratio, skipping texture..." + Environment.NewLine;
                            log    += "Error in texture: " + Path.GetFileName(file) + " This texture has wrong aspect ratio, skipping texture..." + Environment.NewLine;
                            continue;
                        }

                        Stream dst = compressData(src);
                        dst.SeekBegin();

                        FileMod fileMod = new FileMod();
                        fileMod.tag    = FileTextureTag;
                        fileMod.name   = Path.GetFileName(file);
                        fileMod.offset = outFs.Position;
                        fileMod.size   = dst.Length;
                        count++;
                        modFiles.Add(fileMod);

                        outFs.WriteStringASCIINull(foundCrcList[0].name);
                        outFs.WriteUInt32(crc);
                        outFs.WriteFromStream(dst, dst.Length);
                    }
                    if (count == savedCount)
                    {
                        continue;
                    }
                }
                long pos = outFs.Position;
                outFs.SeekBegin();
                outFs.WriteUInt32(TexExplorer.TextureModTag);
                outFs.WriteUInt32(TexExplorer.TextureModVersion);
                outFs.WriteInt64(pos);
                outFs.JumpTo(pos);
                outFs.WriteUInt32((uint)GameData.gameType);
                outFs.WriteInt32(modFiles.Count);
                for (int i = 0; i < modFiles.Count; i++)
                {
                    outFs.WriteUInt32(modFiles[i].tag);
                    outFs.WriteStringASCIINull(modFiles[i].name);
                    outFs.WriteInt64(modFiles[i].offset);
                    outFs.WriteInt64(modFiles[i].size);
                }
            }
            if (count == 0)
            {
                errors += "There are no texture files in " + inDir + ", mod not generated." + Environment.NewLine;
                log    += "There are no texture files in " + inDir + ", mod not generated." + Environment.NewLine;
                File.Delete(outFile);
            }
            return(errors);
        }
Beispiel #32
0
		public static void RunNVCompress(Bitmap bitmap, AssetBundle bundle, string path, AssetAttributes attributes, DDSFormat format, bool mipMaps, byte[] CookingRulesSHA1)
		{
			bool compressed = format == DDSFormat.DXTi;
			Bitmap bledBitmap = null;
			if (bitmap.HasAlpha) {
				bledBitmap = TextureConverterUtils.BleedAlpha(bitmap);
			}
			var ddsPath = Toolbox.GetTempFilePathWithExtension(".dds");
			var tgaPath = Path.ChangeExtension(ddsPath, ".tga");
			try {
				TextureConverterUtils.SaveToTGA(bledBitmap ?? bitmap, tgaPath, swapRedAndBlue: compressed);
				if (bledBitmap != null && bledBitmap != bitmap) {
					bledBitmap.Dispose();
				}
				RunNVCompressHelper(tgaPath, ddsPath, bitmap.HasAlpha, compressed, mipMaps);
				bundle.ImportFile(ddsPath, path, 0, "", attributes, CookingRulesSHA1);
			} finally {
				DeletePossibleLockedFile(ddsPath);
				DeletePossibleLockedFile(tgaPath);
			}
		}
        static private string convertDataModtoMem(string inputDir, string memFilePath)
        {
            string errors = "";

            string[] files = null;

            Console.WriteLine("Mods conversion started...");

            List <string> list = Directory.GetFiles(inputDir, "*.tpf").Where(item => item.EndsWith(".tpf", StringComparison.OrdinalIgnoreCase)).ToList();

            list.AddRange(Directory.GetFiles(inputDir, "*.mod").Where(item => item.EndsWith(".mod", StringComparison.OrdinalIgnoreCase)));
            list.AddRange(Directory.GetFiles(inputDir, "*.dds").Where(item => item.EndsWith(".dds", StringComparison.OrdinalIgnoreCase)));
            list.Sort();
            files = list.ToArray();

            int    result;
            string fileName = "";
            uint   dstLen   = 0;

            string[] ddsList    = null;
            ulong    numEntries = 0;
            List <TexExplorer.BinaryMod> mods = new List <TexExplorer.BinaryMod>();

            foreach (string file in files)
            {
                if (file.EndsWith(".mod", StringComparison.OrdinalIgnoreCase))
                {
                    try
                    {
                        using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
                        {
                            string package = "";
                            int    len     = fs.ReadInt32();
                            string version = fs.ReadStringASCII(len); // version
                            if (version.Length < 5)                   // legacy .mod
                            {
                                fs.SeekBegin();
                            }
                            numEntries = fs.ReadUInt32();
                            for (uint i = 0; i < numEntries; i++)
                            {
                                TexExplorer.BinaryMod mod = new TexExplorer.BinaryMod();
                                len = fs.ReadInt32();
                                string desc = fs.ReadStringASCII(len); // description
                                len = fs.ReadInt32();
                                string scriptLegacy = fs.ReadStringASCII(len);
                                string path         = "";
                                if (desc.Contains("Binary Replacement"))
                                {
                                    try
                                    {
                                        Misc.ParseME3xBinaryScriptMod(scriptLegacy, ref package, ref mod.exportId, ref path);
                                        if (mod.exportId == -1 || package == "" || path == "")
                                        {
                                            throw new Exception();
                                        }
                                    }
                                    catch
                                    {
                                        len = fs.ReadInt32();
                                        fs.Skip(len);
                                        errors += "Skipping not compatible content, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                        continue;
                                    }
                                    mod.packagePath = GameData.RelativeGameData(Path.Combine(path, package));
                                    mod.binaryMod   = true;
                                    len             = fs.ReadInt32();
                                    mod.data        = fs.ReadToBuffer(len);
                                }
                                else
                                {
                                    string       textureName = desc.Split(' ').Last();
                                    FoundTexture f;
                                    try
                                    {
                                        f = Misc.ParseLegacyMe3xScriptMod(textures, scriptLegacy, textureName);
                                        mod.textureCrc = f.crc;
                                        if (mod.textureCrc == 0)
                                        {
                                            throw new Exception();
                                        }
                                    }
                                    catch
                                    {
                                        len = fs.ReadInt32();
                                        fs.Skip(len);
                                        errors += "Skipping not compatible content, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                        continue;
                                    }
                                    textureName     = f.name;
                                    mod.textureName = textureName;
                                    mod.binaryMod   = false;
                                    len             = fs.ReadInt32();
                                    mod.data        = fs.ReadToBuffer(len);
                                    DDSImage image = new DDSImage(new MemoryStream(mod.data));
                                    if (!image.checkExistAllMipmaps())
                                    {
                                        errors += "Error in texture: " + textureName + string.Format("_0x{0:X8}", f.crc) + " This texture has not all the required mipmaps, skipping texture, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                        continue;
                                    }
                                    Package pkg     = new Package(GameData.GamePath + f.list[0].path);
                                    Texture texture = new Texture(pkg, f.list[0].exportID, pkg.getExportData(f.list[0].exportID));

                                    if (texture.mipMapsList.Count > 1 && image.mipMaps.Count() <= 1)
                                    {
                                        errors += "Error in texture: " + textureName + string.Format("_0x{0:X8}", f.crc) + " This texture must have mipmaps, skipping texture, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                        continue;
                                    }

                                    string    fmt       = texture.properties.getProperty("Format").valueName;
                                    DDSFormat ddsFormat = DDSImage.convertFormat(fmt);
                                    if (image.ddsFormat != ddsFormat)
                                    {
                                        errors += "Error in texture: " + textureName + string.Format("_0x{0:X8}", f.crc) + " This texture has wrong texture format, should be: " + ddsFormat + ", skipping texture, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                        continue;
                                    }

                                    if (image.mipMaps[0].origWidth / image.mipMaps[0].origHeight !=
                                        texture.mipMapsList[0].width / texture.mipMapsList[0].height)
                                    {
                                        errors += "Error in texture: " + textureName + string.Format("_0x{0:X8}", f.crc) + " This texture has wrong aspect ratio, skipping texture, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                        continue;
                                    }
                                }
                                mods.Add(mod);
                            }
                        }
                    }
                    catch
                    {
                        errors += "Mod is not compatible: " + file + Environment.NewLine;
                        continue;
                    }
                }
                else if (file.EndsWith(".tpf", StringComparison.OrdinalIgnoreCase))
                {
                    IntPtr handle = IntPtr.Zero;
                    try
                    {
                        byte[] buffer = File.ReadAllBytes(file);
                        handle = ZlibHelper.Zip.Open(buffer, ref numEntries, 1);
                        if (ZlibHelper.Zip.LocateFile(handle, "texmod.def") != 0)
                        {
                            throw new Exception();
                        }
                        result = ZlibHelper.Zip.GetCurrentFileInfo(handle, ref fileName, ref dstLen);
                        if (result != 0)
                        {
                            throw new Exception();
                        }
                        byte[] listText = new byte[dstLen];
                        result = ZlibHelper.Zip.ReadCurrentFile(handle, listText, dstLen);
                        if (result != 0)
                        {
                            throw new Exception();
                        }
                        ddsList = Encoding.ASCII.GetString(listText).Trim('\0').Replace("\r", "").TrimEnd('\n').Split('\n');

                        result = ZlibHelper.Zip.GoToFirstFile(handle);
                        if (result != 0)
                        {
                            throw new Exception();
                        }

                        for (uint i = 0; i < numEntries; i++)
                        {
                            TexExplorer.BinaryMod mod = new TexExplorer.BinaryMod();
                            try
                            {
                                uint crc = 0;
                                result = ZlibHelper.Zip.GetCurrentFileInfo(handle, ref fileName, ref dstLen);
                                if (result != 0)
                                {
                                    throw new Exception();
                                }
                                string filename = Path.GetFileName(fileName);
                                foreach (string dds in ddsList)
                                {
                                    string ddsFile = dds.Split('|')[1];
                                    if (ddsFile.ToLowerInvariant() != filename.ToLowerInvariant())
                                    {
                                        continue;
                                    }
                                    crc = uint.Parse(dds.Split('|')[0].Substring(2), System.Globalization.NumberStyles.HexNumber);
                                    break;
                                }
                                if (crc == 0)
                                {
                                    if (filename != "texmod.def")
                                    {
                                        errors += "Skipping file: " + filename + " not founded in texmod.def, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                    }
                                    ZlibHelper.Zip.GoToNextFile(handle);
                                    continue;
                                }

                                List <FoundTexture> foundCrcList = textures.FindAll(s => s.crc == crc);
                                if (foundCrcList.Count == 0)
                                {
                                    errors += "Texture skipped. File " + filename + string.Format(" - 0x{0:X8}", crc) + " is not present in your game setup - mod: " + file + Environment.NewLine;
                                    ZlibHelper.Zip.GoToNextFile(handle);
                                    continue;
                                }

                                string textureName = foundCrcList[0].name;
                                mod.textureName = textureName;
                                mod.binaryMod   = false;
                                mod.textureCrc  = crc;
                                mod.data        = new byte[dstLen];
                                result          = ZlibHelper.Zip.ReadCurrentFile(handle, mod.data, dstLen);
                                if (result != 0)
                                {
                                    errors += "Error in texture: " + textureName + string.Format("_0x{0:X8}", crc) + ", skipping texture, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                    ZlibHelper.Zip.GoToNextFile(handle);
                                    continue;
                                }
                                uint tag = BitConverter.ToUInt32(mod.data, 0);
                                if (tag != 0x20534444) // DDS
                                {
                                    errors += "Error in texture: " + textureName + string.Format("_0x{0:X8}", crc) + " This texture is not in DDS format, skipping texture, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                    ZlibHelper.Zip.GoToNextFile(handle);
                                    continue;
                                }
                                DDSImage image = new DDSImage(new MemoryStream(mod.data));
                                if (!image.checkExistAllMipmaps())
                                {
                                    errors += "Error in texture: " + textureName + string.Format("_0x{0:X8}", crc) + " This texture has not all the required mipmaps, skipping texture, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                    ZlibHelper.Zip.GoToNextFile(handle);
                                    continue;
                                }
                                Package pkg     = new Package(GameData.GamePath + foundCrcList[0].list[0].path);
                                Texture texture = new Texture(pkg, foundCrcList[0].list[0].exportID, pkg.getExportData(foundCrcList[0].list[0].exportID));

                                if (texture.mipMapsList.Count > 1 && image.mipMaps.Count() <= 1)
                                {
                                    errors += "Error in texture: " + textureName + string.Format("_0x{0:X8}", crc) + " This texture must have mipmaps, skipping texture, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                    ZlibHelper.Zip.GoToNextFile(handle);
                                    continue;
                                }

                                string    fmt       = texture.properties.getProperty("Format").valueName;
                                DDSFormat ddsFormat = DDSImage.convertFormat(fmt);
                                if (image.ddsFormat != ddsFormat)
                                {
                                    errors += "Error in texture: " + textureName + string.Format("_0x{0:X8}", crc) + " This texture has wrong texture format, should be: " + ddsFormat + ", skipping texture, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                    ZlibHelper.Zip.GoToNextFile(handle);
                                    continue;
                                }

                                if (image.mipMaps[0].origWidth / image.mipMaps[0].origHeight !=
                                    texture.mipMapsList[0].width / texture.mipMapsList[0].height)
                                {
                                    errors += "Error in texture: " + textureName + string.Format("_0x{0:X8}", crc) + " This texture has wrong aspect ratio, skipping texture, entry: " + (i + 1) + " - mod: " + file + Environment.NewLine;
                                    ZlibHelper.Zip.GoToNextFile(handle);
                                    continue;
                                }
                                mods.Add(mod);
                            }
                            catch
                            {
                                errors += "Skipping not compatible content, entry: " + (i + 1) + " file: " + fileName + " - mod: " + file + Environment.NewLine;
                            }
                            ZlibHelper.Zip.GoToNextFile(handle);
                        }
                        ZlibHelper.Zip.Close(handle);
                        handle = IntPtr.Zero;
                    }
                    catch
                    {
                        errors += "Mod is not compatible: " + file + Environment.NewLine;
                        if (handle != IntPtr.Zero)
                        {
                            ZlibHelper.Zip.Close(handle);
                        }
                        handle = IntPtr.Zero;
                        continue;
                    }
                }
                else if (file.EndsWith(".dds", StringComparison.OrdinalIgnoreCase))
                {
                    TexExplorer.BinaryMod mod = new TexExplorer.BinaryMod();
                    string filename           = Path.GetFileNameWithoutExtension(file).ToLowerInvariant();
                    if (!filename.Contains("0x"))
                    {
                        errors += "Texture filename not valid: " + Path.GetFileName(file) + " Texture filename must include texture CRC (0xhhhhhhhh). Skipping texture..." + Environment.NewLine;
                        continue;
                    }
                    int idx = filename.IndexOf("0x");
                    if (filename.Length - idx < 10)
                    {
                        errors += "Texture filename not valid: " + Path.GetFileName(file) + " Texture filename must include texture CRC (0xhhhhhhhh). Skipping texture..." + Environment.NewLine;
                        continue;
                    }
                    uint   crc;
                    string crcStr = filename.Substring(idx + 2, 8);
                    try
                    {
                        crc = uint.Parse(crcStr, System.Globalization.NumberStyles.HexNumber);
                    }
                    catch
                    {
                        errors += "Texture filename not valid: " + Path.GetFileName(file) + " Texture filename must include texture CRC (0xhhhhhhhh). Skipping texture..." + Environment.NewLine;
                        continue;
                    }

                    List <FoundTexture> foundCrcList = textures.FindAll(s => s.crc == crc);
                    if (foundCrcList.Count == 0)
                    {
                        errors += "Texture skipped. Texture " + Path.GetFileName(file) + " is not present in your game setup." + Environment.NewLine;
                        continue;
                    }

                    using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
                    {
                        mod.data = fs.ReadToBuffer((int)fs.Length);
                        DDSImage image = new DDSImage(new MemoryStream(mod.data));
                        if (!image.checkExistAllMipmaps())
                        {
                            errors += "Error in texture: " + Path.GetFileName(file) + " This texture has not all the required mipmaps, skipping texture..." + Environment.NewLine;
                            continue;
                        }

                        Package pkg     = new Package(GameData.GamePath + foundCrcList[0].list[0].path);
                        Texture texture = new Texture(pkg, foundCrcList[0].list[0].exportID, pkg.getExportData(foundCrcList[0].list[0].exportID));

                        if (texture.mipMapsList.Count > 1 && image.mipMaps.Count() <= 1)
                        {
                            errors += "Error in texture: " + Path.GetFileName(file) + " This texture must have mipmaps, skipping texture..." + Environment.NewLine;
                            continue;
                        }

                        string    fmt       = texture.properties.getProperty("Format").valueName;
                        DDSFormat ddsFormat = DDSImage.convertFormat(fmt);
                        if (image.ddsFormat != ddsFormat)
                        {
                            errors += "Error in texture: " + Path.GetFileName(file) + " This texture has wrong texture format, should be: " + ddsFormat + ", skipping texture..." + Environment.NewLine;
                            continue;
                        }

                        if (image.mipMaps[0].origWidth / image.mipMaps[0].origHeight !=
                            texture.mipMapsList[0].width / texture.mipMapsList[0].height)
                        {
                            errors += "Error in texture: " + Path.GetFileName(file) + " This texture has wrong aspect ratio, skipping texture..." + Environment.NewLine;
                            continue;
                        }

                        mod.textureName = foundCrcList[0].name;
                        mod.binaryMod   = false;
                        mod.textureCrc  = crc;
                        mods.Add(mod);
                    }
                }
            }

            if (mods.Count == 0)
            {
                Console.WriteLine("Mods conversion failed");
                return(errors);
            }

            Console.WriteLine("Saving to MEM file... " + memFilePath);
            List <MipMaps.FileMod> modFiles = new List <MipMaps.FileMod>();
            FileStream             outFs;

            if (File.Exists(memFilePath))
            {
                File.Delete(memFilePath);
            }

            using (outFs = new FileStream(memFilePath, FileMode.Create, FileAccess.Write))
            {
                outFs.WriteUInt32(TexExplorer.TextureModTag);
                outFs.WriteUInt32(TexExplorer.TextureModVersion);
                outFs.WriteInt64(0); // filled later

                for (int l = 0; l < mods.Count; l++)
                {
                    MipMaps.FileMod fileMod = new MipMaps.FileMod();
                    Stream          dst     = MipMaps.compressData(mods[l].data);
                    dst.SeekBegin();
                    fileMod.offset = outFs.Position;
                    fileMod.size   = dst.Length;

                    if (mods[l].binaryMod)
                    {
                        fileMod.tag  = MipMaps.FileBinaryTag;
                        fileMod.name = Path.GetFileNameWithoutExtension(mods[l].packagePath) + "_" + mods[l].exportId + ".bin";

                        outFs.WriteInt32(mods[l].exportId);
                        outFs.WriteStringASCIINull(mods[l].packagePath);
                    }
                    else
                    {
                        fileMod.tag  = MipMaps.FileTextureTag;
                        fileMod.name = mods[l].textureName + string.Format("_0x{0:X8}", mods[l].textureCrc) + ".dds";
                        outFs.WriteStringASCIINull(mods[l].textureName);
                        outFs.WriteUInt32(mods[l].textureCrc);
                    }
                    outFs.WriteFromStream(dst, dst.Length);
                    modFiles.Add(fileMod);
                }

                long pos = outFs.Position;
                outFs.SeekBegin();
                outFs.WriteUInt32(TexExplorer.TextureModTag);
                outFs.WriteUInt32(TexExplorer.TextureModVersion);
                outFs.WriteInt64(pos);
                outFs.JumpTo(pos);
                outFs.WriteUInt32((uint)GameData.gameType);
                outFs.WriteInt32(modFiles.Count);
                for (int i = 0; i < modFiles.Count; i++)
                {
                    outFs.WriteUInt32(modFiles[i].tag);
                    outFs.WriteStringASCIINull(modFiles[i].name);
                    outFs.WriteInt64(modFiles[i].offset);
                    outFs.WriteInt64(modFiles[i].size);
                }
            }

            Console.WriteLine("Mods conversion process completed");
            return(errors);
        }
        private void LoadDDSImage(MemoryStream ddsStream, bool bypassCheck = false)
        {
            using (BinaryReader r = new BinaryReader(ddsStream))
            {
                dwMagic = r.ReadInt32();
                if (dwMagic != 0x20534444)
                {
                    throw new Exception("This is not a DDS!");
                }

                Read_DDS_HEADER(header, r);

                if (((header.ddspf.dwFlags & DDPF_FOURCC) != 0) && (header.ddspf.dwFourCC == FOURCC_DX10 /*DX10*/))
                {
                    throw new Exception("DX10 not supported yet!");
                }

                int mipMapCount = 1;
                if ((header.dwFlags & DDSD_MIPMAPCOUNT) != 0)
                {
                    mipMapCount = header.dwMipMapCount;
                }
                if (mipMapCount == 0)
                {
                    mipMapCount = 1;
                }

                mipMaps = new List <MipMap>();

                ddsFormat = getFormat();

                double bytePerPixel = getBytesPerPixel(ddsFormat);

                for (int i = 0; i < mipMapCount; i++)
                {
                    int w = (int)(header.dwWidth / Math.Pow(2, i));
                    int h = (int)(header.dwHeight / Math.Pow(2, i));

                    int origW = w;
                    int origH = h;
                    if (origW == 0 && origH != 0)
                    {
                        origW = 1;
                    }
                    if (origH == 0 && origW != 0)
                    {
                        origH = 1;
                    }
                    w = origW;
                    h = origH;
                    if (ddsFormat == DDSFormat.DXT1 || ddsFormat == DDSFormat.DXT3 || ddsFormat == DDSFormat.DXT5)
                    {
                        w = (w < 4) ? 4 : w;
                        h = (h < 4) ? 4 : h;
                    }
                    int    mipMapBytes = (int)(w * h * bytePerPixel);
                    byte[] data        = r.ReadBytes(mipMapBytes);
                    mipMaps.Add(new MipMap(data, ddsFormat, origW, origH));
                }
            }
        }
Beispiel #35
0
        public static void RunNVCompress(Bitmap bitmap, AssetBundle bundle, string path, AssetAttributes attributes, DDSFormat format, bool mipMaps, byte[] CookingRulesSHA1, DateTime time)
        {
            bool   compressed = format == DDSFormat.DXTi;
            Bitmap bledBitmap = null;

            if (bitmap.HasAlpha)
            {
                bledBitmap = TextureConverterUtils.BleedAlpha(bitmap);
            }
            string mipsFlag = mipMaps ? string.Empty : "-nomips";
            string compressionMethod;

            if (compressed)
            {
                compressionMethod = bitmap.HasAlpha ? "-bc3" : "-bc1";
            }
            else
            {
#if WIN
                compressionMethod = "-rgb";
#else
                compressionMethod = "-rgb -rgbfmt bgra8";
#endif
            }
            var nvcompress = GetToolPath("nvcompress");

            string args       = "{0} {1}".Format(mipsFlag, compressionMethod);
            var    hashString = GetTextureHashString(bledBitmap ?? bitmap, ".dds", args);
            var    cachePath  = AssetCache.Instance.Load(hashString);
            if (cachePath != null)
            {
                bundle.ImportFile(cachePath, path, 0, "", attributes, time, CookingRulesSHA1);
                return;
            }
            var ddsPath = Toolbox.GetTempFilePathWithExtension(".dds");
            var tgaPath = Path.ChangeExtension(ddsPath, ".tga");
            var srcPath = Path.Combine(Directory.GetCurrentDirectory(), tgaPath);
            var dstPath = Path.Combine(Directory.GetCurrentDirectory(), ddsPath);
            try {
                TextureConverterUtils.SaveToTGA(bledBitmap ?? bitmap, tgaPath, swapRedAndBlue: compressed);
                if (bledBitmap != null && bledBitmap != bitmap)
                {
                    bledBitmap.Dispose();
                }
                args += $" \"{srcPath}\" \"{dstPath}\"";
                if (Process.Start(nvcompress, args.Format(mipsFlag, compressionMethod, srcPath, dstPath), options: Process.Options.RedirectErrors) != 0)
                {
                    throw new Lime.Exception($"NVCompress error\nCommand line: {nvcompress} {args}\"");
                }
                bundle.ImportFile(ddsPath, path, 0, "", attributes, time, CookingRulesSHA1);
                AssetCache.Instance.Save(ddsPath, hashString);
            } finally {
                DeletePossibleLockedFile(ddsPath);
                DeletePossibleLockedFile(tgaPath);
            }
        }
Beispiel #36
0
        public DDSImage(string ddsFileName)
        {
            using (FileStream ddsStream = File.OpenRead(ddsFileName))
            {
                using (BinaryReader r = new BinaryReader(ddsStream))
                {
                    dwMagic = r.ReadInt32();
                    if (dwMagic != 0x20534444)
                    {
                        throw new Exception("This is not a DDS!");
                    }

                    Read_DDS_HEADER(header, r);

                    if (((header.ddspf.dwFlags & DDPF_FOURCC) != 0) && (header.ddspf.dwFourCC == FOURCC_DX10 /*DX10*/))
                    {
                        throw new Exception("DX10 not supported yet!");
                    }

                    int mipMapCount = 1;
                    if ((header.dwFlags & DDSD_MIPMAPCOUNT) != 0)
                        mipMapCount = header.dwMipMapCount;

                    mipMaps = new MipMap[mipMapCount];

                    ddsFormat = getFormat();

                    double bytePerPixel = getBytesPerPixel(ddsFormat);

                    for (int i = 0; i < mipMapCount; i++)
                    {
                        int w = (int)(header.dwWidth / Math.Pow(2, i));
                        int h = (int)(header.dwHeight / Math.Pow(2, i));

                        if (ddsFormat == DDSFormat.DXT1 || ddsFormat == DDSFormat.DXT5)
                        {
                            w = (w < 4) ? 4 : w;
                            h = (h < 4) ? 4 : h;
                        }

                        int mipMapBytes = (int)(w * h * bytePerPixel);
                        mipMaps[i] = new MipMap(r.ReadBytes(mipMapBytes), ddsFormat, w, h);
                    }
                }
            }
        }