File size: 10,074 Bytes
cb1edc7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b80b314
cb1edc7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62d33e5
cb1edc7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d07eaa9
cb1edc7
 
 
 
b80b314
 
 
 
 
 
 
 
 
 
 
 
 
d34c69a
b80b314
 
 
 
 
 
 
 
 
 
 
 
 
 
cb1edc7
 
 
 
 
 
 
 
 
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
<!DOCTYPE html>
<html>
<head>
    <title>React API Request Form</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
    function App() {
        const [apiEndpoint, setApiEndpoint] = React.useState('https://cvs65it9x6ibiiep.us-east-1.aws.endpoints.huggingface.cloud');
        const [huggingFaceToken, setHuggingFaceToken] = React.useState('');
        const [prompt, setPrompt] = React.useState('');
        const [desiredOutputWidth, setDesiredOutputWidth] = React.useState('512');
        const [text2ImgInferenceSteps, setText2ImgInferenceSteps] = React.useState('50');
        const [img2imgInferenceSteps, setImg2imgInferenceSteps] = React.useState('50');
        const [Text2ImgGuidanceScale, setText2ImgGuidanceScale] = React.useState('7.14');
        const [img2ImgStrength, setImg2ImgStrength] = React.useState('0.6');
        const [error, setError] = React.useState('');
        const [loading, setLoading] = React.useState(false);
        const [imageSrc, setImageSrc] = React.useState(null);
        const [loadingText, setLoadingText] = React.useState("Loading");
        const [previewMode, setPreviewMode] = React.useState("Half-Drop");
        React.useEffect(() => {
            let interval;

            if (loading) {
                interval = setInterval(() => {
                    setLoadingText(prev => prev.length < 10 ? prev + "." : "Loading");
                }, 500); // Update every 500 milliseconds
            }

            return () => clearInterval(interval);
        }, [loading]);

        const sendRequest = (event) => {
            event.preventDefault();
            setError('');
            setLoading(true);

            fetch(apiEndpoint, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    Authorization: `Bearer ${huggingFaceToken}`
                },
                body: JSON.stringify({
                    inputs: prompt,
                    desired_output_width: desiredOutputWidth,
                    text2img_inference_steps: text2ImgInferenceSteps,
                    img2img_inference_steps: img2imgInferenceSteps,
                    text2img_guidance_scale: Text2ImgGuidanceScale,
                    img2img_strength: img2ImgStrength
                })
            })
                .then(response => response.json())
                .then(data => {
                    if (data.error) {
                        setError(data.error)
                    } else {
                        setImageSrc('data:image/jpeg;base64,' + data.image);
                    }
                })
                .catch(error => {
                    console.error('Error:', error);
                }).finally(() => {
                setLoading(false);
            });
        };

        return (
            <div className="grid grid-cols-2 h-screen">
                <form onSubmit={sendRequest} className="grid cols-1 max-w-6xl bg-gray-100 h-full p-10 overflow-scroll">
                    <img src="./pipeline.png"/>
                    {error ? <div className="bg-red-200 py-2 px-3 rounded-md mb-4">
                        <strong className="text-bold">Error: </strong>
                        {error}
                    </div> : null}
                    <label className="block text-sm font-medium text-gray-700 cols-1">Inference Endpoint URL:</label>
                    <input
                        type="text"
                        value={apiEndpoint}
                        onChange={(e) => setApiEndpoint(e.target.value)}
                        className="mb-6 p-2 border border-gray-300 rounded"
                    />
                    <label className="block text-sm font-medium text-gray-700 cols-1">Hugging Face Token:</label>
                    <p className="text-xs">Without "Bearer " prefix, e.g.
                        "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":</p>
                    <input
                        type="text"
                        value={huggingFaceToken}
                        onChange={(e) => setHuggingFaceToken(e.target.value)}
                        className="mb-6 p-2 border border-gray-300 rounded"
                    />
                    <label className="block text-sm font-medium text-gray-700">Prompt:</label>
                    <input
                        type="text"
                        value={prompt}
                        onChange={(e) => setPrompt(e.target.value)}
                        className="mb-6 p-2 border border-gray-300 rounded"
                    />
                    <label className="block text-sm font-medium text-gray-700">Desired Output Width:</label>
                    <p className="text-xs">The desired width of the final half-drop. Because of rounding during the
                        process,
                        the generator will try to get as close to this as possible, but may be off by a few pixels.</p>
                    <input
                        type="number"
                        value={desiredOutputWidth}
                        onChange={(e) => setDesiredOutputWidth(e.target.value)}
                        className="mb-6 p-2 border border-gray-300 rounded"
                    />
                    <label className="block text-sm font-medium text-gray-700">Text2Img Inference Steps:</label>
                    <p className="text-xs">The number of steps to take when generating the original image.</p>
                    <input
                        type="number"
                        value={text2ImgInferenceSteps}
                        onChange={(e) => setText2ImgInferenceSteps(e.target.value)}
                        className="mb-6 p-2 border border-gray-300 rounded"
                    />
                    <label className="block text-sm font-medium text-gray-700">Img2Img Inference Steps:</label>
                    <p className="text-xs">The number of steps to take when converting the extracted diamond into a
                        tile.</p>
                    <input
                        type="number"
                        value={img2imgInferenceSteps}
                        onChange={(e) => setImg2imgInferenceSteps(e.target.value)}
                        className="mb-6 p-2 border border-gray-300 rounded"
                    />
                    <label className="block text-sm font-medium text-gray-700">Text2Img Guidance Scale:</label>
                    <p className="text-xs">Guidance scale for the original image generation. The pipeline default is
                        5.</p>
                    <input
                        type="number"
                        value={Text2ImgGuidanceScale}
                        onChange={(e) => setText2ImgGuidanceScale(e.target.value)}
                        className="mb-6 p-2 border border-gray-300 rounded"
                    />
                    <label className="block text-sm font-medium text-gray-700">Img2Img Strength:</label>
                    <p className="text-xs">Strength to use when converting the diamond into a repeatable tile, i.e. how
                        much
                        it can vary from the original generation. Pipeline default is</p>
                    <input
                        type="number"
                        value={img2ImgStrength}
                        onChange={(e) => setImg2ImgStrength(e.target.value)}
                        className="mb-6 p-2 border border-gray-300 rounded"
                    />

                    <input
                        type="submit"
                        value="Generate"
                        className="mt-2 p-2 bg-blue-500 text-white rounded hover:bg-blue-700"
                    />
                </form>
                <div className="p-10 overflow-scroll">
                    {loading && <p className="mb-8">{loadingText}</p>}
                    {imageSrc && (
                        <>
                            <label htmlFor="pattern-dropdown" className="mr-2">Pattern:</label>
                            <select
                                id="pattern-dropdown"
                                value={previewMode}
                                onChange={(e) => setPreviewMode(e.target.value)}
                                className="border border-gray-300 rounded mb-10"
                            >
                                <option value="Half Drop">Half-Drop</option>
                                <option value="Half Drop Tiled">Half-Drop Tiled</option>
                            </select>
                            {previewMode !== "Half Drop Tiled" && <img src={imageSrc} alt="Response"/>}
                            {previewMode === "Half Drop Tiled" && <div className="grid grid-cols-3 h-full">
                                <div className="flex items-center justify-center">
                                    <img src={imageSrc} alt="Response"/>
                                </div>
                                <div className="flex flex-col items-center justify-center">
                                    <img src={imageSrc} alt="Response"/>
                                    <img src={imageSrc} alt="Response"/>
                                </div>
                                <div className="flex items-center justify-center">
                                    <img src={imageSrc} alt="Response"/>
                                </div>
                            </div>}
                        </>
                    )}
                </div>
            </div>
        );
    }

    ReactDOM.render(<App/>, document.getElementById('app'));
</script>
</body>
</html>