0

我的问题如下..

我有一个纹理文件,世界上任何纹理编辑器都无法打开它,该文件包含例如 100 个纹理。获取这些纹理的唯一方法是使用 Hex Editor(例如 Hex Workshop)打开文件并找到“GBIX”字符串。当您找到一个“GBIX”字符串时,您开始从那里复制直到另一个 GBIX 的开始,您创建一个新文件,将其粘贴到那里,将其保存为 PVR,然后您就有了纹理。但是,您需要这样做 100 次,因为该文件有 100 个“GBIX”字符串(100 个纹理)。好吧,现在,我有一些编程技巧,特别是在 C# 中,但我不知道如何创建一个从字符串复制到字符串然后将其保存在新文件中的程序。

4

4 回答 4

1

在 C 中,这将是微不足道的:

  1. 将文件加载到内存中
  2. 循环槽,strstr()用于寻找GBIX模式
  3. 对于每个找到的模式,查找下一个(或文件结尾)
  4. 对于每个找到的端,写出一个新的二进制文件之间的范围

我想在高级语言中它会更容易。:)

你的问题是什么?

于 2012-10-04T09:37:42.953 回答
1

你能用C编程吗?然后做以下事情

1.open the file using `fopen()` in binary mode.
2.use a loop upto the end of file and search for the string what you want (strstr() to look for the GBIX pattern)-copied from unwind 
3.Then after finding each pattern get the position of the file pointer using ftell() and store it to a array of 100 integer(as 100 of texture you have ).
4.Then go to the first byte of file by using fseek().
5.Now you can use your array to find the location and read the whole data up to the next array element (do it in a loop upto 100 times).
6.then store this data or write it to another file(open a file in append mode and write there).

我觉得有点棘手,但使用这个算法并从互联网上搜索代码你肯定能做到这一点。

于 2012-10-04T10:29:40.510 回答
0

我认为这个代码示例可能会对您有所帮助。它显示了如何为您解析文件。您需要做的就是创建一个新文件..

using System;
using System.IO;
using Extensions;
using System.Drawing;

/* Archive Module */
namespace puyo_tools
{
    public class Images
    {
        /* Image format */
        private ImageClass Converter = null;
        public GraphicFormat Format  = GraphicFormat.NULL;
        private Stream Data          = null;
        private Bitmap imageData     = null;
        public string ImageName      = null;
        private string FileExt       = null;

        /* Image Object for unpacking */
        public Images(Stream dataStream, string dataFilename)
        {
            /* Set up our image information */
            Data = dataStream;

            ImageInformation(ref Data, out Format, out Converter, out ImageName, out FileExt);
        }

        /* Unpack image */
        public Bitmap Unpack()
        {
            return Converter.Unpack(ref Data);
        }
        public Bitmap Unpack(Stream palette)
        {
            return Converter.Unpack(ref Data, palette);
        }

        /* Pack image */
        public Stream Pack()
        {
            return Converter.Pack(ref imageData);
        }

        /* Output Directory */
        public string OutputDirectory
        {
            get
            {
                return (ImageName == null ? null : ImageName + " Converted");
            }
        }

        /* File Extension */
        public string FileExtension
        {
            get
            {
                return (FileExt == null ? String.Empty : FileExt);
            }
        }

        /* Get image information */
        private void ImageInformation(ref Stream data, out GraphicFormat format, out ImageClass converter, out string name, out string ext)
        {
            try
            {
                /* Let's check for image formats based on the 12 byte headers first */
                switch (data.ReadString(0x0, 12, false))
                {
                    case GraphicHeader.GIM: // GIM (Big Endian)
                    case GraphicHeader.MIG: // GIM (Little Endian)
                        format    = GraphicFormat.GIM;
                        converter = new GIM();
                        name      = "GIM";
                        ext       = ".gim";
                        return;
                }

                /* Ok, do special checks now */

                /* PVR file */
                if ((data.ReadString(0x0, 4) == GraphicHeader.GBIX && data.ReadString(0x10, 4) == GraphicHeader.PVRT && data.ReadByte(0x19) < 64) ||
                    (data.ReadString(0x0, 4) == GraphicHeader.PVRT && data.ReadByte(0x9) < 64))
                {
                    format    = GraphicFormat.PVR;
                    //converter = new PVR();
                    converter = null;
                    name      = "PVR";
                    ext       = ".pvr";
                    return;
                }

                /* GVR File */
                if ((data.ReadString(0x0, 4) == GraphicHeader.GBIX && data.ReadString(0x10, 4) == GraphicHeader.GVRT) ||
                    (data.ReadString(0x0, 4) == GraphicHeader.GCIX && data.ReadString(0x10, 4) == GraphicHeader.GVRT) ||
                    (data.ReadString(0x0, 4) == GraphicHeader.GVRT))
                {
                    format    = GraphicFormat.GVR;
                    converter = new GVR();
                    name      = "GVR";
                    ext       = ".gvr";
                    return;
                }

                /* SVR File */
                if ((data.ReadString(0x0, 4) == GraphicHeader.GBIX && data.ReadString(0x10, 4) == GraphicHeader.PVRT && data.ReadByte(0x19) > 64) ||
                    (data.ReadString(0x0, 4) == GraphicHeader.PVRT && data.ReadByte(0x9) > 64))
                {
                    format    = GraphicFormat.SVR;
                    converter = new SVR();
                    name      = "SVR";
                    ext       = ".svr";
                    return;
                }

                /* GMP File */
                if (data.ReadString(0x0, 8, false) == "GMP-200\x00")
                {
                    format    = GraphicFormat.GMP;
                    converter = new GMP();
                    name      = "GMP";
                    ext       = ".gmp";
                    return;
                }

                /* Unknown or unsupported compression */
                throw new GraphicFormatNotSupported();
            }
            catch (GraphicFormatNotSupported)
            {
                /* Unknown or unsupported image format */
                format     = GraphicFormat.NULL;
                converter  = null;
                name       = null;
                ext        = null;
                return;
            }
            catch
            {
                /* An error occured. */
                format     = GraphicFormat.NULL;
                converter  = null;
                name       = null;
                ext        = null;
                return;
            }
        }

