1

問題: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(正しく実行した場合)、実行が再び非常に遅くなります。

私は愚かな間違いを犯していますか?


EDIT:(@ 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)
                {
                    ..
                }
            }            
        };
4

2 に答える 2

2

TIFF 操作全体をバックグラウンド ワーカーに入れる必要があります。次に、入力画像のコピーを引数として に渡しますRunWorkerAsync。これを行う方法について、Web で利用可能な多くのソリューションの 1つへのリンクを次に示します。 BitmapSource から WritableBitmap へのコピー。そのコードをヘルパー メソッドに挿入し、それを使用してイメージをディスクに保存する前にコピーします。

于 2013-09-13T18:42:25.283 に答える