private static void CropImages(string contentDirectory) { Console.WriteLine("Loading bases pending cropping of transparent borders."); var ponies = new DesktopPonies.PonyCollection(true); string poniesDirectory = Path.Combine(contentDirectory, DesktopPonies.PonyBase.RootDirectory); int currentLine = -1; foreach (var ponyBase in ponies.Bases) { if (currentLine == Console.CursorTop) ConsoleReplacePreviousLine("Checking images for " + ponyBase.Directory); else Console.WriteLine("Checking images for " + ponyBase.Directory); currentLine = Console.CursorTop; var ponyDirectory = Path.Combine(poniesDirectory, ponyBase.Directory); var imageFilePaths = Directory.GetFiles(ponyDirectory, "*.gif").Concat(Directory.GetFiles(ponyDirectory, "*.png")); // Ignore any images involved in effects, as the transparent borders may be used for alignment. var imagesToIgnore = ponyBase.Effects.Select(e => { var behavior = ponyBase.Behaviors.Single(b => b.Name == e.BehaviorName); return new string[] { e.LeftImage.Path, e.RightImage.Path, behavior.LeftImage.Path, behavior.RightImage.Path }; }).SelectMany(images => images).ToArray(); var imageFilePathsToUse = new HashSet<string>(imageFilePaths, DesktopPonies.PathEquality.Comparer); imageFilePathsToUse.ExceptWith(imagesToIgnore); var imageCropInfo = new Dictionary<string, Point>(DesktopPonies.PathEquality.Comparer); foreach (var imageFilePath in imageFilePathsToUse) { Rectangle? maybeCropped = GetCroppedRegion(contentDirectory, imageFilePath); if (maybeCropped.HasValue) { if (Path.GetExtension(imageFilePath) == ".gif") { if (maybeCropped.Value == Rectangle.Empty) CropGifImage(contentDirectory, imageFilePath, new Rectangle(0, 0, 1, 1)); else CropGifImage(contentDirectory, imageFilePath, maybeCropped.Value); } else { CropPngImage(contentDirectory, imageFilePath, maybeCropped.Value); } imageCropInfo.Add(imageFilePath, maybeCropped.Value.Location); } } bool changed = false; foreach (var behavior in ponyBase.Behaviors) { changed = FixCustomCenter(imageCropInfo, behavior, true) || changed; changed = FixCustomCenter(imageCropInfo, behavior, false) || changed; } if (changed) ponyBase.Save(); } }
private static void CropImages(string toolDirectory, string contentDirectory) { Console.WriteLine("Loading bases pending cropping of transparent borders."); var ponies = new DesktopPonies.PonyCollection(true); var poniesDirectory = Path.Combine(contentDirectory, DesktopPonies.PonyBase.RootDirectory); var currentLine = -1; foreach (var ponyBase in ponies.Bases) { if (currentLine == Console.CursorTop) { ConsoleReplacePreviousLine("Checking images for " + ponyBase.Directory); } else { Console.WriteLine("Checking images for " + ponyBase.Directory); } currentLine = Console.CursorTop; var ponyDirectory = Path.Combine(poniesDirectory, ponyBase.Directory); var imageFilePaths = Directory.GetFiles(ponyDirectory, "*.gif").Concat(Directory.GetFiles(ponyDirectory, "*.png")) .Select(filePath => filePath.Replace(contentDirectory + Path.DirectorySeparatorChar, "")); // Ignore any images involved in effects or behavior chains when set up by follow targets, as the transparent borders may // be used for alignment. // TODO: An improved method would not be to ignore these images, but consider them more carefully. // For effects, each side could be considered individually and the minimum of any shared padding between the behavior and // effect could be cropped. // For images in sequences, the union of the minimums for each image in the sequences for both the follower and followee // could be cropped. var imagesToIgnore = ponyBase.Effects.Select( e => new[] { e.LeftImage.Path, e.RightImage.Path, e.GetBehavior().LeftImage.Path, e.GetBehavior().RightImage.Path }) .Concat( ponyBase.Behaviors.Where(b => !string.IsNullOrEmpty(b.FollowTargetName)).SelectMany( b => { var behaviorChain = new List <DesktopPonies.Behavior>(); while (b != null) { behaviorChain.Add(b); b = b.GetLinkedBehavior(); } return(behaviorChain); }).Select( b => new[] { b.LeftImage.Path, b.RightImage.Path })) .SelectMany(images => images); var imageFilePathsToUse = new HashSet <string>(imageFilePaths, PathEquality.Comparer); imageFilePathsToUse.ExceptWith(imagesToIgnore); var imageCropInfo = new Dictionary <string, Point>(PathEquality.Comparer); foreach (var imageFilePath in imageFilePathsToUse) { Rectangle?maybeCropped = GetCroppedRegion(imageFilePath); if (maybeCropped.HasValue) { if (Path.GetExtension(imageFilePath) == ".gif") { CropGifImage(toolDirectory, contentDirectory, imageFilePath, maybeCropped.Value); } else { CropPngImage(contentDirectory, imageFilePath, maybeCropped.Value); } imageCropInfo.Add(imageFilePath, maybeCropped.Value.Location); } } var changed = false; foreach (var behavior in ponyBase.Behaviors) { changed = FixCustomCenter(imageCropInfo, behavior, true) || changed; changed = FixCustomCenter(imageCropInfo, behavior, false) || changed; } if (changed) { ponyBase.Save(); } } if (currentLine == Console.CursorTop) { ConsoleReplacePreviousLine(""); } }
private static void CropImages(string contentDirectory) { Console.WriteLine("Loading bases pending cropping of transparent borders."); var ponies = new DesktopPonies.PonyCollection(true); string poniesDirectory = Path.Combine(contentDirectory, DesktopPonies.PonyBase.RootDirectory); int currentLine = -1; foreach (var ponyBase in ponies.Bases) { if (currentLine == Console.CursorTop) { ConsoleReplacePreviousLine("Checking images for " + ponyBase.Directory); } else { Console.WriteLine("Checking images for " + ponyBase.Directory); } currentLine = Console.CursorTop; var ponyDirectory = Path.Combine(poniesDirectory, ponyBase.Directory); var imageFilePaths = Directory.GetFiles(ponyDirectory, "*.gif").Concat(Directory.GetFiles(ponyDirectory, "*.png")); // Ignore any images involved in effects, as the transparent borders may be used for alignment. var imagesToIgnore = ponyBase.Effects.Select(e => { var behavior = ponyBase.Behaviors.Single(b => b.Name == e.BehaviorName); return(new string[] { e.LeftImage.Path, e.RightImage.Path, behavior.LeftImage.Path, behavior.RightImage.Path }); }).SelectMany(images => images).ToArray(); var imageFilePathsToUse = new HashSet <string>(imageFilePaths, DesktopPonies.PathEquality.Comparer); imageFilePathsToUse.ExceptWith(imagesToIgnore); var imageCropInfo = new Dictionary <string, Point>(DesktopPonies.PathEquality.Comparer); foreach (var imageFilePath in imageFilePathsToUse) { Rectangle?maybeCropped = GetCroppedRegion(contentDirectory, imageFilePath); if (maybeCropped.HasValue) { if (Path.GetExtension(imageFilePath) == ".gif") { if (maybeCropped.Value == Rectangle.Empty) { CropGifImage(contentDirectory, imageFilePath, new Rectangle(0, 0, 1, 1)); } else { CropGifImage(contentDirectory, imageFilePath, maybeCropped.Value); } } else { CropPngImage(contentDirectory, imageFilePath, maybeCropped.Value); } imageCropInfo.Add(imageFilePath, maybeCropped.Value.Location); } } bool changed = false; foreach (var behavior in ponyBase.Behaviors) { changed = FixCustomCenter(imageCropInfo, behavior, true) || changed; changed = FixCustomCenter(imageCropInfo, behavior, false) || changed; } if (changed) { ponyBase.Save(); } } }
private static void CropImages(string toolDirectory, string contentDirectory) { Console.WriteLine("Loading bases pending cropping of transparent borders."); var ponies = new DesktopPonies.PonyCollection(true); string poniesDirectory = Path.Combine(contentDirectory, DesktopPonies.PonyBase.RootDirectory); int currentLine = -1; foreach (var ponyBase in ponies.Bases) { if (currentLine == Console.CursorTop) ConsoleReplacePreviousLine("Checking images for " + ponyBase.Directory); else Console.WriteLine("Checking images for " + ponyBase.Directory); currentLine = Console.CursorTop; var ponyDirectory = Path.Combine(poniesDirectory, ponyBase.Directory); var imageFilePaths = Directory.GetFiles(ponyDirectory, "*.gif").Concat(Directory.GetFiles(ponyDirectory, "*.png")) .Select(filePath => filePath.Replace(contentDirectory + Path.DirectorySeparatorChar, "")); // Ignore any images involved in effects or behavior chains when set up by follow targets, as the transparent borders may // be used for alignment. // TODO: An improved method would not be to ignore these images, but consider them more carefully. // For effects, each side could be considered individually and the minimum of any shared padding between the behavior and // effect could be cropped. // For images in sequences, the union of the minimums for each image in the sequences for both the follower and followee // could be cropped. var imagesToIgnore = ponyBase.Effects.Select( e => new[] { e.LeftImage.Path, e.RightImage.Path, e.GetBehavior().LeftImage.Path, e.GetBehavior().RightImage.Path }) .Concat( ponyBase.Behaviors.Where(b => !string.IsNullOrEmpty(b.FollowTargetName)).SelectMany( b => { var behaviorChain = new List<DesktopPonies.Behavior>(); while (b != null) { behaviorChain.Add(b); b = b.GetLinkedBehavior(); } return behaviorChain; }).Select( b => new[] { b.LeftImage.Path, b.RightImage.Path })) .SelectMany(images => images); var imageFilePathsToUse = new HashSet<string>(imageFilePaths, PathEquality.Comparer); imageFilePathsToUse.ExceptWith(imagesToIgnore); var imageCropInfo = new Dictionary<string, Point>(PathEquality.Comparer); foreach (var imageFilePath in imageFilePathsToUse) { Rectangle? maybeCropped = GetCroppedRegion(imageFilePath); if (maybeCropped.HasValue) { if (Path.GetExtension(imageFilePath) == ".gif") CropGifImage(toolDirectory, contentDirectory, imageFilePath, maybeCropped.Value); else CropPngImage(contentDirectory, imageFilePath, maybeCropped.Value); imageCropInfo.Add(imageFilePath, maybeCropped.Value.Location); } } bool changed = false; foreach (var behavior in ponyBase.Behaviors) { changed = FixCustomCenter(imageCropInfo, behavior, true) || changed; changed = FixCustomCenter(imageCropInfo, behavior, false) || changed; } if (changed) ponyBase.Save(); } if (currentLine == Console.CursorTop) ConsoleReplacePreviousLine(""); }