DOBON.NETプログラミング道掲示板
(現在 過去ログ5 を表示中)

[ 最新記事及び返信フォームをトピックトップへ ]

■35118 / inTopicNo.1)  bitmapを複数スレッドで処理したい
  
□投稿者/ Trans 一般人(1回)-(2022/07/31(Sun) 11:43:32)
  • アイコン環境/言語:[Windows10、C#] 
    分類:[.NET] 

    並列処理に挑戦したく思い、1枚の画像を複数スレッドで加工するテストコードを書きました。
    {
        // 画像をメモリに読み込む
        FileStream fs = File.OpenRead(filename);
        Image img = Image.FromStream(fs, false, false);
        Bitmap bitmap = new Bitmap(img);
    
        //読み込んだ画像を表示する
        PictureBox.Image = bitmap;
        PictureBox.Refresh();
    
        // 縦横サイズを取得
        int w = img.Width;
        int h = img.Height;
    
        Parallel.Invoke(
            () => TransformPixel(bitmap, 0, 1000, w),
            () => TransformPixel(bitmap, 1000, h, w)
        );
    
        //作成した画像を表示する
        PictureBox.Image = bitmap;
    }
    private void TransformPixel(Bitmap bitmap, int start, int end, int w)
    {
        Color pixel;
        for (int y = start; y < end; y++)
        {
            for (int x = 0; x < w; x++)
            {
                // ピクセル加工
                pixel = PixelTrans(bitmap.GetPixel(x, y));
    
                bitmap.SetPixel(x, y, pixel);
            }
        }
    
    }
    
    ファイルから読み込んだ画像の頭1000ラインまでをスレッド1、残りをスレッド2で加工するような感じです。
    実行してみたところ、
    Parallel.Invoke(の行で、
    
    System.InvalidOperationException
      HResult=0x80131509
      Message=Object is currently in use elsewhere.
      Source=System.Drawing.Common
      スタック トレース:
       at System.Drawing.Bitmap.GetPixel(Int32 x, Int32 y)
    
    のようなエラーとなってしまいます。
    同じbitmapに複数スレッドからの操作は出来ないんじゃないか?という気はするのですが、何をどうすればいいのかがわかりません。
    ご教授をお願いいたします。
    

引用返信 削除キー/
■35119 / inTopicNo.2)  Re[1]: bitmapを複数スレッドで処理したい
□投稿者/ Azulean 大御所(531回)-(2022/07/31(Sun) 17:46:52)
  • アイコンNo35118に返信(Transさんの記事)
    > 同じbitmapに複数スレッドからの操作は出来ないんじゃないか?という気はするのですが、何をどうすればいいのかがわかりません。

    そうですね、1 つの Bitmap を複数のスレッドから触ることはできません。

    LockBits を使ってメモリに展開したものを複数のスレッドで同時に加工することはできるかもしれません。
    https://dobon.net/vb/dotnet/graphics/drawnegativeimage.html#lockbits
引用返信 削除キー/
■35120 / inTopicNo.3)  Re[2]: bitmapを複数スレッドで処理したい
□投稿者/ Trans 一般人(2回)-(2022/07/31(Sun) 20:55:29)
  • アイコン
    2022/07/31(Sun) 20:55:54 編集(投稿者)
    
    ■No35119に返信(Azuleanさんの記事)
    > ■No35118に返信(Transさんの記事)
    >>同じbitmapに複数スレッドからの操作は出来ないんじゃないか?という気はするのですが、何をどうすればいいのかがわかりません。
    > 
    > そうですね、1 つの Bitmap を複数のスレッドから触ることはできません。
    > 
    > LockBits を使ってメモリに展開したものを複数のスレッドで同時に加工することはできるかもしれません。
    > https://dobon.net/vb/dotnet/graphics/drawnegativeimage.html#lockbits
    
    なるほど。一旦メモリ展開ですか。
    案内の内容を参考に以下のように直してみたら動いたようです。
    ありがとうございました。
    {
        // 画像をメモリに読み込む
        FileStream fs = File.OpenRead(filename);
        Image img = Image.FromStream(fs, false, false);
        Bitmap bitmap = new Bitmap(img);
    
        //読み込んだ画像を表示する
        PictureBox.Image = bitmap;
        PictureBox.Refresh();
    
        // 縦横サイズを取得
        int w = img.Width;
        int h = img.Height;
    
        // Bitmapをロックする
        Rectangle rect = new Rectangle(0, 0, w, h);
        BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    
        // ピクセルデータをバイト型配列で取得する
        IntPtr ptr = bmpData.Scan0;
        string[] array = new string[3];
        byte[] pixels = new byte[bmpData.Stride * img.Height - 1];
        System.Runtime.InteropServices.Marshal.Copy(ptr, pixels, 0, pixels.Length);
    
        Parallel.Invoke(
            () => TransformPixel(pixels, 0, 99999),
            () => TransformPixel(pixels, 100000, pixels.Length)
        );
    
        // ピクセルデータを元に戻す
        System.Runtime.InteropServices.Marshal.Copy(pixels, 0, ptr, pixels.Length);
    
        // ロックを解除する
        bitmap.UnlockBits(bmpData);
    
        //作成した画像を表示する
        PictureBox.Image = bitmap;
    
    }
    
    private void TransformPixel(byte[] pixels, int start, int end)
    {
        for (int i = start; i < end; i++)
        {
            pixels[i] = (byte)~pixels[i];
        }
    
    }
    

解決み!
引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

Mode/  Pass/


- Child Tree -