        /* Image Information */
        public class Information
        {
            public string Name = null;
            public string Ext = null;
            public string Filter = null;

            public bool Unpack = false;
            public bool Pack  = false;

            public Information(string name, bool unpack, bool pack, string ext, string filter)
            {
                Name   = name;
                Ext    = ext;
                Filter = filter;

                Unpack = unpack;
                Pack   = pack;
            }
        }
    }

    /* Image Format */
    public enum GraphicFormat : byte
    {
        NULL,
        GIM,
        GMP,
        GVR,
        PVR,
        SVR,
    }

    /* Image Header */
    public static class GraphicHeader
    {
        public const string
            GBIX = "GBIX",
            GCIX = "GCIX",
            GIM  = ".GIM1.00\x00PSP",
            GMP  = "GMP-200\x00",
            GVRT = "GVRT",
            MIG  = "MIG.00.1PSP\x00",
            PVRT = "PVRT";
    }

    public abstract class ImageClass
    {
        /* Image Functions */
        public abstract Bitmap Unpack(ref Stream data);   // Unpack image
        public abstract Stream Pack(ref Bitmap data);     // Pack Image
        public abstract bool Check(ref Stream data);      // Check Image
        public abstract Images.Information Information(); // Image Information
        public virtual Bitmap Unpack(ref Stream data, Stream palette) // Unpack image (with external palette file)
        {
            return null;
        }
    }
}
于 2012-10-04T09:42:08.657 回答
0

你说你用过C#。这应该让您大致了解如何在 C# 中执行此操作,尽管我自己没有测试过。

在开始之前,您的文件有多大?如果它可以完全放入内存,读取它的最简单方法是使用File.ReadAllBytes,它将整个文件读入一个很大的字节数组。(如果您的文件大小为千兆字节,您将无法一次全部加载。如果是这种情况,有更高级的方法来读取文件,但我暂时不会继续讨论这些方法。)

您可以使用File.ReadAllBytes读取文件,Array.IndexOf在其中搜索字节“G”,并使用普通数组索引来检查其他字母。当您找到它们时,您可以使用复制出数组的一部分Array.Copy并将其保存到使用File.WriteAllBytes.

您的问题对文件的格式并不完全清楚。根据你的描述,我认为是这样的:

HEADERBYTESblahblahblahGBIXcontentcontentcontentGBIXmorecontentGBIXyetmorecontent

并且您希望将其丢弃:

HEADERBYTESblahblahblah

以及要创建的三个单独的文件:

GBIXcontentcontentcontent
GBIXmorecontent
GBIXyetmorecontent

所以我假设在第一个“GBIX”之前可能有文本并且你想忽略它,并且从最后一个“GBIX”到文件末尾是你想要提取的正确纹理,没有任何内容在它之后。我还假设字符“GBIX”永远不会出现在其中一个纹理的中间 - 如果它们出现,那么您将需要使用能够真正理解文件格式的东西。

using System;
using System.IO;

public class Program
{
    public static void WriteFile(int aFileIndex, byte[] sourceBytes, int firstByteIndex, int byteCount)
    {
        string filename = String.Format("output{0}.pvr", aFileIndex);
        byte[] outputBytes = new byte[byteCount];
        Array.Copy(sourceBytes, firstByteIndex, outputBytes, 0, byteCount);
        File.WriteAllBytes(filename, outputBytes);
    }

    public static void Main()
    {
        byte[] fileBytes = File.ReadAllBytes("inputfile");
        int filesOutput = 0;
        int startIndex = -1;
        int currentIndex = 0;
        for (;;)
        {
            int nextIndex = Array.IndexOf(fileBytes, (byte)'G', currentIndex);
            if (nextIndex == -1)
            {
                // There are no more ASCII 'G's in the file.
                break;
            }
            if (nextIndex + 4 >= fileBytes.Length)
            {
                // There aren't enough characters left in the file for this
                // to be an ASCII "GBIX" string.
                break;
            }
            if (fileBytes[nextIndex+1] == (byte)'B' &&
                fileBytes[nextIndex+2] == (byte)'I' &&
                fileBytes[nextIndex+3] == (byte)'X')
            {
                // Found ASCII "GBIX" at nextIndex. Output the previous
                // complete file, if there is one.
                if (startIndex != -1)
                {
                    Write(filesOutput, fileBytes, startIndex, nextIndex - startIndex);
                }
                filesOutput += 1;
                startIndex = nextIndex;
            }
            currentIndex = nextIndex + 1;
        }
        if (startIndex != -1)
        {
            WriteFile(filesOutput, fileBytes, startIndex, fileBytes.Length - startIndex);
        }
    }
}
于 2012-10-04T15:03:09.630 回答