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

问题描述 投票:0回答:2

我正在学习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参数,以及所有sprite的列表及其ID,大小和转储。加载功能“似乎”几乎“完成”,但我不知道如何为该“阅读器”写入文件。请显示解决方案。感谢前进!

c# image-processing binaryfiles
2个回答
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);
        }
    }
}

[另一种选择是先编写精灵,并如上所述跟踪它们在索引数组中的位置,但要编写索引after精灵。然后,要读取该文件,请从文件的开头读取子画面计数,将其乘以8(long的大小),然后减至文件末尾减去该值。那是:

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

0
投票

我需要启用将图像文件转换为PDF文件的功能。每当用户保存任何格式的图像文件时,都应将其保存为PDF文件。

我已经使用二进制读取器和写入器读取图像并另存为pdf,但是PDF文件已损坏。

您能否协助我使用二进制阅读器读取图像文件,并使用二进制写入器将其另存为pdf文件,而又不会损坏文件?

© www.soinside.com 2019 - 2024. All rights reserved.