/// <summary> /// Extract item icons to the target destination /// </summary> /// <param name="itemsArcFullpath">Full path to items.arc</param> /// <param name="destinationFolder"></param> public static void ExtractItemIcons(string itemsArcFullpath, string destinationFolder) { logger.Debug($"Extracting item icons from {itemsArcFullpath} to {destinationFolder}"); try { if (!File.Exists(itemsArcFullpath)) { logger.Warn($"The file {itemsArcFullpath} does not exist, icon extraction aborted."); } else if (!Directory.Exists(destinationFolder)) { logger.Warn($"The specified output folder {destinationFolder} does not exist, icon extraction aborted."); } else { Decompress dc = new Decompress(itemsArcFullpath, true); dc.decompress(); foreach (string icon in dc.strings) { byte[] b = dc.GetTexture(icon); if (b != null && !icon.EndsWith("_dif.tex") && !icon.EndsWith("_nml.tex")) { try { Image img = ExtractImage(b); img?.Save(Path.Combine(destinationFolder, $@"{Path.GetFileName(icon)}.png"), ImageFormat.Png); } catch (Exception ex) { logger.Warn($"Error extracting icon \"{icon}\", {ex.Message}", ex); } } } } } catch (UnauthorizedAccessException) { logger.Warn("Tried to parse GD icons while GD was running: Access denied"); throw; } logger.Debug("Item icon extraction complete"); }
/// <summary> /// Extract item icons to the target destination /// </summary> /// <param name="itemsArcFullPath">Full path to items.arc</param> /// <param name="destinationFolder"></param> public static void ExtractItemIcons(string itemsArcFullPath, string destinationFolder) { const int KiloByte30 = 1024 * 45; logger.Debug($"Extracting item icons from {itemsArcFullPath} to {destinationFolder}"); try { if (!File.Exists(itemsArcFullPath)) { logger.Warn($"The file {itemsArcFullPath} does not exist, icon extraction aborted."); } else if (!Directory.Exists(destinationFolder)) { logger.Warn($"The specified output folder {destinationFolder} does not exist, icon extraction aborted."); } else { var dc = new Decompress(itemsArcFullPath, true); dc.decompress(); foreach (var icon in dc.strings) { var b = dc.GetTexture(icon); if (b == null) { continue; } if (b.Length > KiloByte30) { logger.Warn($"Skipping {icon}, size is {b.Length / 1024}kb, max limit {KiloByte30 / 1024}kb"); continue; } if (icon.EndsWith(".png")) { var imagePath = Path.Combine(destinationFolder, $@"{Path.GetFileName(icon)}"); if (File.Exists(imagePath)) { continue; } try { using (var image = Image.FromStream(new MemoryStream(b))) { var h = image.Height; var w = image.Width; // Anything bigger than 128 is likely a real texture if (w > 128 || h > 128) { continue; } // Anything bigger than 96, and square is most likely a real texture if ((w > 96 || h > 96) && w == h) { continue; } image.Save(imagePath); } } catch (Exception ex) { logger.Warn($"Error extracting icon \"{icon}\", {ex.Message}", ex); } } else if (!icon.EndsWith("_nml.tex") && !icon.EndsWith(".anm") && !icon.EndsWith(".pfx") && !icon.EndsWith(".wav") && !icon.EndsWith("bmp.tex") && !icon.EndsWith("_spec.tex") && !icon.EndsWith("_glo.tex") && !icon.EndsWith("_g.tex") && !icon.EndsWith(".txt") && !icon.EndsWith(".mt1") && !icon.EndsWith(".obj")) { // TODO: Should make this a whitelist instead try { var imagePath = Path.Combine(destinationFolder, $@"{Path.GetFileName(icon)}.png"); logger.Debug($"Parsing icon {icon}"); if (File.Exists(imagePath)) { continue; } var img = ExtractImage(b); img?.Save(imagePath, ImageFormat.Png); } catch (Exception ex) { logger.Warn($"Error extracting icon \"{icon}\", {ex.Message}", ex); } } } } } catch (UnauthorizedAccessException) { logger.Warn("Tried to parse GD icons while GD was running: Access denied"); throw; } logger.Debug("Item icon extraction complete"); }