C#,从二进制文件中写入和读取图像

时间:2014-10-19 02:36:39

标签: c# image-processing binaryfiles

我正在学习C#,并在BinaryReader / Writer上进行堆栈。我如何在这个原因中读/写文件: 我需要将这些数据存储到二进制文件中。 (精灵班)

public class Sprite
{
    public Int32 id; //spriteID
    public Int32 size; //sprite byte size
    public byte[] dump; //sprite image byte-array
    public Sprite()
    {
        id = 0;
        size = 0;
        dump = null;
    }
}

我通过这个函数得到精灵数据:

    public Sprite createSprite(Image image, System.Drawing.Imaging.ImageFormat format)
    {
      using (MemoryStream ms = new MemoryStream())
       {
         Sprite tmpSpr = new Sprite();
         image.Save(ms, format);
         tmpSpr.dump = ms.ToArray();
         tmpSpr.size = tmpSpr.Length;
         tmpSpr.id = 1; //just for example
         return tmpSpr;
       }
   }

但我正在堆叠解决这个问题:

   public static bool save(string filename)
    {
      FileStream fileStream = new FileStream(filename, FileMode.Create);
      MemoryStream ms = new MemoryStream();
      BinaryWriter wr = new BinaryWriter(ms);
      //How i am should write a sprites here?
    }

这里有未完成的读者功能。堆叠在阅读上。

public static bool load(string filename, ref Dictionary<UInt32, Sprite> sprites)
{
   FileStream fileStream = new FileStream(filename, FileMode.Open);
        try
        {
            using (BinaryReader reader = new BinaryReader(fileStream))
            {
                UInt32 totalSprites = reader.ReadUInt32(); //total sprites in file
                //something like that?
                List<UInt32> spriteIndexes = new List<UInt32>();
                for (uint i = 0; i < totalSprites; ++i)
                {
                    UInt32 index = reader.ReadUInt32();
                    spriteIndexes.Add(index);
                }
                UInt32 id = 1;
                foreach (UInt32 element in spriteIndexes)
                {
                    //i am not sure here =(
                    reader.BaseStream.Seek(element, SeekOrigin.Begin);
                    UInt32 size = reader.ReadUInt32();

                    Sprite sprite;
                    if (sprites.TryGetValue(id, out sprite))
                    {
                        if (sprite != null && size > 0)
                        {
                            if (sprite.size > 0)
                            {
                                //generate warning
                            }
                            else
                            {
                                sprite.id = id;
                                sprite.size = size;
                                sprite.dump = reader.ReadBytes(size);

                                sprites[id] = sprite;
                            }
                        }
                    }
                    else
                    {
                        //i am not shure here  too.
                        reader.BaseStream.Seek(size, SeekOrigin.Current);
                    }

                    ++id;
                }
            }
        }
        finally
        {
            fileStream.Close();
        }
        return true;
}

Sprite文件应该有一个totalSprites参数,以及所有精灵的列表,以及它们的id,size,dump。加载功能“似乎”几乎“完成”,但我不知道,如何为该“读者”写文件。请显示解决方案。谢谢你提前!

1 个答案:

答案 0 :(得分:2)

你的基本问题是你不知道精灵在文件中的位置,直到你写它(除非你通过数组并计算字节,这是可能的),但你想写索引在精灵之前。您有几个选择:

首先,为什么要有一个索引?如果你知道你有多少精灵,你可以写下这个数字,然后按顺序读取文件,一次一个精灵。这是最简单的:

using (var fs = File.OpenWrite(filename))
{
    using (var writer = new BinaryWriter(fs))
    {
        // write sprite count
        writer.Write(spriteList.Count);
        // and write each sprite
        foreach (var s in spriteList)
        {
            writer.Write(sprite.id);
            writer.Write(sprite.size);
            writer.Write(sprite.dump);
        }
    }
}

阅读正好相反:读取计数,然后读取那么多精灵。除非您希望能够读取第五个精灵,否则不需要索引,而无需先读取前四个精灵。

如果你真的需要索引,可以为它编写一个占位符,然后编写精灵,跟踪它们的位置,然后回到文件的开头并写下真实的索引。像这样:

var index = new List<long>(spriteList.Count);
using (var fs = File.OpenWrite(filename))
{
    using (var writer = new BinaryWriter(fs))
    {
        // write sprite count
        writer.Write(spriteList.Count);

        var indexPos = writer.BaseStream.Position;

        // write index placeholder
        for (var i = 0; i < spriteList.Count; ++i)
        {
            writer.Write(0L);
        }

        // and write each sprite
        for (var i = 0; i < spriteList.Count ++i)
        {
            // save current position
            writer.Flush();
            index[i] = writer.BaseStream.Position;

            writer.Write(sprite.id);
            writer.Write(sprite.size);
            writer.Write(sprite.dump);
        }

        // Seek back to the index position 
        writer.Flush();
        writer.BaseStream.Position = indexPos;

        // and write the real index
        foreach (var pos in index)
        {
            writer.Write(pos);
        }
    }
}

另一种方法是首先编写精灵,然后如上所述跟踪它们在索引数组中的位置,但在精灵后写入索引。然后,要读取,您从文件的开头读取精灵计数,将其乘以8(long的大小),并寻找文件的末尾减去那么多。那就是:

var spriteCount = reader.ReadInt32();
long indexSize = spriteCount * 8;
reader.BaseStream.Seek(-indexSize, SeekOrigin.End);
// now read the index of spriteCount values