@@ -8,9 +8,9 @@ namespace Unity_Mask_Map_Generator
88{
99 public partial class Form1 : Form
1010 {
11- Bitmap metallic , ao , detail , smoothness , maskMap ;
12- bool state1 , state2 , state3 , state4 = false ;
13- bool invertState1 , invertState2 , invertState3 , invertState4 = false ;
11+ private static Bitmap metallic , ao , detail , smoothness , maskMap ;
12+ private static bool state1 , state2 , state3 , state4 = false ;
13+ private static bool invertState1 , invertState2 , invertState3 , invertState4 = false ;
1414 int imageCount = 0 ;
1515 public Form1 ( )
1616 {
@@ -144,7 +144,7 @@ private void button1_Click(object sender, EventArgs e)
144144 if ( state1 == true || state2 == true || state3 == true || state4 == true )
145145 {
146146 helpText . Visible = false ;
147- generateMaskMap ( ) ;
147+ GenerateMaskMap ( ) ;
148148 }
149149 else if ( metallic != null && ao != null && smoothness != null && detail != null && ! isBoundsMatching ( ) )
150150 {
@@ -258,57 +258,125 @@ private void pictureBox3_DragDrop(object sender, DragEventArgs e)
258258
259259 }
260260
261- private async void generateMaskMap ( )
261+ private async void GenerateMaskMap ( )
262262 {
263263 CheckForIllegalCrossThreadCalls = false ;
264+
264265 int width = Math . Max ( Math . Max ( metallic ? . Width ?? 0 , ao ? . Width ?? 0 ) , Math . Max ( smoothness ? . Width ?? 0 , detail ? . Width ?? 0 ) ) ;
265266 int height = Math . Max ( Math . Max ( metallic ? . Height ?? 0 , ao ? . Height ?? 0 ) , Math . Max ( smoothness ? . Height ?? 0 , detail ? . Height ?? 0 ) ) ;
267+
266268 save . Visible = false ;
267269 imgSize . Visible = false ;
268270 maskMap ? . Dispose ( ) ;
269271 maskMap = null ;
270272 resultPictureBox . Image = null ;
273+
271274 maskMap = new Bitmap ( width , height ) ;
272275 progressBar1 . Visible = true ;
273276 EnableOrDisableCheckBoxes ( false ) ;
274- Stopwatch stopwatch = new Stopwatch ( ) ;
275- stopwatch . Start ( ) ;
276- await GlobalScope . Launch ( ( ) =>
277+
278+ generate . Enabled = false ;
279+ generate . Text = "Generating..." ;
280+ helpText2 . Visible = true ;
281+ progressLabel . Visible = true ;
282+
283+ byte [ ] maskMapData = new byte [ width * height * 4 ] ;
284+ byte [ ] ? metallicData = metallic != null ? ConvertBitmapToByteArray ( metallic ) : null ;
285+ byte [ ] ? aoData = ao != null ? ConvertBitmapToByteArray ( ao ) : null ;
286+ byte [ ] ? detailData = detail != null ? ConvertBitmapToByteArray ( detail ) : null ;
287+ byte [ ] ? smoothnessData = smoothness != null ? ConvertBitmapToByteArray ( smoothness ) : null ;
288+
289+ Stopwatch stopwatch = Stopwatch . StartNew ( ) ;
290+
291+ // Using the CoroutineBuilder to launch multiple coroutines in parallel
292+ await CoroutineBuilder . LaunchAll ( new List < Func < Task > > {
293+ ( ) => { ProcessImage ( maskMapData , metallicData , aoData , detailData , smoothnessData , width , height , 0 , height / 4 ) ; return Task . CompletedTask ; } ,
294+ ( ) => { ProcessImage ( maskMapData , metallicData , aoData , detailData , smoothnessData , width , height , height / 4 , height / 4 ) ; return Task . CompletedTask ; } ,
295+ ( ) => { ProcessImage ( maskMapData , metallicData , aoData , detailData , smoothnessData , width , height , height / 2 , height / 4 ) ; return Task . CompletedTask ; } ,
296+ ( ) => { ProcessImage ( maskMapData , metallicData , aoData , detailData , smoothnessData , width , height , 3 * height / 4 , height / 4 ) ; return Task . CompletedTask ; }
297+ } , Dispatcher . Main ) ;
298+
299+ maskMap = ConvertToBitmap ( maskMapData , width , height ) ;
300+ resultPictureBox . Image = maskMap ;
301+ stopwatch . Stop ( ) ;
302+ imgSize . Text = $ "Image Size: { width } x { height } ({ stopwatch . ElapsedMilliseconds / 1000f : F2} s)";
303+ imgSize . Visible = true ;
304+ progressBar1 . Visible = false ;
305+ progressLabel . Visible = false ;
306+ save . Visible = true ;
307+ helpText2 . Visible = false ;
308+ generate . Text = "Generate" ;
309+ EnableOrDisableCheckBoxes ( true ) ;
310+ generate . Enabled = true ;
311+ }
312+
313+ private static byte [ ] ConvertBitmapToByteArray ( Bitmap bitmap )
314+ {
315+ int width = bitmap . Width ;
316+ int height = bitmap . Height ;
317+ byte [ ] byteArray = new byte [ width * height * 4 ] ;
318+
319+ var bitmapData = bitmap . LockBits ( new Rectangle ( 0 , 0 , width , height ) , ImageLockMode . ReadOnly , PixelFormat . Format32bppArgb ) ;
320+ System . Runtime . InteropServices . Marshal . Copy ( bitmapData . Scan0 , byteArray , 0 , byteArray . Length ) ;
321+ bitmap . UnlockBits ( bitmapData ) ;
322+
323+ return byteArray ;
324+ }
325+
326+ private static void ProcessImage ( byte [ ] maskMapData , byte [ ] metallicData , byte [ ] aoData , byte [ ] detailData , byte [ ] smoothnessData , int width , int height , int startY , int chunkHeight )
327+ {
328+ for ( int y = startY ; y < startY + chunkHeight ; y ++ )
277329 {
278- generate . Enabled = false ;
279- generate . Text = "Generating..." ;
280- helpText2 . Visible = true ;
281- progressLabel . Visible = true ;
282- for ( int y = 0 ; y < height ; y ++ )
330+ for ( int x = 0 ; x < width ; x ++ )
283331 {
284- for ( int x = 0 ; x < width ; x ++ )
332+ int index = ( y * width + x ) * 4 ;
333+
334+ int a = 255 , r = 0 , g = 0 , b = 0 ;
335+
336+ if ( metallicData != null )
285337 {
286- int r = metallic != null ? metallic . GetPixel ( x , y ) . R : 0 ;
338+ int metallicIndex = index ;
339+ r = metallicData [ metallicIndex + 2 ] ;
287340 if ( invertState1 ) r = 255 - r ;
288- int g = ao != null ? ao . GetPixel ( x , y ) . G : 0 ;
341+ }
342+
343+ if ( aoData != null )
344+ {
345+ int aoIndex = index ;
346+ g = aoData [ aoIndex + 1 ] ;
289347 if ( invertState2 ) g = 255 - g ;
290- int b = detail != null ? detail . GetPixel ( x , y ) . B : 0 ;
348+ }
349+
350+ if ( detailData != null )
351+ {
352+ int detailIndex = index ;
353+ b = detailData [ detailIndex ] ;
291354 if ( invertState4 ) b = 255 - b ;
292- int a = smoothness != null ? smoothness . GetPixel ( x , y ) . R : 255 ;
355+ }
356+
357+ if ( smoothnessData != null )
358+ {
359+ int smoothnessIndex = index ;
360+ a = smoothnessData [ smoothnessIndex + 3 ] ;
293361 if ( invertState3 ) a = 255 - a ;
294- maskMap . SetPixel ( x , y , Color . FromArgb ( a , r , g , b ) ) ;
295362 }
296- int progress = ( int ) ( ( y * 1f ) / height * 100 ) ;
297- progressLabel . Text = progress + "%" ;
298- progressBar1 . Value = progress ;
363+
364+ maskMapData [ index + 0 ] = ( byte ) b ;
365+ maskMapData [ index + 1 ] = ( byte ) g ;
366+ maskMapData [ index + 2 ] = ( byte ) r ;
367+ maskMapData [ index + 3 ] = ( byte ) a ;
299368 }
300- stopwatch . Stop ( ) ;
301- imgSize . Text = $ "Image Size: { width } x { height } ({ stopwatch . ElapsedMilliseconds / 1000f } s)";
302- imgSize . Visible = true ;
303- progressBar1 . Visible = false ;
304- progressLabel . Visible = false ;
305- save . Visible = true ;
306- helpText2 . Visible = false ;
307- generate . Text = "Generate" ;
308- EnableOrDisableCheckBoxes ( true ) ;
309- generate . Enabled = true ;
310- } ) ;
311- resultPictureBox . Image = maskMap ;
369+ }
370+ }
371+
372+ private static Bitmap ConvertToBitmap ( byte [ ] pixelData , int width , int height )
373+ {
374+ Bitmap bitmap = new Bitmap ( width , height , System . Drawing . Imaging . PixelFormat . Format32bppArgb ) ;
375+ var bitmapData = bitmap . LockBits ( new Rectangle ( 0 , 0 , width , height ) , System . Drawing . Imaging . ImageLockMode . WriteOnly , bitmap . PixelFormat ) ;
376+ System . Runtime . InteropServices . Marshal . Copy ( pixelData , 0 , bitmapData . Scan0 , pixelData . Length ) ;
377+ bitmap . UnlockBits ( bitmapData ) ;
378+
379+ return bitmap ;
312380 }
313381
314382 private void EnableOrDisableCheckBoxes ( bool state )
0 commit comments