TiffBitmapEncoder:使位图编码异步
本文关键字:编码 异步 位图 TiffBitmapEncoder | 更新日期: 2023-09-27 18:31:10
问题:如何相对于主线程异步保存/压缩位图图像(其中几个堆叠在tiff
文件中)?
我的设置:(同步和慢速工作解决方案:执行压缩时,线程会卡住几秒钟。我负担不起。
...in the body of a window class
private void afunction(){
//called with a given frequency and updating this.colorBitmap
...
this.colorBitmap = something;
savePictureStackTiff();
}
private int stack_pict_count = 0;
private int PICT_PER_FILE = 45;
private TiffBitmapEncoder encoder;
private string savePictureStackTiff()
{
initializeTiffEncoder();
//make a local copy of the image I want to put in the tiff binder
WriteableBitmap localCopy = new WriteableBitmap(this.colorBitmap);
encoder.Frames.Add(BitmapFrame.Create(localCopy));
stack_pict_count++;
if (stack_pict_count % PICT_PER_FILE == 0)
//Once I have enough files stacked I ask for compression
{
stack_pict_count = 0;
pict_metadata = "";
try
{
using (FileStream fs = new FileStream(path, FileMode.Create))
{
encoder.Save(fs); //<<<== LINE WHICH I'D LIKE TO BE RUN ASYNC
}
}
catch (IOException)
{}
}
}
private void initializeTiffEncoder()
{
if (stack_pict_count == 0)
{
encoder = new TiffBitmapEncoder();
encoder.Compression = TiffCompressOption.Zip;
}
}
我一直在尝试的:我希望压缩(调用encoder.save(fs)
)在主线程以外的另一个线程中执行。
我试图将调用encoder.save(fs)
放在一个BackgroundWorker
中,该预防性地将编码器复制到本地版本(不确定它是否有效),然后进行调用。我收到类似"调用线程无法访问此对象,因为其他线程拥有它"之类的错误。
如果我使用Dispatcher.Invoke
(前提是我做得正确),执行再次变得非常慢。
我犯了什么愚蠢的错误吗?
编辑:(根据@meilke和@user7116的建议进行中的工作)
我现在在BackgroundWorker
中移动了压缩机的分配和执行.虽然现在colorBitmap
传递,但拥有另一个线程。我试图freeze
它,但它看起来还不够;我仍然收到"调用线程无法访问此对象,因为其他线程拥有它"。
tiffCompressorWorker = new BackgroundWorker();
tiffCompressorWorker.DoWork += (s, a) =>
{
initializeTiffEncoder();
WriteableBitmap localCopy = new WriteableBitmap((WriteableBitmap)a.Argument);
localCopy.Freeze();
encoder.Frames.Add(BitmapFrame.Create(localCopy));
stack_pict_count++;
if (stack_pict_count % PICT_PER_FILE == 0)
{
stack_pict_count = 0;
try
{
using (FileStream fs = new FileStream(path, FileMode.Create))
{
saving_encoder.Save(fs);
}
}
catch (IOException)
{
..
}
}
};
您必须将整个 TIFF 操作放入后台工作线程中。然后将输入图像的副本作为参数传递给RunWorkerAsync
.以下是网络上提供的有关如何执行此操作的众多解决方案之一的链接:从BitmapSource复制到WritableBitmap。将该代码放入帮助程序方法中,并在将图像保存到磁盘之前使用它来复制图像。
我不是计算机科学家,但我找到了这篇文章,其中指出:
WriteableBitmap 继承 DispatcherObject,并且只能在拥有它的调度程序线程中访问。
而且,在我看来,您正在超出调度程序对象的权限。