недопустимый обработчик в вызове BitmapEncoder.Frames.Add - PullRequest
0 голосов
/ 12 июня 2018

Я использую этот пользовательский метод для преобразования Bitmapsource в Bitmap:

    public Bitmap BitmapFromSource(BitmapSource bitmapsource) {
        using (MemoryStream outStream = new MemoryStream()) {
            BitmapEncoder enc = new BmpBitmapEncoder();
            enc.Frames.Add(BitmapFrame.Create(bitmapsource));
            enc.Save(outStream);
            using (var tempBitmap = new Bitmap(outStream)) {
                return new Bitmap(tempBitmap);
            } } }

этот метод вызывается несколько раз в моем коде, и он прекрасно работает.Но когда я вызываю его с помощью события щелчка мышью или события нажатия клавиши, я получаю, что обработчик содержит недопустимую ошибку.

Я понятия не имею, как поступить.Любое предложение?

В коде у меня есть список битовых фреймов:

List<BitmapFrame> myImages = new List<BitmapFrame>();

изначально метод работает, когда я показываю каждый кадр в несколько коробок с картинками:

var handler = new EventHandler(pictureBoxClick);

for (int i = 0; i < (decoder.Frames.Count); i++) {
   var picture = new MyPictureBox {
    Name = "pictureBoxFrame" + i,
    Width = (int)newWidth,
    Height = (int)newHeight,
    SizeMode = PictureBoxSizeMode.Zoom,
    Location= loc,
    Image = BitmapFromSource(myImages[i]), };
Controls[i].Click += handler;
splitContainer1.Panel1.Controls.Add(picture);
}

затем, когда я нажимаю одну из этих коробок с картинками:

void pictureBoxClick (object sender , EventArgs e) {
    var selectedPictureBox = (PictureBox)sender;
    int idx = Controls.IndexOf(selectedPictureBox);
    pictureBox1.Image = BitmapFromSource(myImages[idx]);
}

я получаю ошибку ...

1 Ответ

0 голосов
/ 12 июня 2018

Из того, что я вижу из вашего кода, вы, вероятно, являетесь жертвой "потока".
Это означает, что при загрузке ресурса из FileStream поток должен бытьдоступно (не утилизировано) для срока службы этого ресурса.
Это относится и к ресурсу изображения, на который ссылается BitmapDecoder .
Если вы утилизируете поток, использованный для инициализации BitmapDecoder,для его коллекции Frames будет задан 1 кадр размером 1x1.
Поскольку оставлять поток открытым не рекомендуется, его обычно копируют в MemoryStream (необработанный байтовый массив) и располагают сразу после.

Независимо от того, что вы, возможно, прочитали или услышали, MemoryStream на самом деле не нужно выбрасывать (не сразу, по крайней мере), потому что он на самом деле не используетжизненные ресурсы.

После загрузки ресурса изображения из потока BitmapDecoder можно инициализировать следующим образом:

MemoryStream memstream = new MemoryStream();
stream.CopyTo(memstream);
memstream.Position = 0;
BitmapDecoder bitmapDecoder = BitmapDecoder.Create(memstream,
                                            BitmapCreateOptions.PreservePixelFormat,
                                            BitmapCacheOption.Default);

Таким образом,BitmapFrames из BitmapDecoder будет иметь значениеидентификатор, потому что основной поток все еще жив.
Когда вы загружаете новое изображение, MemoryStream будет обновляться с использованием нового FileStream.

Для проверки результата чегоздесь и в комментариях (эти предложения тоже актуальны) я построил класс Test Form.
Вы можете скачать исходный код из PasteBin.

...