前提
プログラミング初心者です。
visual studio2019でParallel.Forを用いた画像の二値化処理プログラムを作成しました。
このプログラムで下記三点の処理時間を計測します。
・Parallel.Forのみを関数にした処理
・同一関数内で全て行う処理
・Parallel.Forを使わない処理
上手くプログラムが動作するのが確認出来ると後述の疑問点が生まれました。
疑問点
・Parallel.Forを関数にすると何故lockをしなくても処理できるのか
・関数void型で戻り値を使用してないのになぜbyte[] baimageの値は
変更されて正常に二値化されてる画像が表示されるのか
該当のソースコード
C#
1//関数を新規に作り、Parallel.Forを実施 2private void Button1_Click(object sender, EventArgs e) 3{ 4 var ofd = new OpenFileDialog(); 5 if (ofd.ShowDialog() != DialogResult.O 6 return; 7 8 var sw = new Stopwatch(); 9 sw.Start(); 10 11 Bitmap bmp = new Bitmap(ofd.FileName); 12 BitmapData bmpDate = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), 13 ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 14 byte[] baimage = new byte[bmp.Width * bmp.Height * 4]; 15 Marshal.Copy(bmpDate.Scan0, baimage, 0, baimage.Length); 16 17 parallel(bmp.Height, bmp.Width, baimage); 18 19 Marshal.Copy(baimage, 0, bmpDate.Scan0, baimage.Length); 20 bmp.UnlockBits(bmpDate); 21 sw.Stop(); 22 label1.Text = sw.ElapsedMilliseconds.ToString(); 23 24 pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; 25 pictureBox1.Image = bmp; 26} 27 28private void parallel(int bmp_height, int bmp_width, byte[] image) 29{ 30 Parallel.For(0, bmp_height, y => 31 { 32 for (int x = 0; x < bmp_width; x++) 33 { 34 var bytePos = y * bmp_width * 4 + x * 4; 35 int gray = (int)(0.299 * image[bytePos + 2] + 0.587 * image[bytePos + 1] + 0.114 * image[bytePos]); 36 37 if (gray > 127) 38 { 39 // 閾値を超えた場合、白 40 image[bytePos] = 0xFF; 41 image[bytePos + 1] = 0xFF; 42 image[bytePos + 2] = 0xFF; 43 } 44 else 45 { 46 // 閾値以下の場合、黒 47 image[bytePos] = 0x0; 48 image[bytePos + 1] = 0x0; 49 image[bytePos + 2] = 0x0; 50 } 51 } 52 }); 53} 54 55 56//同一関数内でParallel.Forを実施 57private void Button2_Click(object sender, EventArgs e) 58{ 59 var ofd = new OpenFileDialog(); 60 if (ofd.ShowDialog() != DialogResult.OK) 61 return; 62 63 var sw = new Stopwatch(); 64 sw.Start(); 65 66 Bitmap bmp = new Bitmap(ofd.FileName); 67 BitmapData bmpDate = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), 68 ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 69 byte[] baimage = new byte[bmp.Width * bmp.Height * 4]; 70 Marshal.Copy(bmpDate.Scan0, baimage, 0, baimage.Length); 71 72 Parallel.For(0, bmp.Height, y => 73 { 74 lock (this) for (int x = 0; x < bmp.Width; x++) 75 { 76 var bytePos = y * bmp.Width * 4 + x * 4; 77 int gray = (int)(0.299 * baimage[bytePos + 2] + 0.587 * baimage[bytePos + 1] + 0.114 * baimage[bytePos]); 78 79 if (gray > 127) 80 { 81 // 閾値を超えた場合、白 82 baimage[bytePos] = 0xFF; 83 baimage[bytePos + 1] = 0xFF; 84 baimage[bytePos + 2] = 0xFF; 85 } 86 else 87 { 88 // 閾値以下の場合、黒 89 baimage[bytePos] = 0x0; 90 baimage[bytePos + 1] = 0x0; 91 baimage[bytePos + 2] = 0x0; 92 } 93 } 94 }); 95 96 Marshal.Copy(baimage, 0, bmpDate.Scan0, baimage.Length); 97 bmp.UnlockBits(bmpDate); 98 sw.Stop(); 99 label2.Text = sw.ElapsedMilliseconds.ToString(); 100 101 pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; 102 pictureBox1.Image = bmp; 103} 104 105 106//すべてFor文 107private void Button3_Click(object sender, EventArgs e) 108{ 109 var ofd = new OpenFileDialog(); 110 if (ofd.ShowDialog() != DialogResult.OK) 111 return; 112 113 var sw = new Stopwatch(); 114 sw.Start(); 115 116 Bitmap bmp = new Bitmap(ofd.FileName); 117 BitmapData bmpDate = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), 118 ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 119 byte[] baimage = new byte[bmp.Width * bmp.Height * 4]; 120 Marshal.Copy(bmpDate.Scan0, baimage, 0, baimage.Length); 121 122 for (int y = 0; y < bmp.Height; y++) 123 { 124 for (int x = 0; x < bmp.Width; x++) 125 { 126 var bytePos = y * bmp.Width * 4 + x * 4; 127 int gray = (int)(0.299 * baimage[bytePos + 2] + 0.587 * baimage[bytePos + 1] + 0.114 * baimage[bytePos]); 128 129 if (gray > 127) 130 { 131 // 閾値を超えた場合、白 132 baimage[bytePos] = 0xFF; 133 baimage[bytePos + 1] = 0xFF; 134 baimage[bytePos + 2] = 0xFF; 135 } 136 else 137 { 138 // 閾値以下の場合、黒 139 baimage[bytePos] = 0x0; 140 baimage[bytePos + 1] = 0x0; 141 baimage[bytePos + 2] = 0x0; 142 } 143 } 144 } 145 146 Marshal.Copy(baimage, 0, bmpDate.Scan0, baimage.Length); 147 bmp.UnlockBits(bmpDate); 148 sw.Stop(); 149 label3.Text = sw.ElapsedMilliseconds.ToString(); 150 151 pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; 152 pictureBox1.Image = bmp; 153}
似たような記述のint型、計算処理プログラムを作成するも
int型だと別途関数を作成した時の値が狂ってしまいlockする必要が出てきてしまいました。
色々と調べたのですが、分からなかったので教えていただけないでしょうか。
質問の意味がよくわかりません。
回答1件
あなたの回答
tips
プレビュー