C#: сохранить несколько изображений в один файл

Я работаю над классом, который поддерживает словарь изображений. Этот словарь должен быть сохранен и загружен из файла.

Я реализовал приведенное ниже решение, но проблема в том, что согласно документации MSDN для Image.FromStream ();
http://msdn.microsoft.com/en-us/library/93z9ee4x(v=VS.80).aspx

"Поток сбрасывается в ноль, если этот метод вызывается последовательно с одним и тем же потоком".

Любые идеи, как это исправить? Скорость загрузки словаря критична.

class ImageDictionary
{
    private Dictionary<string, Image> dict = new Dictionary<string, Image>();

    public void AddImage(string resourceName, string filename)
    {
       //...
    }

    public Image GetImage(string resourceName) 
    {
       //...
    }


    public void Save(string filename)
    {
        var stream = new FileStream(filename, FileMode.Create);
        var writer = new BinaryWriter(stream);
        writer.Write((Int32) dict.Count);
        foreach (string key in dict.Keys)
        {
            writer.Write(key);

            Image img;
            dict.TryGetValue(key, out img);
            img.Save(stream,System.Drawing.Imaging.ImageFormat.Png);
        }
        writer.Close();
        stream.Close();
    }

    public void Load(string filename)
    {
        var stream = new FileStream(filename, FileMode.Open);
        var reader = new BinaryReader(stream);
        Int32 count = reader.ReadInt32();
        dict.Clear();

        for (int i = 0; i < count; i++)
        {
            string key = reader.ReadString();
            Image img = Image.FromStream(stream);
            dict.Add(key, img);

        }

        reader.Close();
        stream.Close();

    }



}

4 ответа

Решение

Image.FromStream Метод ожидает действительный поток изображений. Вы объединяете несколько изображений в один файл, и если вы хотите восстановить их, вам также необходимо сохранить их размер в дополнение к их количеству. Более простым решением будет просто двоичная сериализация словаря изображений:

public void Save(string filename)
{
    var serializer = new BinaryFormatter();
    using (var stream = File.Create(filename))
    {
        serializer.Serialize(stream, dict);
    }
}

public void Load(string filename)
{
    var serializer = new BinaryFormatter();
    using (var stream = File.Open(filename, FileMode.Open))
    {
        dict = (Dictionary<string, Image>)serializer.Deserialize(stream);
    }
}

Вы можете попробовать использовать BinaryFormatter для сериализации / десериализации вашего словаря. dict в / из файла.

Почему бы не создать пользовательский заголовок для этого файла, который включает в себя (количество изображений, начальный адрес реальных изображений и сделать между каждым изображением разделитель строк)

Идея вне стен, которая может работать (я определенно не проверял это):

  • Создать Substream класс, который происходит от Stream а также оборачивает основную Stream, Его конструктор будет принимать Stream и offset в этот поток, что Substream трактует как ноль. Substream это в основном ограниченное представление или окно в другой поток (в данном случае, ваш файловый поток).
  • Изначально создайте Substream над вашим FileStream с offset нуля.
  • Когда вы звоните Image.FromStream, положение вашего Substream будет продвигаться к какой-то новой позиции (позвоните p).
  • Создать новый Substream над вашим FileStream с offset из p,
  • Цикл до конца.

Идея в том, что даже если Image.FromStream сбрасывает основной поток, он сбрасывает Substream в некотором смещении в FileStream, что вы действительно хотите.

Другие вопросы по тегам