-
-
Notifications
You must be signed in to change notification settings - Fork 395
Add "Scale To Side Length" Resolution Mode to Image Batch Tool #1359
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,8 @@ | |
| using System; | ||
| using System.IO; | ||
| using System.Net.WebSockets; | ||
| using SixLabors.ImageSharp.Metadata.Profiles.Exif; | ||
| using SixLabors.ImageSharp.Processing; | ||
| using ISImage = SixLabors.ImageSharp.Image; | ||
|
|
||
| namespace SwarmUI.Builtin_ImageBatchToolExtension; | ||
|
|
@@ -30,7 +32,7 @@ public override void OnInit() | |
| } | ||
|
|
||
| /// <summary>API route to generate images with WebSocket updates.</summary> | ||
| public static async Task<JObject> ImageBatchRun(WebSocket socket, Session session, JObject rawInput, string input_folder, string output_folder, bool init_image, bool revision, bool controlnet, string resMode, bool append_filename_to_prompt) | ||
| public static async Task<JObject> ImageBatchRun(WebSocket socket, Session session, JObject rawInput, string input_folder, string output_folder, bool init_image, bool revision, bool controlnet, string resMode, bool append_filename_to_prompt, bool use_same_side_length = true, int input_side_length = 1024, int output_side_length = 1024) | ||
| { | ||
| // TODO: Strict path validation / user permission confirmation. | ||
| if (input_folder.Length < 5 || output_folder.Length < 5) | ||
|
|
@@ -61,17 +63,23 @@ public static async Task<JObject> ImageBatchRun(WebSocket socket, Session sessio | |
| await socket.SendAndReportError($"ImageBatchRun request from {session.User.UserID}, for folder '{input_folder}'", "Image batch needs to supply the images to at least one parameter.", API.WebsocketTimeout); | ||
| return null; | ||
| } | ||
| // In case someone tries to leverage the websocket API directly, not possible from UI | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this comment shouldn't be here |
||
| if (input_side_length <= 0 || output_side_length <= 0) | ||
| { | ||
| await socket.SendAndReportError($"ImageBatchRun request from {session.User.UserID}", "Side lengths must be positive values.", API.WebsocketTimeout); | ||
| return null; | ||
| } | ||
| Directory.CreateDirectory(output_folder); | ||
| await API.RunWebsocketHandlerCallWS(GenBatchRun_Internal, session, (rawInput, input_folder, output_folder, init_image, revision, controlnet, imageFiles, resMode, append_filename_to_prompt), socket); | ||
| await API.RunWebsocketHandlerCallWS(GenBatchRun_Internal, session, (rawInput, input_folder, output_folder, init_image, revision, controlnet, imageFiles, resMode, append_filename_to_prompt, use_same_side_length, input_side_length, output_side_length), socket); | ||
| Logs.Info("Image Batcher completed successfully"); | ||
| await socket.SendJson(new JObject() { ["success"] = "complete" }, API.WebsocketTimeout); | ||
| return null; | ||
| } | ||
|
|
||
| public static async Task GenBatchRun_Internal(Session session, (JObject, string, string, bool, bool, bool, string[], string, bool) input, Action<JObject> output, bool isWS) | ||
| public static async Task GenBatchRun_Internal(Session session, (JObject, string, string, bool, bool, bool, string[], string, bool, bool, int, int) input, Action<JObject> output, bool isWS) | ||
| { | ||
| // TODO: This is a silly way of passing data, time for a struct? | ||
| (JObject rawInput, string input_folder, string output_folder, bool init_image, bool revision, bool controlnet, string[] imageFiles, string resMode, bool appendFilenameToPrompt) = input; | ||
| (JObject rawInput, string input_folder, string output_folder, bool init_image, bool revision, bool controlnet, string[] imageFiles, string resMode, bool appendFilenameToPrompt, bool useSameSideLength, int inputSideLength, int outputSideLength) = input; | ||
| using Session.GenClaim claim = session.Claim(gens: imageFiles.Length); | ||
| async Task sendStatus() | ||
| { | ||
|
|
@@ -129,6 +137,17 @@ void removeDoneTasks() | |
| } | ||
| Image image = new(File.ReadAllBytes(file), MediaType.GetByExtension(file.AfterLast('.'))); | ||
| ISImage imgData = image.ToIS; | ||
| // Check EXIF to make sure we have the correct orientation | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. again, comment should be here |
||
| if (imgData.Metadata?.ExifProfile?.TryGetValue(ExifTag.Orientation, out IExifValue<ushort> orientationValue) ?? false) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems out of place to be in this PR |
||
| { | ||
| ushort orientation = orientationValue.Value; | ||
| if (orientation != 1) | ||
| { | ||
| using ISImage oriented = imgData.Clone(x => x.AutoOrient()); | ||
| image = new Image(ImageFile.ISImgToPngBytes(oriented), MediaType.ImagePng); | ||
| imgData = image.ToIS; | ||
| } | ||
| } | ||
| T2IParamInput param = baseParams.Clone(); | ||
| void setRes(int width, int height) | ||
| { | ||
|
|
@@ -164,6 +183,20 @@ void setRes(int width, int height) | |
| setRes(width, height); | ||
| } | ||
| break; | ||
| case "Scale Input To Side Length": | ||
| (int scaledInputWidth, int scaledInputHeight) = Utilities.ResToModelFit(imgData.Width, imgData.Height, inputSideLength * inputSideLength, 16); | ||
| image = (Image)((ImageFile)image).Resize(scaledInputWidth, scaledInputHeight); | ||
| imgData = image.ToIS; | ||
| if (useSameSideLength) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this boolean and code around it make no sense |
||
| { | ||
| setRes(scaledInputWidth, scaledInputHeight); | ||
| } | ||
| else | ||
| { | ||
| (int scaledOutputWidth, int scaledOutputHeight) = Utilities.ResToModelFit(imgData.Width, imgData.Height, outputSideLength * outputSideLength, 16); | ||
| setRes(scaledOutputWidth, scaledOutputHeight); | ||
| } | ||
| break; | ||
| default: | ||
| throw new SwarmUserErrorException("Invalid resolution mode"); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This value makes no sense to have