194 lines
7.0 KiB
C#
194 lines
7.0 KiB
C#
using Newtonsoft.Json;
|
||
using Newtonsoft.Json.Linq;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using XPrintServer.Business.Dto;
|
||
using XPrintServer.Business.Workflows.Configure;
|
||
|
||
namespace XPrintServer.Business.Workflows
|
||
{
|
||
public class QwenWorkflow : Workflow, IDisposable
|
||
{
|
||
public QwenWorkflow(ComfyUIInfos infos) : base(infos)
|
||
{
|
||
workflowPath = Path.Combine(workflowFolder, infos.Workflow.QwenImageFileName);
|
||
CheckWorkFlow();
|
||
}
|
||
|
||
// 调用ComfyUI生成图像
|
||
public async Task<string> GenerateImageAsync(string prompt, string negative_prompt, long seed, int width, int height)
|
||
{
|
||
try
|
||
{
|
||
//CheckWorkFlow();
|
||
if (seed == -1)
|
||
{
|
||
seed = new Random().NextInt64();
|
||
}
|
||
|
||
// 2. 解析并修改工作流中的提示词,宽,高
|
||
var modifiedWorkflow = ModifyWorkflow(prompt, negative_prompt, seed, width, height);
|
||
|
||
// 3. 构建API请求内容
|
||
string requestJson = "{\"client_id\":\"" + client_id + "\",\"prompt\":" + modifiedWorkflow + "}";
|
||
var content = new StringContent(requestJson, Encoding.UTF8, "application/json");
|
||
|
||
// 4. 发送POST请求到ComfyUI API
|
||
//Console.WriteLine("正在发送生成请求...");
|
||
var response = await httpClient!.PostAsync(apiUrl, content);
|
||
response.EnsureSuccessStatusCode();
|
||
|
||
var responseContent = await response.Content.ReadAsStringAsync();
|
||
var result = System.Text.Json.JsonSerializer.Deserialize<ComfyUIPromptResult>(responseContent!)!;
|
||
return result.PromptId!;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"发生错误: {ex.Message} {ex.InnerException}");
|
||
}
|
||
return string.Empty;
|
||
}
|
||
|
||
|
||
// 修改提示词(节点100)
|
||
public void UpdatePrompt(JObject workflow, string newText)
|
||
{
|
||
var node = workflow["100"]?["inputs"]?["text"] as JValue;
|
||
if (node != null && node.Type == JTokenType.String)
|
||
{
|
||
node.Value = newText;
|
||
}
|
||
else
|
||
{
|
||
throw new InvalidOperationException("未找到有效的提示词节点");
|
||
}
|
||
}
|
||
|
||
// 修改分辨率(节点97)
|
||
public void UpdateResolution(JObject workflow, int width, int height)
|
||
{
|
||
var node = workflow["97"]?["inputs"] as JObject;
|
||
if (node != null)
|
||
{
|
||
if (node.TryGetValue("width", out JToken? widthToken))
|
||
{
|
||
widthToken.Replace(width);
|
||
}
|
||
if (node.TryGetValue("height", out JToken? heightToken))
|
||
{
|
||
heightToken.Replace(height);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
throw new InvalidOperationException("未找到分辨率节点");
|
||
}
|
||
}
|
||
|
||
// 修改KSampler节点的种子值
|
||
public void UpdateSeed(JObject workflow, long newSeed)
|
||
{
|
||
// 定位KSampler节点(ID 95)
|
||
var samplerNode = workflow["95"] as JObject;
|
||
if (samplerNode == null)
|
||
throw new KeyNotFoundException("未找到KSampler节点");
|
||
|
||
// 修改seed参数
|
||
JToken seedToken = samplerNode["inputs"]!["seed"]!;
|
||
if (seedToken != null && seedToken.Type == JTokenType.Integer)
|
||
{
|
||
samplerNode["inputs"]!["seed"] = newSeed;
|
||
}
|
||
else
|
||
{
|
||
throw new InvalidCastException("种子参数类型错误");
|
||
}
|
||
}
|
||
|
||
|
||
// 修改工作流中的提示词
|
||
// 修改工作流中的prompt、width、height
|
||
public string ModifyWorkflow(string newPrompt, string negative_prompt, long seed, int newWidth, int newHeight)
|
||
{
|
||
// 解析JSON为可修改的JObject
|
||
JObject workflow = JObject.Parse(workflowJson);
|
||
|
||
UpdatePrompt(workflow, newPrompt);
|
||
|
||
UpdateResolution(workflow, newWidth, newHeight);
|
||
|
||
UpdateSeed(workflow, seed);
|
||
|
||
// 返回修改后的JSON字符串
|
||
return workflow.ToString();
|
||
}
|
||
|
||
// 示例调用
|
||
//public static void Main(string[] args)
|
||
//{
|
||
// try
|
||
// {
|
||
// // 1. 加载工作流JSON文件(替换为你的文件路径)
|
||
// string workflowPath = "your_workflow.json";
|
||
// string originalWorkflow = File.ReadAllText(workflowPath);
|
||
|
||
// // 2. 定义新的参数
|
||
// string newPrompt = "超写实机甲,金属质感,暴雨场景,细节丰富,8K分辨率";
|
||
// int newWidth = 768; // 新宽度
|
||
// int newHeight = 1024; // 新高度
|
||
|
||
// // 3. 修改工作流
|
||
// string modifiedWorkflow = ModifyWorkflow(originalWorkflow, newPrompt, newWidth, newHeight);
|
||
|
||
// // 4. 保存修改后的工作流(可选)
|
||
// string modifiedPath = "modified_workflow.json";
|
||
// File.WriteAllText(modifiedPath, modifiedWorkflow);
|
||
// Console.WriteLine($"修改后的工作流已保存至:{modifiedPath}");
|
||
|
||
// // 5. 后续可将modifiedWorkflow发送到ComfyUI API(参考之前的API调用代码)
|
||
// }
|
||
// catch (Exception ex)
|
||
// {
|
||
// Console.WriteLine($"错误:{ex.Message}");
|
||
// }
|
||
//}
|
||
|
||
// 从响应中提取图像并保存
|
||
private async Task SaveImageFromResponse(System.Text.Json.JsonDocument response, string outputPath)
|
||
{
|
||
// 解析响应中的图像数据(根据实际响应结构调整)
|
||
if (response.RootElement.TryGetProperty("results", out var results))
|
||
{
|
||
foreach (var result in results.EnumerateArray())
|
||
{
|
||
if (result.TryGetProperty("data", out var data) &&
|
||
result.TryGetProperty("type", out var type) &&
|
||
type.GetString() == "image")
|
||
{
|
||
// 解码Base64图像数据
|
||
string base64Image = data.GetString()!;
|
||
byte[] imageBytes = Convert.FromBase64String(base64Image);
|
||
|
||
// 保存图像文件
|
||
await File.WriteAllBytesAsync(outputPath, imageBytes);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
throw new Exception("未从响应中找到图像数据");
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
if (httpClient != null)
|
||
{
|
||
httpClient.Dispose();
|
||
}
|
||
}
|
||
}
|
||
}
|