WPF загружает сериализованное изображение - PullRequest
3 голосов
/ 16 сентября 2010

В приложении мне нужно сериализовать изображение с помощью бинарной записи и получить его в другом приложении для его отображения.

Вот часть моего кода "сериализации":

FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write);
BinaryWriter bin = new BinaryWriter(fs);                         

bin.Write((short)this.Animations.Count);

for (int i = 0; i < this.Animations.Count; i++)
{
    MemoryStream stream = new MemoryStream();
    BitmapEncoder encoder = new PngBitmapEncoder();

    encoder.Frames.Add(BitmapFrame.Create(Animations[i].Image));
    encoder.Save(stream);

    stream.Seek(0, SeekOrigin.Begin);

    bin.Write((int)stream.GetBuffer().Length);
    bin.Write(stream.GetBuffer());

    stream.Close();
}

bin.Close();

И вот часть моей десериализации, которая загружает изображение:

FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
BinaryReader bin = new BinaryReader(fs);

int animCount = bin.ReadInt16();
int imageBytesLenght;
byte[] imageBytes;
BitmapSource img;

for (int i = 0; i < animCount; i++)
{    
    imageBytesLenght = bin.ReadInt32();
    imageBytes = bin.ReadBytes(imageBytesLenght);
    img = new BitmapImage();
    MemoryStream stream = new MemoryStream(imageBytes);
    BitmapDecoder dec = new PngBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
    img = dec.Frames[0];
    stream.Close();
}

bin.Close();

Когда я использую этот метод, я загружаю изображение (кажется, что оно хранится в объекте "img"), но оно не может быть отображено.

Есть идеи?

Спасибо

Kite

UPD :

Я уже делаю это: обновляю свою привязку или даже пытаюсь повлиять на нее напрямую через кодирование окна. Ни один из этих подходов не работает: s

Однако, когда я добавлю это:

private void CreateFile(byte[] bytes)
{
    FileStream fs = new FileStream(Environment.CurrentDirectory + "/" + "testeuh.png", FileMode.Create, FileAccess.Write);
    fs.Write(bytes, 0, bytes.Length);     
    fs.Close();
}

в конце вашей функции он отлично создает файл, который можно прочитать без проблем ... Так что я не знаю, где может быть проблема.

UPD 2 :

Странные вещи случаются.

Вот привязка, которую я использую:

<Image x:Name="imgSelectedAnim" Width="150" Height="150" Source="{Binding ElementName=lstAnims, Path=SelectedItem.Image}" Stretch="Uniform" />

(сам список привязан к коллекции observableCollection).

Когда я вручную создаю анимацию через приложение, она работает (изображение отображается).

Но когда я загружаю его, он не отображается (я смотрю на мой код, нет никаких «новых», которые могли бы сломать мою привязку, поскольку есть другие свойства, связанные так же, и они не перестают работать).

Кроме того, я установил точку останова в функции получения / установки свойств изображения моей анимации.

Когда он создан, нет проблем, у него хорошая информация.

Но когда он получен через геттер, он возвращает хорошее изображение в первый раз, а затем и изображение с pixelWidth, pixelHeight, width, height только 1, но без прохождения через сеттер!

Есть идеи?

UPD3

попробовал то, что вы сказали, как это:

Добавлено свойство TEST в моей viewModel:

  private BitmapSource test;
        public BitmapSource TEST { get { return test; } set { test = value; RaisePropertyChanged("TEST"); } }

затем сделал это:

img = getBmpSrcFromBytes(bin.ReadBytes(imageBytesLenght));
TEST = img;

(в коде, показанном и измененном ранее)

и мой переплет:

 <Image x:Name="imgSelectedAnim" Width="150" Height="150" Source="{Binding Path=TEST}" Stretch="Uniform" />

(для datacontext установлено значение моей ViewModel)

И он все еще не работает и выполняет странную модификацию изображения (pixW, pixH, W и H установлены в 1)

ФИНАЛЬНОЕ UPD:

Кажется, я наконец-то решил проблему. Вот что я сделал:

byte[] bytes = bin.ReadBytes(imageBytesLenght);
MemoryStream mem = new MemoryStream(bytes);

img = new BitmapImage();
img.BeginInit();
img.StreamSource = mem;
img.EndInit();

странно то, что это не сработало в первый раз, возможно, это связано с архитектурной модификацией в моем классе спрайтанимации, но я не думаю, что это так.

Что ж, большое спасибо Евгению Чеверде за помощь

1 Ответ

0 голосов
/ 16 сентября 2010

Во-первых, я думаю, что вы должны хранить ваши изображения в списке BitmapSource и обеспечить обратное кодирование изображения для использования stream как BitmapImage.StreamSource:

FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
        BinaryReader bin = new BinaryReader(fs);

        int animCount = bin.ReadInt16();
        int imageBytesLenght;
        byte[] imageBytes;
        List<BitmapSource> bitmaps = new List<BitmapSource>();

        for (int i = 0; i < animCount; i++)
        {
            imageBytesLenght = bin.ReadInt32();
            imageBytes = bin.ReadBytes(imageBytesLenght);
            bitmaps.Add(getBmpSrcFromBytes(imageBytes));
        }

        bin.Close();

UPD В приведенном выше коде используйте func, написанное ниже:

private BitmapSource getBmpSrcFromBytes(byte[] bytes)
        {
            using (var srcStream = new MemoryStream(bytes))
            {
                var dec = new PngBitmapDecoder(srcStream, BitmapCreateOptions.PreservePixelFormat,
                                                             BitmapCacheOption.Default);

                var encoder = new PngBitmapEncoder();
                encoder.Frames.Add(dec.Frames[0]);
                BitmapImage bitmapImage = null;
                bool isCreated;
                try
                {
                    using (var ms = new MemoryStream())
                    {
                        encoder.Save(ms);
                        bitmapImage = new BitmapImage();
                        bitmapImage.BeginInit();
                        bitmapImage.StreamSource = ms;
                        bitmapImage.EndInit();
                        isCreated = true;
                    }
                }
                catch
                {
                    isCreated = false;
                }
                return isCreated ? bitmapImage : null;
            }
        }

Надеюсь, это поможет.

UPD # 2

Ваша привязка неверна. Вы можете привязать выбранный элемент, например, к CurrentImageSource. И затем этот CurrentImageSource связывается с Image control.

Код:

public class MyViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<BitmapSource> ImagesCollection { get; set; }
        private BitmapSource _currentImage;

        public BitmapSource CurrentImage
        {
            get { return _currentImage; }
            set
            {
                _currentImage = value;
                raiseOnPropertyChanged("CurrentImage");
            }
        }

        private void raiseOnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }        

        public event PropertyChangedEventHandler PropertyChanged;
    }

Тогда:

<ListBox ItemsSource="{Binding ImagesCollection}" SelectedItem="{Binding CurrentImage}"/>
<Image Source="{Binding CurrentImage}"/>

ДОБАВЛЕНО

Вот пример проекта, в котором реализована техника, как я описал выше. Он создает коллекцию анимаций и представляет их в списке, выбранная анимация отображается в элементе управления Image с использованием свойства Image.

Что я хочу сказать, так это то, что если вы не можете получить изображение в должном порядке, вам нужно искать проблемы в сериализации / десериализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...