在应用程序中,我需要通过二进制文件来序列化图像,并将其放入其他应用程序中以显示它。
以下是我的“序列化”代码的一部分:
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”对象中)但无法显示。
有想法吗?
由于
风筝
UPD :
我已经这样做了:更新我的绑定,甚至试图通过窗口代码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 :
发生了奇怪的事情。
这是我使用的绑定:
<Image x:Name="imgSelectedAnim" Width="150" Height="150" Source="{Binding ElementName=lstAnims, Path=SelectedItem.Image}" Stretch="Uniform" />
(列表本身绑定在observableCollection上)。
当我通过应用程序手动创建动画时,它可以正常工作(显示图像)。
但是当我加载它时,它没有显示(我查看我的代码,没有任何“新”可能会破坏我的绑定,因为有其他属性绑定相同的方式,它们不会失败)。
此外,我在动画的属性Image的getter / setter上设置了一个断点。
创建时没有任何问题,它有良好的信息。
但是当它通过吸气剂后退时,它会在第一次返回一个好的图像,然后和pixelWidth,pixelHeight,宽度,高度只有1的图像,但不再通过设置器了!
有什么想法吗?
UPD3
尝试了你这样说的话:
在我的viewModel中添加了属性TEST:
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)
最终更新:
似乎我终于解决了这个问题。这就是我所做的:
byte[] bytes = bin.ReadBytes(imageBytesLenght);
MemoryStream mem = new MemoryStream(bytes);
img = new BitmapImage();
img.BeginInit();
img.StreamSource = mem;
img.EndInit();
奇怪的是它第一次没有用,也许是因为我的spriteanimation类中的架构修改,但我认为不是。
嗯,非常感谢Eugene Cheverda的帮助
答案 0 :(得分:0)
首先,我认为您应该将图片存储在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
您的绑定不正确。您可能应该将所选项绑定到例如CurrentImageSource
。然后这个CurrentImageSource
绑定到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}"/>
<强> ADDED 强>
Here is the sample project in which implemented technique as I described above. 它创建动画集合并在列表框中表示它们,所选动画使用其Image属性显示在Image控件中。
我想说的是,如果您无法获得应有的图像,则需要在序列化/反序列化中搜索问题。