gpt4 book ai didi

WPF 加载序列化图像

转载 作者:行者123 更新时间:2023-12-02 05:13:04 24 4
gpt4 key购买 nike

在一个应用程序中,我需要通过二进制编写器序列化图像,并在另一个应用程序中获取它以显示它。

这是我的“序列化”代码的一部分:

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”对象中)但是无法显示。

有什么想法吗?

谢谢

风筝

更新:

我已经这样做了:更新我的绑定(bind),或者甚至试图通过窗口代码 behing 直接影响它。这些方法都不起作用: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:

奇怪的事情发生了。

这是我使用的绑定(bind):

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

(列表本身绑定(bind)在一个 observableCollection 上)。

当我通过应用程序手动创建动画时,它可以工作(显示图像)。

但是当我加载它时,它没有显示(我查看了我的代码,没有任何可以破坏我的绑定(bind)的"new",因为还有其他属性以相同的方式绑定(bind)并且它们不会失败)。

此外,我在动画的属性图像的 getter/setter 上放置了一个断点。

当它创建时,没有问题,它有很好的信息。

但是当通过getter获取的时候,第一次返回的是一张好的图片,然后和pixelWidth,pixelHeight,width,height只有1的图片,不再通过setter了!

有什么想法吗?

UPD3

试过你说的是这样的:

在我的 viewModel 中添加了一个属性 TEST:

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

然后做了:

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

(在之前展示和修改过的代码中)

和我的绑定(bind):

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

(数据上下文设置为我的 ViewModel)

它仍然不起作用,并且进行了奇怪的图像修改(pixW、pixH、W 和 H 设置为 1)

最终更新:

看来我终于解决了这个问题。这就是我所做的:

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

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

奇怪的是它第一次没有工作,可能是由于我的 spriteanimation 类中的架构修改,但我认为不是。

好吧,非常感谢 Eugene Cheverda 的帮助

最佳答案

首先,我认为您应该将图像存储在 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在上面的代码中使用下面写的函数:

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

您的绑定(bind)不正确。您可能应该将所选项目绑定(bind)到例如 CurrentImageSource。然后这个 CurrentImageSource 绑定(bind)到 Image 控件。

代码:

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}"/>

已添加

Here is the sample project in which implemented technique as I described above.它创建动画集合并在列表框中表示它们,选定的动画使用其 Image 属性显示在 Image 控件中。

我想说的是,如果不能正常获取图片,就需要在序列化/反序列化中查找问题。

关于WPF 加载序列化图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3724843/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com