File size: 3,741 Bytes
838b286
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
551a5ac
 
 
 
 
838b286
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fd7fe93
9584e7a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fd7fe93
9584e7a
 
 
838b286
9584e7a
838b286
 
551a5ac
838b286
9584e7a
fd7fe93
9584e7a
838b286
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<script lang="ts">
	let canvas: HTMLCanvasElement;
	import { API } from '../data';
	import { nanoid } from 'nanoid';
	import type { Params } from '../types';

	import {
		selectedParams,
		generateHuman,
		currentCanvas,
		resultImage,
		saveResult
	} from '$lib/store';

	$: (async () => {
		if ($generateHuman) {
			const results = await predict($currentCanvas.toDataURL(), $selectedParams);
			if (results) {
				$resultImage = results.data[0];
			}
			$generateHuman = false;
		}
	})();

	$: (async () => {
		if ($saveResult) {
			const results = await saveImage($resultImage);
			$saveResult = false;
		}
	})();

	let predictStatus: string = '';
	async function saveImage(base64Image: string) {
		return new Promise((resolve, reject) => {
			try {
				const a = document.createElement('a');
				a.download = `sucess-${Date.now()}.png`;
				a.target = '_self';
				a.onclick = async (e) => {
					if (a.href) {
						URL.revokeObjectURL(a.href);
					}
					a.href = base64Image;
				};
				requestAnimationFrame(() => {
					console.log('Downloading image.');
					a.click();
					resolve(null);
				});
			} catch (err) {
				reject();
			}
		});
	}
	async function predict(base64Image: string, { texture, steps, seed }: Params) {
		const session = nanoid(11);
		let hash, queue_position;
		let b = 0;
		predictStatus = 'Generating';
		const controller = new AbortController();
		// invalidation.then(() => {
		// 	controller.abort();
		// });
		await fetch(API + '/api/queue/push/', {
			signal: controller.signal,
			headers: { 'Content-Type': 'application/json' },
			method: 'POST',
			body: JSON.stringify({
				fn_index: 2,
				data: [base64Image, texture, steps, Number(seed)],
				action: 'predict',
				session_hash: session
			})
		})
			.then(async (res) => {
				const data = await res.json();
				({ hash, queue_position } = data);
			})
			.catch((err) => {
				console.log(err);
			});

		let timeout = 0;
		let status, data;
		while (status !== 'QUEUED' || status !== 'PENDING') {
			try {
				const resp = await fetch(API + '/api/queue/status/', {
					signal: controller.signal,
					headers: { 'Content-Type': 'application/json' },
					method: 'POST',
					body: JSON.stringify({ hash: hash })
				});
				if (resp.status != 200) {
					break;
				}
				({ status, data } = await resp.json());
				if (status === 'QUEUED') {
					predictStatus = `Queue ${data}/${queue_position}`;
				} else if (status === 'PENDING') {
					predictStatus = 'Pending';
				} else if (status === 'FAILED') {
					predictStatus = 'Failed';
					break;
				} else if (status === 'COMPLETE') {
					predictStatus = 'Complete';
					break;
				}
				await new Promise((resolve) => setTimeout(resolve, 1000));
			} catch (error) {
				console.log(error);
				break;
			}
		}
		return data;
	}
</script>

<div class="relative overflow-clip flex flex-col justify-center items-center w-full h-full">
	{#if $resultImage}
		<img
			class="image {$generateHuman ? 'opacity-30' : ''}"
			alt="Generative Human Result"
			src={$resultImage}
			width="256"
			height="512"
		/>
	{/if}
	{#if $generateHuman}
		<div class="loading">
			<svg
				xmlns="http://www.w3.org/2000/svg"
				fill="none"
				viewBox="0 0 24 24"
				class="animate-spin max-w-[3rem]"
			>
				<path
					fill="currentColor"
					d="M20 12a8 8 0 0 1-8 8v4a12 12 0 0 0 12-12h-4Zm-2-5.3a8 8 0 0 1 2 5.3h4c0-3-1.1-5.8-3-8l-3 2.7Z"
				/>
			</svg>
			<span class="text-xs">{predictStatus}</span>
		</div>
	{/if}
</div>

<!-- {/if} -->
<style lang="postcss" scoped>
	.image {
		@apply box-border z-0 border dark:border-gray-300 border-gray-500 aspect-[256/512];
	}
	.loading {
		@apply absolute top-0 left-0 right-0 bottom-0 flex flex-col justify-center items-center;
	}
</style>