Advertisement
Guest User

Untitled

a guest
Oct 3rd, 2018
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.28 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Drawing;
  5. using System.Drawing.Imaging;
  6. using System.IO;
  7. using System.Runtime.InteropServices;
  8.  
  9. namespace RMAPack
  10. {
  11.     public struct ImageDesc
  12.     {
  13.         public string Roughness;
  14.         public string Metallicty;
  15.         public string BaseColor;
  16.         public string AmbientOcclusion;
  17.         public string Normal;
  18.     }
  19.  
  20.     class Program
  21.     {
  22.         private static readonly string[] BASE_COLOR = new string[] { "_base_color", "_basecolor" };
  23.         private static readonly string[] NORMAL = new string[] { "_normal" };
  24.         private static readonly string[] ROUGHNESS = new string[] { "_roughness", "_rough", "_r"};
  25.         private static readonly string[] METALLIC = new string[] { "_metallic", "_metallicity", "_m"};
  26.         private static readonly string[] AMBIENT_OCCLUSION = new string[] { "_ambientocclusion" };
  27.  
  28.         static void Main(string[] args)
  29.         {
  30.             if (args.Length < 2)
  31.             {
  32.                 Usage();
  33.                 return;
  34.             }
  35.             var sourceDir = args[0];
  36.             var targetDir = args[1];
  37.             ProcessFolder(sourceDir, targetDir);
  38.         }
  39.  
  40.         static void ProcessFolder(string sourceDir, string targetDir)
  41.         {
  42.             var sourceFiles = Directory.EnumerateFiles(sourceDir);
  43.             var desces = CollectDescriptions(sourceFiles);
  44.             foreach (var desc in desces)
  45.             {
  46.                 if (string.IsNullOrEmpty(desc.Value.Roughness) || string.IsNullOrEmpty(desc.Value.Metallicty)
  47.                     || string.IsNullOrEmpty(desc.Value.Normal) || string.IsNullOrEmpty(desc.Value.BaseColor))
  48.                 {
  49.                     Console.WriteLine($@"Skipping {desc.Key} - not enough maps");
  50.                     continue;
  51.                 }
  52.                 using (var normal = Bitmap.FromFile(desc.Value.Normal))
  53.                 using (var baseColor = Bitmap.FromFile(desc.Value.BaseColor))
  54.                 using (var mask = ProcessImage(desc.Key, desc.Value))
  55.                 {
  56.                     var maskOutPath = Path.Combine(targetDir, $"T_{desc.Key}_M.png");
  57.                     var baseOutPath = Path.Combine(targetDir, $"T_{desc.Key}_BC.png");
  58.                     var normalOutPath = Path.Combine(targetDir, $"T_{desc.Key}_N.png");
  59.                     mask.Save(maskOutPath, ImageFormat.Png);
  60.                     normal.Save(normalOutPath, ImageFormat.Png);
  61.                     baseColor.Save(baseOutPath, ImageFormat.Png);
  62.                 }
  63.             }
  64.         }
  65.  
  66.         static Bitmap ProcessImage(string imageName, ImageDesc desc)
  67.         {
  68.             Console.WriteLine($@"Processing {imageName}");
  69.             using (var roughness = Bitmap.FromFile(desc.Roughness))
  70.             using (var metallicity = Bitmap.FromFile(desc.Metallicty))
  71.             {
  72.                 Console.WriteLine(" Loading source images");
  73.                 var ao = string.IsNullOrEmpty(desc.AmbientOcclusion) ? null : Bitmap.FromFile(desc.AmbientOcclusion);
  74.  
  75.                 var roughnessData = ExtractRedChannel(roughness as Bitmap);
  76.                 var metallicityData = ExtractRedChannel(metallicity as Bitmap);
  77.                 var aoData = ao != null ? ExtractRedChannel(ao as Bitmap) : null;
  78.                 var resultImage = new Bitmap(roughness);
  79.                 BitmapData data = null;
  80.                 try
  81.                 {
  82.                     data = resultImage.LockBits(new Rectangle(0, 0, resultImage.Width, resultImage.Height),
  83.                         ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
  84.                     var resultData = new byte[data.Stride * resultImage.Width];
  85.                     Console.WriteLine(" Composing final image");
  86.                     for (var row = 0; row < resultImage.Height; row++)
  87.                     {
  88.                         for (var offset = 0; offset < resultImage.Width; offset++)
  89.                         {
  90.                             var inShift = row * resultImage.Width + offset;
  91.                             var outShift = (row * data.Stride + offset * 3);
  92.                             resultData[outShift + 2] = roughnessData[inShift];
  93.                             resultData[outShift + 1] = metallicityData[inShift];
  94.                             resultData[outShift] = aoData != null ? aoData[inShift] : (byte)255;
  95.                          
  96.                         }
  97.                     }
  98.                     Marshal.Copy(resultData, 0, data.Scan0, resultData.Length);
  99.                     return resultImage;
  100.                 }
  101.                 finally
  102.                 {
  103.                     if (data != null)
  104.                     {
  105.                         resultImage.UnlockBits(data);
  106.                     }
  107.                     if (ao != null)
  108.                     {
  109.                         ao.Dispose();
  110.                     }
  111.                 }
  112.             }
  113.         }
  114.  
  115.         static byte[] ExtractRedChannel(Bitmap bitmap)
  116.         {
  117.             BitmapData data = null;
  118.             try
  119.             {
  120.                 data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly,
  121.                     PixelFormat.Format24bppRgb);
  122.                 var result = new byte[bitmap.Width * bitmap.Height];
  123.                 var sourceData = new byte[data.Stride * bitmap.Height];
  124.                 Marshal.Copy(data.Scan0, sourceData, 0, sourceData.Length);
  125.                 for (var row = 0; row < bitmap.Height; row++)
  126.                 {
  127.                     for (var shift = 0; shift < bitmap.Width; shift++)
  128.                     {
  129.                         var red = sourceData[(row * data.Stride + shift * 3)];
  130.                         result[row * bitmap.Width + shift] = red;
  131.                     }
  132.                 }
  133.                 return result;
  134.             }
  135.             finally
  136.             {
  137.                 if (data != null)
  138.                 {
  139.                     bitmap.UnlockBits(data);
  140.                 }
  141.                
  142.             }
  143.            
  144.         }
  145.  
  146.         private static Dictionary<string, ImageDesc> CollectDescriptions(IEnumerable<string> sourceFiles)
  147.         {
  148.             var allImageDesc = new Dictionary<string, ImageDesc>();
  149.             foreach (var sourceFile in sourceFiles)
  150.             {
  151.                 var fullName = Path.GetFileNameWithoutExtension(sourceFile.ToLower());
  152.                 var lastUnderscorePosition = fullName.LastIndexOf("_");
  153.                 if (fullName.EndsWith(BASE_COLOR[0]))
  154.                 {
  155.                     lastUnderscorePosition = fullName.LastIndexOf(BASE_COLOR[0]); // HACK!
  156.                 }                
  157.                 if (lastUnderscorePosition < 0)
  158.                 {
  159.                     continue;
  160.                 }
  161.                 var imageName = fullName.Substring(0, lastUnderscorePosition);
  162.                 ImageDesc desc;
  163.                 if (!allImageDesc.TryGetValue(imageName, out desc))
  164.                 {
  165.                     desc = new ImageDesc();
  166.                 }
  167.                 if (IsNameEndsWith(fullName, ROUGHNESS))
  168.                 {
  169.                     desc.Roughness = sourceFile;
  170.                 }
  171.                 else if (IsNameEndsWith(fullName, METALLIC))
  172.                 {
  173.                     desc.Metallicty = sourceFile;
  174.                 }
  175.                 else if (IsNameEndsWith(fullName, BASE_COLOR))
  176.                 {
  177.                     desc.BaseColor = sourceFile;
  178.                 }
  179.                 else if (IsNameEndsWith(fullName, NORMAL))
  180.                 {
  181.                     desc.Normal = sourceFile;
  182.                 }
  183.                 else if (IsNameEndsWith(fullName, AMBIENT_OCCLUSION))
  184.                 {
  185.                     desc.AmbientOcclusion = sourceFile;
  186.                 }
  187.                 allImageDesc[imageName] = desc;
  188.             }
  189.             return allImageDesc;
  190.         }
  191.  
  192.         static bool IsNameEndsWith(string name, string[] ends)
  193.         {
  194.             foreach (var end in ends)
  195.             {
  196.                 if (name.EndsWith(end))
  197.                 {
  198.                     return true;
  199.                 }
  200.             }
  201.             return false;
  202.         }
  203.  
  204.         static void Usage()
  205.         {
  206.             Console.WriteLine("Usage: rmapack sourcedir targetdir");
  207.         }
  208.     }
  209. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement