Skip to content
This repository was archived by the owner on Nov 27, 2024. It is now read-only.

Commit 0d6527c

Browse files
committed
Add multiple result view
1 parent c9286bc commit 0d6527c

File tree

2 files changed

+142
-17
lines changed

2 files changed

+142
-17
lines changed

OnnxStack.WebUI/Pages/StableDiffusion/TextToImage.cshtml

Lines changed: 142 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,27 @@
7878
</form>
7979
</div>
8080

81-
<div class="d-flex flex-row gap-2 justify-content-center pt-5" autocomplete="off">
82-
<button type="button" class="btn-cancel btn btn-warning w-25" disabled>Cancel</button>
83-
<button id="btn-txt2img-execute" type="button" class="btn btn-success w-25">Generate</button>
81+
<div class="d-flex flex-row gap-2 justify-content-between pt-5" autocomplete="off">
82+
<div class="d-flex flex-column justify-content-end w-50">
83+
<div class="d-flex flex-row gap-2">
84+
<button type="button" class="btn-cancel btn btn-warning w-100" disabled>Cancel</button>
85+
<button id="btn-txt2img-execute" type="button" class="btn btn-success w-100">Generate</button>
86+
</div>
87+
</div>
88+
<div class="d-flex flex-row justify-content-end w-50">
89+
<div>
90+
<small>Mode</small>
91+
<div class="d-flex flex-row gap-1">
92+
<select id="result-layout" class="form-control form-select form-select-sm">
93+
<option value="Single">Single</option>
94+
<option value="Multiple">Multiple</option>
95+
</select>
96+
<button id="btn-clear" class="btn btn-sm btn-danger">
97+
<i class="fa fa-trash"></i>
98+
</button>
99+
</div>
100+
</div>
101+
</div>
84102
</div>
85103
</div>
86104
</div>
@@ -89,18 +107,20 @@
89107
<div class="d-flex w-100 p-2 border border-1">
90108
<div id="output-container" class="d-flex flex-fill flex-wrap justify-content-center align-content-center align-items-center">
91109
</div>
110+
<div id="output-container-grid" class="d-flex flex-fill flex-wrap justify-content-start align-content-start align-items-start gap-3" style="overflow-y:auto">
111+
</div>
92112
</div>
93113
</div>
94114
</div>
95115

96116
<script id="progressResultTemplate" type="text/html">
97-
<div class="d-flex flex-column border border-1 p-1" style="min-width:256px">
117+
<div class="output-progress d-flex flex-column border border-1 p-1" style="min-width:256px;">
98118
<div style="overflow:hidden;">
99-
<img id="img-result" width="512" src="~/images/placeholder.jpg" />
119+
<img width="{{width}}" height="{{height}}" src="~/images/placeholder.jpg" />
100120
</div>
101121
<div class="d-flex flex-column pt-2">
102122
<div class="progress">
103-
<div id="progress-result" class="progress-bar" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
123+
<div class="progress-result progress-bar" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
104124
</div>
105125
</div>
106126
<div class="d-flex flex-row gap-2 pt-2">
@@ -111,17 +131,26 @@
111131
</script>
112132

113133
<script id="outputResultTemplate" type="text/html">
114-
<div class="d-flex flex-column border border-1 p-1" style="min-width:256px">
115-
<div style="overflow:hidden;">
116-
<img id="img-result" style="max-width:100%;max-height:100%;width:auto;height:auto" src="{{outputImageUrl}}" />
134+
<div class="d-flex flex-column border border-1 p-1" style="min-width:256px;">
135+
<div style="overflow:hidden;text-align:center">
136+
<img id="img-result" width="{{width}}" height="{{height}}" src="{{outputImageUrl}}" />
117137
</div>
118138
<div class="d-flex flex-column pt-2">
119139
<div class="progress">
120140
<div class="progress-bar" role="progressbar" style="width: 100%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">Completed</div>
121141
</div>
122142
</div>
123143
<div class="d-flex flex-row gap-2 pt-2">
124-
<a class="btn btn-sm btn-success w-100" href="{{outputImageUrl}}" download="{{OutputImage}}">Download</a>
144+
<div class="btn-group dropend w-100">
145+
<a class="btn btn-sm btn-success w-100" href="{{outputImageUrl}}" download="{{OutputImage}}">Download</a>
146+
<button type="button" class="btn btn-sm btn-success dropdown-toggle dropdown-toggle-split w-25" data-bs-toggle="dropdown" aria-expanded="false">
147+
148+
</button>
149+
<ul class="dropdown-menu">
150+
<li><a class="dropdown-item" href="{{outputImageUrl}}" download="{{OutputImage}}">Download PNG</a></li>
151+
<li><a class="dropdown-item" href="{{outputOptionsUrl}}" download="{{OutputOptions}}">Download JSON</a></li>
152+
</ul>
153+
</div>
125154
<button type="button" class="btn btn-sm btn-info w-100" disabled>Image To Image</button>
126155
</div>
127156
</div>
@@ -135,14 +164,14 @@
135164
136165
const stableDiffusionTextToImage = () => {
137166
167+
let diffusionProcess;
138168
const optionsForm = $("#TextToImageParameters")
139169
const outputContainer = $("#output-container");
170+
const outputContainerGrid = $("#output-container-grid");
140171
const progressResultTemplate = $("#progressResultTemplate").html();
141172
const outputResultTemplate = $("#outputResultTemplate").html();
142173
const connection = new signalR.HubConnectionBuilder().withUrl("/StableDiffusionHub").build();
143174
144-
let diffusionProcess;
145-
146175
const onResponse = (response) => {
147176
if (!response)
148177
return;
@@ -167,18 +196,17 @@
167196
168197
const onCanceled = (response) => {
169198
console.log(response);
170-
outputContainer.html('');
199+
updatePlaceholderImage();
171200
processEnd();
172201
}
173202
174203
const executeTextToImage = async () => {
175-
176204
const diffusionParams = serializeFormToJson(optionsForm);
177205
if (!validateForm())
178206
return;
179207
180208
processBegin();
181-
outputContainer.html(Mustache.render(progressResultTemplate));
209+
updatePlaceholderImage();
182210
diffusionProcess = await connection
183211
.stream("ExecuteTextToImage", diffusionParams)
184212
.subscribe({
@@ -193,13 +221,47 @@
193221
}
194222
195223
const updateResultImage = (response) => {
196-
outputContainer.html(Mustache.render(outputResultTemplate, response));
224+
const width = getWidth();
225+
const height = getHeight();
226+
227+
const size = getSafeSize(width, height, 512);
228+
outputContainer.html(Mustache.render(outputResultTemplate, {
229+
width: size.width,
230+
height: size.height,
231+
...response
232+
}));
233+
234+
const gridSize = getSafeSize(width, height, 256);
235+
outputContainerGrid.find(".output-progress").remove();
236+
outputContainerGrid.prepend(Mustache.render(outputResultTemplate, {
237+
width: gridSize.width,
238+
height: gridSize.height,
239+
...response
240+
}));
241+
}
242+
243+
const updatePlaceholderImage = () => {
244+
const width = getWidth();
245+
const height = getHeight();
246+
247+
const size = getSafeSize(width, height, 512);
248+
outputContainer.html(Mustache.render(progressResultTemplate, {
249+
width: size.width,
250+
height: size.height,
251+
}));
252+
253+
const gridSize = getSafeSize(width, height, 256);
254+
outputContainerGrid.find(".output-progress").remove();
255+
outputContainerGrid.prepend(Mustache.render(progressResultTemplate, {
256+
width: gridSize.width,
257+
height: gridSize.height,
258+
}));
197259
}
198260
199261
const updateProgress = (response) => {
200262
const increment = Math.max(100 / response.total, 1);
201263
const progressPercent = Math.round(Math.min(increment * response.progress, 100), 0);
202-
const progressBar = $("#progress-result");
264+
const progressBar = $(".progress-result");
203265
progressBar.css("width", progressPercent + "%");
204266
progressBar.text(progressPercent + "%");
205267
}
@@ -219,6 +281,67 @@
219281
return optionsForm.valid();
220282
}
221283
284+
const clearHistory = () => {
285+
outputContainer.empty();
286+
outputContainerGrid.empty();
287+
updatePlaceholderImage();
288+
}
289+
290+
const getLayout = () => {
291+
return $("option:selected", "#result-layout").val();
292+
}
293+
294+
const getWidth = () => {
295+
return +$("option:selected", "#Options_Width").val();
296+
}
297+
298+
const getHeight = () => {
299+
return +$("option:selected", "#Options_Height").val();
300+
}
301+
302+
const updateLayout = () => {
303+
const layout = getLayout();
304+
if (layout == "Single") {
305+
outputContainer.removeClass("d-none").addClass("d-flex");
306+
outputContainerGrid.removeClass("d-flex").addClass("d-none");
307+
updatePlaceholderImage();
308+
}
309+
else if (layout == "Multiple") {
310+
outputContainer.removeClass("d-flex").addClass("d-none");
311+
outputContainerGrid.removeClass("d-none").addClass("d-flex");
312+
}
313+
}
314+
315+
const getSafeSize = (width, height, max) => {
316+
let largest = Math.max(width, height);
317+
if (largest > max) {
318+
while (largest > max) {
319+
largest -= 16;
320+
}
321+
322+
const delta = Math.max(width, height) / largest;
323+
return {
324+
width: width / delta,
325+
height: height / delta
326+
};
327+
}
328+
else if (largest < max) {
329+
while (largest < max) {
330+
largest += 16;
331+
}
332+
333+
const delta = largest - Math.max(width, height);
334+
return {
335+
width: width + delta,
336+
height: height + delta
337+
};
338+
}
339+
return {
340+
width: width,
341+
height: height
342+
};
343+
}
344+
222345
const serializeFormToJson = (form) => {
223346
const formDataJson = {};
224347
const formData = new FormData(document.getElementById(form.attr("id")));
@@ -244,7 +367,9 @@
244367
245368
246369
$(".btn-cancel").on("click", cancelDiffusion);
370+
$("#btn-clear").on("click", clearHistory);
247371
$("#btn-txt2img-execute").on("click", executeTextToImage);
372+
$("#result-layout").on("change", updateLayout).trigger("change");
248373
$(".slider").on("input", function (e) {
249374
const slider = $(this);
250375
slider.next().text(slider.val());
-44.3 KB
Binary file not shown.

0 commit comments

Comments
 (0)